]> projects.mako.cc - selectricity-live/blob - app/models/election.rb
Merge trunk
[selectricity-live] / 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 initialize(params={})
19     super
20     self.enddate = read_attribute( :enddate ) || \
21                    Time.now + 14.days - 1.second
22   end
23
24   def other_methods
25     if election_method
26       @other_methods = ELECTION_TYPES.reject {|i| i == election_method}
27     else
28       @other_methods = nil
29     end
30     @other_methods
31   end
32
33   def startdate
34     read_attribute( :startdate ) || Time.now
35   end
36
37   def enddate=(date)
38     date += 1.day
39     date = Time.gm(*date)
40     super(date)
41   end
42
43   def votes
44     votes = Array.new
45     self.voters.each do |voter|
46       votes << voter.vote
47     end
48     return votes
49   end
50
51   def destroy
52     self.candidates.each do |candidate|
53       candidate.destroy
54     end
55     super
56   end
57
58   def start_blockers
59     reasons = []
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?