+
+ #Calculate results if not in memcache
+ def results
+ # Assignment is intentional
+ if Cache and c = Cache.get("election_results:#{id}:#{self.votes.length}")
+ @plurality_result = c['plurality']
+ @approval_result = c['approval']
+ @condorcet_result = c['condorcet']
+ @ssd_result = c['ssd']
+ @borda_result = c['borda']
+ return c
+ elsif Cache
+ # memcache is available, but missed.
+ results = self.results!
+ Cache.set("election_results:#{id}:#{self.votes.length}", results)
+ return results
+ else
+ return self.results!
+ end
+ end
+
+ #Always Calculate Election Results
+ def results!
+ # initalize the tallies to empty arrays
+ preference_tally = Array.new
+ plurality_tally = Array.new
+ approval_tally = Array.new
+
+ self.voters.each do |voter|
+ # skip if the voter has not voted or has an unconfirmed vote
+ next unless voter.voted?
+
+ plurality_tally << voter.vote.rankings.sort[0].candidate_id
+ approval_tally << voter.vote.rankings.sort[0..1].collect \
+ { |ranking| ranking.candidate_id }
+ preference_tally << voter.vote.rankings.sort.collect \
+ { |ranking| ranking.candidate_id }
+ end
+
+ @plurality_result = PluralityVote.new(plurality_tally).result
+ @approval_result = ApprovalVote.new(approval_tally).result
+ @condorcet_result = PureCondorcetVote.new(preference_tally).result
+ @ssd_result = CloneproofSSDVote.new(preference_tally).result
+ @borda_result = BordaVote.new(preference_tally).result
+
+ { 'plurality' => @plurality_result,
+ 'approval' => @approval_result,
+ 'condorcet' => @condorcet_result,
+ 'ssd' => @ssd_result,
+ 'borda' => @borda_result }
+ end
+
+ def names_by_id
+ names = Hash.new
+
+ competitors = self.candidates.sort.collect {|candidate| candidate.id}
+ competitors.each do |candidate|
+ names[candidate] = Candidate.find(candidate).name
+ end
+
+ names
+ end
+
+ def candidate_hash
+ hash = {}
+ self.candidates.each {|c| hash[c.id] = c}
+ return hash
+ end
+
+
+ # TODO now that this code is in here, we should go ahead and remove
+ # date checking from other places in the code
+ def after_find
+ if self.active < 2 and self.enddate < Time.now
+ self.active = 2
+ self.save
+ end
+ end
+
+ def just_before_midnight(datetime)
+ if datetime.instance_of? DateTime
+ off = datetime.offset
+ else
+ off = Rational(datetime.utc_offset, 60*60*24)
+ end
+ return DateTime.new(datetime.year, datetime.month, datetime.day,
+ 23, 59, 59, off)
+ end
+
+ private
+ def enforce_constraints
+ # elections end just before midnight
+ self.enddate = just_before_midnight(self.enddate)
+ # kiosks can't be authenticated
+ self.authenticated = false if kiosk?
+ return true
+ end
+