1 class InstantRunoffVote < ElectionVote
2 def initialize(votes=nil)
3 @candidates = Array.new
5 @candidates = vote.uniq if vote.uniq.length > candidates.length
8 @candidates.each do |candidate|
9 @votes[candidate] = [0, Hash.new] unless @votes.has_key?(candidate)
14 InstantRunoffResult.new(self)
20 candidate = votecopy.shift
21 votes[candidate] = [0, Hash.new] unless votes.has_key?(candidate)
22 votes[candidate][0] += 1
23 if votes[candidate][1].has_key?(votecopy)
24 votes[candidate][1][votecopy] += 1
26 votes[candidate][1][votecopy] = 1
30 def verify_vote(vote=nil)
31 vote.instance_of?( Array ) and
36 class InstantRunoffResult < ElectionResult
37 attr_reader :ranked_candidates
39 def initialize(voteobj=nil)
40 unless voteobj and voteobj.kind_of?( InstantRunoffVote )
41 raise ArgumentError, "You must pass an InstantRunoffVote array.", caller
45 votes = @election.votes.clone
46 candidates = @election.candidates
47 majority = votes.inject(0) {|n, value| n + value[1][0]}/2 + 1
48 @ranked_candidates = Array.new()
49 ranked_candidates = Array.new()
52 ranked_candidates = votes.sort do |a, b|
54 end.collect {|i| i[0]}
55 @winners = ranked_candidates.find_all do |i|
56 votes[i][0] >= majority
59 loser = ranked_candidates[-1]
60 break if self.winner? or votes[loser][0] == votes[ranked_candidates[-2]][0]
62 @ranked_candidates.unshift(loser)
65 @ranked_candidates.unshift(*ranked_candidates)
68 def runoff(votes, loser)
69 votes.each_pair do |candidate, morevotes|
71 hash.each_pair do |vote, count|
77 votes[loser][1].each_pair do |vote, count|
78 candidate = vote.shift
79 votes[candidate][0] += count
80 if votes[candidate][1].has_key?(vote)
81 votes[candidate][1][vote] += count
83 votes[candidate][1][vote] = count