3 class InstantRunoffVote < ElectionVote
4 def initialize(votes=nil)
5 @candidates = Array.new
7 @candidates = vote.uniq if vote.uniq.length > candidates.length
10 @candidates.each do |candidate|
11 @votes[candidate] = [0, Hash.new] unless @votes.has_key?(candidate)
16 InstantRunoffResult.new(self)
22 candidate = votecopy.shift
23 votes[candidate] = [0, Hash.new] unless votes.has_key?(candidate)
24 votes[candidate][0] += 1
25 if votes[candidate][1].has_key?(votecopy)
26 votes[candidate][1][votecopy] += 1
28 votes[candidate][1][votecopy] = 1
32 def verify_vote(vote=nil)
33 vote.instance_of?( Array ) and
38 class InstantRunoffResult < ElectionResult
39 attr_reader :ranked_candidates
41 def initialize(voteobj=nil)
42 unless voteobj and voteobj.kind_of?( InstantRunoffVote )
43 raise ArgumentError, "You must pass an InstantRunoffVote array.", caller
47 votes = @election.votes.clone
48 candidates = @election.candidates
49 majority = votes.inject(0) {|n, value| n + value[1][0]}/2 + 1
50 @ranked_candidates = Array.new()
51 ranked_candidates = Array.new()
54 ranked_candidates = votes.sort do |a, b|
56 end.collect {|i| i[0]}
57 @winners = ranked_candidates.find_all do |i|
58 votes[i][0] >= majority
61 loser = ranked_candidates[-1]
62 break if self.winner? or votes[loser][0] == votes[ranked_candidates[-2]][0]
64 @ranked_candidates.unshift(loser)
67 @ranked_candidates.unshift(*ranked_candidates)
70 def runoff(votes, loser)
71 votes.each_pair do |candidate, morevotes|
73 hash.each_pair do |vote, count|
79 votes[loser][1].each_pair do |vote, count|
80 candidate = vote.shift
81 votes[candidate][0] += count
82 if votes[candidate][1].has_key?(vote)
83 votes[candidate][1][vote] += count
85 votes[candidate][1][vote] = count