From 924aa1ff433ac4ccd2db5851e91038088be00a09 Mon Sep 17 00:00:00 2001 From: Date: Wed, 15 Aug 2007 17:46:20 -0400 Subject: [PATCH] Modified graphs to ahve a 4 color scheme, but it isn't the full palette of selectricity yet , that will be on next commit. LAso modified several voting methods within RubyVote to have more useful instance variables and accessors available in the results class. the quickvote results view has been updated to include a partial for displaying a condorcet vote table, w hich is strangely appearing below the footer on the results page, it seems to be displaying the correct data however. --- .bzrignore | 1 + app/controllers/graph_controller.rb | 38 +++++++++++++++++---------- app/views/quickvote/_pref_table.rhtml | 19 ++++++++++++++ app/views/quickvote/results.rhtml | 4 +-- lib/rubyvote/condorcet.rb | 6 +++-- lib/rubyvote/election.rb | 5 +++- lib/rubyvote/positional.rb | 9 ++++--- 7 files changed, 60 insertions(+), 22 deletions(-) create mode 100644 app/views/quickvote/_pref_table.rhtml diff --git a/.bzrignore b/.bzrignore index 50c7c5b..1e24ca1 100644 --- a/.bzrignore +++ b/.bzrignore @@ -5,3 +5,4 @@ server.log test.log tmp public/engine_files +.DS_Store diff --git a/app/controllers/graph_controller.rb b/app/controllers/graph_controller.rb index 8256884..bbd5cd7 100644 --- a/app/controllers/graph_controller.rb +++ b/app/controllers/graph_controller.rb @@ -7,13 +7,19 @@ class GraphController < ApplicationController size = "700x400" @graph = options[:graph_type].new(size) - @graph.theme = { :background_colors => ['#73BF26', '#ffffff'] } + @graph.theme = { :colors => ['#000000', '#00FFFF', '#FFCC00', '#990033'], + :background_colors => ['#74ce00', '#ffffff'] } @graph.font = File.expand_path('/usr/X11R6/lib/X11/fonts/TTF/Vera.ttf', RAILS_ROOT) # fill in the data with the optional data name - #Check to see if multiple datasets, if so, fill them all! - if options[:data].size > 1 && options[:data].all? {|i| i.is_a?(Array)} + #Check to see if multiple datasets, if so, fill them all! + if options[:data].is_a?(Hash) + options[:data].each_pair do |name, array| + @graph.data( name, array) + end + #if each dataset nameless, will have only multiple arrays + elsif options[:data].size > 1 && options[:data].all? {|i| i.is_a?(Array)} options[:data].each do |array| @graph.data( options.fetch(:data_name, "Data"), array) end @@ -73,10 +79,10 @@ class GraphController < ApplicationController def borda_bar @election = Election.find(params[:id]) - pref_tally = make_preference_tally(@election) + #pref_tally = make_preference_tally(@election) - @borda_result = BordaVote.new(pref_tally).result - data, labels = get_borda_points(@borda_result) + #@borda_result = BordaVote.new(pref_tally).result + data, labels = get_borda_points(@election.borda_result) graph = GruffGraff.new( :graph_type => Gruff::Bar, :data_name => @election.name, @@ -87,16 +93,22 @@ class GraphController < ApplicationController :x_axis_label => "Candidate") send_data(*graph.output) end - - def choices_positions + #Acording to Tufte, small, concomparitive, highly labeled data sets usually + # belong in tables. The following is a bar graph...but would it be better + #as a table? + def choices_positions @election = Election.find(params[:id]) pref_tally = make_preference_tally(@election) fulldata, labels = get_positions_info(@election) - labels = @candidates + legend = Hash.new + + @election.candidates.each_with_index do |candidate, index| + legend[candidate.name] = fulldata[index] + end + graph = GruffGraff.new( :graph_type => Gruff::Bar, - :data_name => @election.name, - :data => fulldata, + :data => legend, :interval_labels => labels, :title => "Times Voted in Each Position", :y_axis_label => "Number of Times Ranked", @@ -133,7 +145,7 @@ class GraphController < ApplicationController rank_labels[i] = (i+1).to_s end end - + return buckets2.values, rank_labels end @@ -236,8 +248,6 @@ class GraphController < ApplicationController 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 diff --git a/app/views/quickvote/_pref_table.rhtml b/app/views/quickvote/_pref_table.rhtml new file mode 100644 index 0000000..dfcb6cc --- /dev/null +++ b/app/views/quickvote/_pref_table.rhtml @@ -0,0 +1,19 @@ +<% candidates = @election.candidates.sort.collect {|candidate| candidate.id} -%> + + + + <% candidates.each do |candidate| -%> + + <% end -%> +<% candidates.each do |winner| -%> + + + <% candidates.each do |loser| -%> + <% if winner == loser -%> + + <% else %> + + <% end -%> + <% end -%> + +<%end -%> \ No newline at end of file diff --git a/app/views/quickvote/results.rhtml b/app/views/quickvote/results.rhtml index 98a71e5..5626636 100644 --- a/app/views/quickvote/results.rhtml +++ b/app/views/quickvote/results.rhtml @@ -145,7 +145,6 @@ by several other names.

Voters

-
<%= candidate -%>
<%= winner %> -- <%= @election.condorcet_result.matrix[winner][loser] %>
@@ -168,8 +167,9 @@ by several other names.

<% end %>
IP Address
+<%= render :partial => 'pref_table' %> + <%= 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 => 'borda_bar', :id => @election ) ) %>
<%= image_tag( graph_url( :action => 'choices_positions', :id => @election ) ) %> - diff --git a/lib/rubyvote/condorcet.rb b/lib/rubyvote/condorcet.rb index aaa5044..bf4e548 100644 --- a/lib/rubyvote/condorcet.rb +++ b/lib/rubyvote/condorcet.rb @@ -32,7 +32,7 @@ ## the CloneproofSSDVote classes but should not be used directly. class CondorcetVote < ElectionVote - + attr_accessor :results def initialize(votes=nil) @@ -144,15 +144,17 @@ end ## directly. class CondorcetResult < ElectionResult + attr_reader :matrix + def initialize(voteobj=nil) unless voteobj and voteobj.kind_of?( CondorcetVote ) raise ArgumentError, "You must pass a CondorcetVote array.", caller end super(voteobj) + @matrix = voteobj.votes end protected - def defeats(candidates=nil, votes=nil) candidates = @election.candidates unless candidates votes = @election.votes unless votes diff --git a/lib/rubyvote/election.rb b/lib/rubyvote/election.rb index 42f18bb..efb8dd8 100644 --- a/lib/rubyvote/election.rb +++ b/lib/rubyvote/election.rb @@ -140,7 +140,8 @@ end class PluralityResult < ElectionResult attr_reader :ranked_candidates - + attr_reader :points + def initialize(voteobj=nil) super(voteobj) @@ -151,6 +152,8 @@ class PluralityResult < ElectionResult b[1] <=> a[1] end.collect {|a| a[0]} + @points = self.election.votes + # winners are anyone who has the same number of votes as the # first person @winners = @ranked_candidates.find_all do |i| diff --git a/lib/rubyvote/positional.rb b/lib/rubyvote/positional.rb index 3de3fb2..dc0b63a 100644 --- a/lib/rubyvote/positional.rb +++ b/lib/rubyvote/positional.rb @@ -38,7 +38,7 @@ class BordaVote < ElectionVote end super(votes) end - + def tally_vote(vote) points = candidates.length - 1 vote.each do |candidate| @@ -51,7 +51,7 @@ class BordaVote < ElectionVote points -= 1 end end - + def verify_vote(vote=nil) vote.instance_of?( Array ) and vote == vote.uniq @@ -64,11 +64,12 @@ end class BordaResult < ElectionResult attr_reader :ranked_candidates + attr_reader :points def initialize(voteobj=nil) super(voteobj) votes = @election.votes - + @ranked_candidates = votes.sort do |a, b| b[1] <=> a[1] end.collect {|i| i[0]} @@ -76,6 +77,8 @@ class BordaResult < ElectionResult @winners = @ranked_candidates.find_all do |i| votes[i] == votes[@ranked_candidates[0]] end + + @points = self.election.votes end end -- 2.30.2