Made the results page 'modular,' and all the necessary adaptations.
[selectricity] / app / models / election.rb
1 class Election < ActiveRecord::Base
2   has_many :candidates
3   has_many :voters
4   has_many :votes
5   belongs_to :user
6   validates_presence_of :name, :description
7   
8   #validate that method is one of the listed election types
9   
10   attr_reader :plurality_result
11   attr_reader :approval_result
12   attr_reader :condorcet_result
13   attr_reader :ssd_result
14   attr_reader :borda_result
15   
16   require 'date'
17   
18   def other_methods
19     if election_method
20       @other_methods = ELECTION_TYPES.reject {|i| i == election_method}
21     else
22       @other_methods = nil
23     end
24     @other_methods
25   end
26
27   def startdate
28     read_attribute( :startdate ) || Time.now
29   end
30   
31   def enddate
32     date = read_attribute( :enddate ) || Time.now + 14
33     date - 1.second
34   end
35
36   def enddate=(date)
37     date += 1.day
38     date = Time.gm(*date)
39     super(date)
40   end
41
42   def votes
43     votes = Array.new
44     self.voters.each do |voter|
45       votes << voter.vote
46     end
47     return votes
48   end
49
50   def destroy
51     self.candidates.each do |candidate|
52       candidate.destroy
53     end
54     super
55   end
56
57   def start_blockers
58     reasons = []
59     
60     if self.candidates.length <= 1
61       reasons << "You must have at least two candidates."
62     end
63     
64     if self.voters.length <= 1
65       reasons << "You must have at least two voters."
66     end
67
68     reasons
69   end
70
71   def activate!
72     self.active = 1
73     self.save!
74   end
75   
76   def quickvote?
77     self.class == 'QuickVote'
78   end
79
80   def active?
81     active == 1
82   end 
83
84   def done?
85     active == 2
86   end
87
88   def shortdesc
89     shortdesc = description.split(/\n/)[0]
90   end
91
92   def longdesc
93     longdesc = description.split(/\n/)[1..-1].join("")
94     longdesc.length > 0 ? longdesc : nil 
95   end
96   
97   #Calculate Election Results
98   def results
99     # initalize the tallies to empty arrays
100     preference_tally = Array.new
101     plurality_tally = Array.new
102     approval_tally = Array.new
103
104     self.voters.each do |voter|
105       # skip if the voter has not voted or has an unconfirmed vote
106       next unless voter.voted?
107
108       plurality_tally << voter.vote.rankings.sort[0].candidate.id
109       approval_tally << voter.vote.rankings.sort[0..1].collect \
110         { |ranking| ranking.candidate.id }
111       preference_tally << voter.vote.rankings.sort.collect \
112         { |ranking| ranking.candidate.id }
113     end
114     
115     @plurality_result = PluralityVote.new(plurality_tally).result
116     @approval_result = ApprovalVote.new(approval_tally).result
117     @condorcet_result = PureCondorcetVote.new(preference_tally).result
118     @ssd_result = CloneproofSSDVote.new(preference_tally).result
119     @borda_result = BordaVote.new(preference_tally).result
120     
121     { 'plurality' => @plurality_result,
122       'approval' => @approval_result,
123       'condorcet' => @condorcet_result,
124       'ssd' => @ssd_result,
125       'borda' => @borda_result }
126     end
127   
128   def names_by_id
129     names = Hash.new
130     
131     competitors = self.candidates.sort.collect {|candidate| candidate.id}
132     competitors.each do |candidate|
133       names[candidate] = Candidate.find(candidate).name
134     end
135     
136     names
137   end
138   
139 end
140
141

Benjamin Mako Hill || Want to submit a patch?