From:
Date: Fri, 10 Aug 2007 22:47:33 +0000 (-0400)
Subject: Added a new bar graph, that counts how many points the borda system of
X-Git-Url: https://projects.mako.cc/source/selectricity-live/commitdiff_plain/09c67d9323c7d379d4c6de5dc0457b6de16cff14
Added a new bar graph, that counts how many points the borda system of
voting has asssigned to every candidate, it shows the margins fo victory
and loss clearly. Also had to make modifications to the RubyVote libary.
There was an error in BordaVote that prevented it from working correctly,
which has been fixed. Also added an attr_reader to BordaResult for
ranked_candidates. About to delete the Gruff Plugin v 0.1.2 and replace it
with Gruff gem v 0.2.8.
---
diff --git a/app/controllers/election_controller.rb b/app/controllers/election_controller.rb
index e950153..df0aa7c 100644
--- a/app/controllers/election_controller.rb
+++ b/app/controllers/election_controller.rb
@@ -196,15 +196,15 @@ class ElectionController < ApplicationController
if incoming_voters.email == 0
new_voter.contacted = 1
- elsif incoming_voters.email == 1
- email_voter( new_voter )
- new_voter.contacted = 1
- else
- new_voter.contacted = 0
- end
+ elsif incoming_voters.email == 1
+ email_voter( new_voter )
+ new_voter.contacted = 1
+ else
+ new_voter.contacted = 0
+ end
# the new voter should be in good shape. save add to the election
- new_voter.save
+ new_voter.save
@election.voters << new_voter
end
end
diff --git a/app/controllers/graph_controller.rb b/app/controllers/graph_controller.rb
index 9ab2a4c..7b593cc 100644
--- a/app/controllers/graph_controller.rb
+++ b/app/controllers/graph_controller.rb
@@ -11,21 +11,20 @@ class GraphController < ApplicationController
line.font = File.expand_path('/usr/X11R6/lib/X11/fonts/TTF/Vera.ttf',
RAILS_ROOT)
- line.data("#{@election.name}", data )
+ line.data( "#{@election.name}", data )
line.labels = labels
line.x_axis_label = "Date"
line.y_axis_label = "Number of Votes"
line.minimum_value = 0.0
- line.draw
send_data(line.to_blob, :disposition => 'inline', :type => 'image/png')
end
#will place votes in a fixed number of intervals, and shows votes over time
def votes_per_interval
@election = Election.find(params[:id])
- data, labels = get_votes_per_interval_data(@election)
+ data, labels, scale = get_votes_per_interval_data(@election)
line = Gruff::Line.new("700x400")
line.theme = { :background_colors => ['#73BF26', '#ffffff'] }
@@ -36,11 +35,10 @@ class GraphController < ApplicationController
line.data("#{@election.name}", data )
line.labels = labels
- line.x_axis_label = "Intervals"
+ line.x_axis_label = scale
line.y_axis_label = "Number of Votes"
line.minimum_value = 0.0
- line.draw
send_data(line.to_blob, :disposition => 'inline', :type => 'image/png')
end
@@ -50,19 +48,28 @@ class GraphController < ApplicationController
def borda_bar
@election = Election.find(params[:id])
+ pref_tally = make_preference_tally(@election)
+
+ @borda_result = BordaVote.new(pref_tally).result
+ data, labels = get_borda_points(@borda_result)
- #Get the list of candidates from the election, and calculate how RubyVote
- #gave each one points
- @election.candidates.each do |candidate|
+ bar = Gruff::Bar.new("700x400")
+ bar.theme = { :background_colors => ['#73BF26', '#ffffff'] }
+ bar.title = "Points Per Candidate"
+ bar.font = File.expand_path('/usr/X11R6/lib/X11/fonts/TTF/Vera.ttf',
+ RAILS_ROOT)
+
+ bar.data("#{@election.name}", data)
+ bar.labels = labels
- #Tabulate how many points each candidate received
- #Make the name of each candidate a label under the correspoding column
- #done!
+ bar.y_axis_label = "Points"
+ bar.x_axis_label = "Candidate"
+ bar.minimum_value = 0.0
+ send_data(bar.to_blob, :disposition => 'inline', :type => 'image/png')
end
-
private
-
+
# generate the data and labels for each graph
def get_votes_per_day_data(election)
voter_days = Array.new
@@ -111,6 +118,7 @@ class GraphController < ApplicationController
labels_hash = Hash.new
buckets = Hash.new
total_per_interval = Array.new
+ interval_type = ""
starttime = election.startdate
timedelta = Time.now - starttime
@@ -142,18 +150,52 @@ class GraphController < ApplicationController
labels_hash[0] = starttime.min.to_s
labels_hash[(numcols/2)-1] = (starttime + (timedelta/2)).min.to_s
labels_hash[numcols-1] = Time.now.min.to_s
+ interval_type = "Minutes"
elsif timedelta < 2.days #more than 2 hours means use hours for labels
labels_hash[0] = starttime.hour.to_s
labels_hash[(numcols/2)-1] = (starttime + (timedelta/2)).hour.to_s
labels_hash[numcols-1] = Time.now.hour.to_s
+ interval_type = "Hours"
else #more than 2 days means use dates for labels
labels_hash[0] = (Date.parse(starttime.to_s)).to_s
labels_hash[(numcols/2)-1] = (Date.parse(starttime + (timedelta/2))).to_s
labels_hash[numcols-1] = (Date.today).to_s
+ interval_type = "Days"
end
# Make sure to return an array for data and hash for labels
- return total_per_interval, labels_hash
+ return total_per_interval, labels_hash, interval_type
+ end
+
+ def get_borda_points(result)
+ #points holds how mnay points each candidate has received in array form
+ #becasue Gruff::Bar#data takes only an array
+ points = Array.new
+ labels = Hash.new
+
+ #Populate points with an sorted array from election.votes hash
+ #biggest to smallest will go from left to right
+ points = result.election.votes.sort do |a, b|
+ b[1] <=> a[1]
+ end.collect {|i| i[1]}
+
+ #make the labels
+ result.ranked_candidates.each_with_index do |candidate, index|
+ labels[index] = Candidate.find(candidate).name
+ end
+
+ return points, labels
+ end
+
+ #most vote result objects require an array of vote arrays, which this will make
+ def make_preference_tally(election)
+ preference_tally = Array.new
+ @election.voters.each do |voter|
+ next unless voter.voted?
+ preference_tally << voter.vote.rankings.sort.collect \
+ { |ranking| ranking.candidate.id }
+ end
+ return preference_tally
end
end
diff --git a/app/controllers/quickvote_controller.rb b/app/controllers/quickvote_controller.rb
index d842f63..0b745af 100644
--- a/app/controllers/quickvote_controller.rb
+++ b/app/controllers/quickvote_controller.rb
@@ -63,7 +63,7 @@ class QuickvoteController < ApplicationController
# if the voter has not voted we destroy them
if @voter and not @voter.voted?
@voter.destroy
- @voter = nil
+ @voter = nil
end
# if the voter does not exist or has has been destroyed, lets
@@ -73,12 +73,12 @@ class QuickvoteController < ApplicationController
@voter = QuickVoter.new
@voter.election = QuickVote.find_all( [ "name = ?", params[:votename] ] )[0]
@voter.session_id = session.session_id
-
- # create new vote and make it the defaulted sorted list
+
+ # create new vote and make it the defaulted sorted list
@voter.vote = Vote.new
- @voter.save
- @voter.vote.set_defaults!
- @voter.reload
+ @voter.save
+ @voter.vote.set_defaults!
+ @voter.reload
end
else
redirect_to :controller => 'site'
@@ -91,14 +91,14 @@ class QuickvoteController < ApplicationController
# find out who the voter is for this election
@voter = QuickVoter.find_all(["session_id = ? and election_id = ?",
- session.session_id, election.id])[0]
-
+ session.session_id, election.id])[0]
+
if not @voter
# we have not seen this voter before. something is wrong, try
# again
redirect_to quickvote_url( :votename => params[:votename] )
- elsif @voter.voted?
+ elsif @voter.voted?
# this person has already voted, we try again
flash[:notice] = "You have already voted!"
redirect_to quickvote_url( :votename => params[:votename] )
@@ -108,8 +108,7 @@ class QuickvoteController < ApplicationController
@voter.ipaddress = request.env["REMOTE_ADDR"]
@voter.save
- # save the time the vote was made for statistical use, it doesn't
- #work here unless I use a method that will save it to the db
+ # save the time the vote was made for statistical use
@voter.vote.time = Time.now
# toggle the confirmation bit
@@ -143,7 +142,7 @@ class QuickvoteController < ApplicationController
###############################################################
def results
- @election = QuickVote.find_all( ["name = ?", params[:votename]] )[0]
+ @election = QuickVote.find_all(["name = ?", params[:votename]] )[0]
# initalize the tallies to empty arrays
preference_tally = Array.new
diff --git a/app/controllers/site_controller.rb b/app/controllers/site_controller.rb
index e86624e..a33a1fa 100644
--- a/app/controllers/site_controller.rb
+++ b/app/controllers/site_controller.rb
@@ -16,7 +16,7 @@ class SiteController < ApplicationController
b.enddate <=> a.enddate
end
else
- # if we have no record of them, set the session id back to
+ # if we have no record of them, set the user back to
# nothing and start again
session[:user] = nil
diff --git a/app/views/quickvote/results.rhtml b/app/views/quickvote/results.rhtml
index 030d246..5fdfc3c 100644
--- a/app/views/quickvote/results.rhtml
+++ b/app/views/quickvote/results.rhtml
@@ -163,7 +163,7 @@ by several other names.
<%= image_tag( graph_url( :action => 'votes_per_day', :id => @election ) ) %>
-<%= image_tag( graph_url(:action => 'votes_per_interval', :id => @election)) %>
-
+<%= image_tag( graph_url( :action => 'votes_per_interval', :id => @election ))%>
+<%= image_tag( graph_url( :action => 'borda_bar', :id => @election ) ) %>
diff --git a/lib/rubyvote/positional.rb b/lib/rubyvote/positional.rb
index 11e8a49..3de3fb2 100644
--- a/lib/rubyvote/positional.rb
+++ b/lib/rubyvote/positional.rb
@@ -42,7 +42,12 @@ class BordaVote < ElectionVote
def tally_vote(vote)
points = candidates.length - 1
vote.each do |candidate|
- @votes[candidate] = points
+ #if the candidate exist, add the points, otherwise assign them
+ if @votes.has_key?(candidate)
+ @votes[candidate] += points
+ else
+ @votes[candidate] = points
+ end
points -= 1
end
end
@@ -58,6 +63,8 @@ class BordaVote < ElectionVote
end
class BordaResult < ElectionResult
+ attr_reader :ranked_candidates
+
def initialize(voteobj=nil)
super(voteobj)
votes = @election.votes