+++ /dev/null
-# election library -- a ruby library for elections
-# copyright © 2005 MIT Media Lab and Benjamin Mako Hill
-
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
-# 02110-1301, USA.
-
-#################################################################
-## ==== election.rb ====
-##
-## This file contains the core ElectionVote and ElectionResults
-## classes and the most common and simple election methods including
-## plurality and approval voting.
-#################################################################
-
-##################################################################
-## ElectionVote Classes and SubClasses
-##
-## There classes are used to store, verify, and "tally" (i.e. count
-## votes for the standard Election superclass and for the most common
-## types of elections.
-
-class ElectionVote
- attr_reader :votes
- attr_reader :candidates
-
- def initialize(votes=nil)
- @votes = Hash.new unless defined?(@votes)
- @candidates = Array.new unless defined?(@candidates)
-
- if votes
- if votes.instance_of?( Array )
- votes.each do |vote|
- self.tally_vote(vote) if self.verify_vote(vote)
- end
- else
- raise ElectionError, "Votes must be in the form of an array.", caller
- end
- end
- end
-
- protected
- # by default, this is set to look if the vote is defined. it should
- # be overridden in each class
- def verify_vote(vote=nil)
- vote ? true : false
- end
-
- # by default, this does nothing. it must be redefined in any subclass
- def tally_vote
- self.verify_vote(vote)
- end
-end
-
-class PluralityVote < ElectionVote
- def result
- PluralityResult.new(self)
- end
-
- protected
- def verify_vote(vote=nil)
- vote.instance_of?( String )
- end
-
- def tally_vote(candidate)
- if @votes.has_key?(candidate)
- @votes[candidate] += 1
- else
- @votes[candidate] = 1
- @candidates << candidate
- end
- end
-end
-
-class ApprovalVote < PluralityVote
- def result
- ApprovalResult.new(self)
- end
-
- protected
- def verify_vote(vote=nil)
- vote.instance_of?( Array ) and vote.length >= 1
- end
-
- def tally_vote(approvals)
- approvals.each {|candidate| super(candidate)}
- end
-end
-
-
-##################################################################
-## Election Result Classes
-##
-
-## There classes are used to compute and report the results of an
-## election. In almost all cases, these will be returned by the
-## #results method of a corresponding ElectionVote subclass.
-
-class ElectionResult
- attr_reader :winners
-
- def initialize(voteobj=nil)
- unless voteobj and voteobj.kind_of?( ElectionVote )
- raise ArgumentError, "You must pass a ElectionVote array.", caller
- end
-
- @election = voteobj
- @winners = Array.new
- end
-
- def winner
- @winners[0] if @winners.length > 0
- end
-
- def winner?
- @winners.length > 0
- end
-
-end
-
-class PluralityResult < ElectionResult
- attr_reader :ranked_candidates
-
- def initialize(voteobj=nil)
- super(voteobj)
-
- votes = @election.votes
- candidates = @election.candidates
-
- @ranked_candidates = votes.sort do |a, b|
- b[1] <=> a[1]
- end.collect {|a| a[0]}
-
- # winners are anyone who has the same number of votes as the
- # first person
- @winners = @ranked_candidates.find_all do |i|
- votes[i] == votes[@ranked_candidates[0]]
- end
- end
-end
-
-# this class is complete because results for approval are computed
-# identically to results from plurality
-class ApprovalResult < PluralityResult
-end
-
-class ElectionError < ArgumentError
-end
-