def index
if params[:urlpassword]
password = params[:urlpassword]
- else
- password = nil
- end
- if @voter = FullVoter.find(:all, :conditions =>
- [ "password = ?", password ] )[0]
- @voter.vote = Vote.new if @voter.vote.nil?
- @voter.vote.set_defaults! if @voter.vote.rankings.empty?
+ if @voter = FullVoter.find(:all,
+ :conditions => [ "password = ?", password ] )[0]
- @election = @voter.election
- @sidebar_content = render_to_string(:partial => 'sortable_vote')
- render :action => 'full_vote'
- elsif params[:urlpassword]
- redirect_to :action => 'index'
+ @voter.vote = Vote.new if @voter.vote.nil?
+ @voter.vote.set_defaults! if @voter.vote.rankings.empty?
+
+ @election = @voter.election
+
+ # if the election is now finished
+ if @election.enddate < Time.now
+ # compute and display results
+
+ @results = @election.results
+ @candidates = {}
+ @election.candidates.each {|c| @candidates[c.id] = c}
+ @names = @election.names_by_id
+
+ @sidebar_content = render_to_string(:partial => 'results_sidebar')
+ render :action => 'results'
+ else
+ @sidebar_content = render_to_string(:partial => 'vote_sidebar')
+ render :action => 'full_vote'
+ end
+ elsif params[:urlpassword]
+ redirect_to :action => 'index'
+ end
end
end
end
end
+ def pref_tables
+ if authenticate
+ @election = @voter.election
+ @results = @election.results
+ @candidates = {}
+ @election.candidates.each {|c| @candidates[c.id] = c}
+ @names = @election.names_by_id
+ render :template => 'common/pref_tables', :layout => 'basic'
+ else
+ redirect_to :action => 'index'
+ end
+ end
+
+ def details
+ if authenticate
+ @election = @voter.election
+ @votes = @election.votes.select {|v| v.confirmed? }.randomize
+ @voters = @votes.collect {|v| v.voter}.randomize
+ render :action => 'details'
+ else
+ redirect_to :action => 'index'
+ end
+ end
+
def review
if authenticate
@voter.vote.time = Time.now
confirmed == 1
end
- def votestring=(string="")
- candidate_ids = voter.election.candidates.sort.collect \
- { |candidate| candidate.id.to_i }
-
- rel_votes = string.split("").collect { |vote| vote.to_i }
-
- # covert relative orders to absolute candidate ids
- self.votes = rel_votes.collect { |vote| candidate_ids[ vote - 1 ] }
- end
-
def votestring
# create a mapping of candidates ids and the relative order of the
# candidates as they appear when sorted alphabetically
end
# assemble the votestring
- self.votes.collect {|v| cand_relnums[v]}.join("")
+ self.votes.collect {|v| (cand_relnums[v] + 64).chr}.join("")
end
# the following subroutine is used for quickvotes, but need for elections now
"Simple Condorcet" to distinguish it from the Schulze method which is
another Condorcet system.</p>
-<%= render :partial => 'pref_tables' %>
+<% candidates = @election.ssd_result.ranked_candidates.flatten -%>
+<% if candidates.size <= 7 -%>
+ <%= render_partial 'common/pref_tables' %>
+<% else %>
+
+ There are too many candidates in your elections to show the result
+ tables. <%= link_to "Click here", { :action => 'pref_tables', :id =>
+ @voter.password }, :popup => [] %> to view details.
+
+<% end -%>
</div>
--- /dev/null
+<p>The full results of this election ranked the candidates in order of
+preference (from most preferred to least preferred):</p>
+
+<ol>
+<% @election.ssd_result.ranked_candidates.each do |place| %>
+ <li><%= h(place.collect {|c| @names[c].capitalize}.join( " <em>and</em> " )) %>
+ <%= "<strong>(TIE)</strong>" if place.length > 1 %></li>
+<% end %>
+</ol>
+
+
+<div class="rbmoreinfo">
+<h4>About the Schulze Method</h4>
+
+<p>The <%= link_to "Schulze method",
+"http://en.wikipedia.org/wiki/Schulze_method" %> is a preferential
+voting system. It is based on the Condorcet method but includes a set of
+methods for resolving "circular" defeats.</p>
+
+<p>The Schulze method is also known as Schwartz Sequential Dropping
+(SSD), Cloneproof Schwartz Sequential Dropping (CSSD), Beatpath Method,
+Beatpath Winner, Path Voting, and Path Winner.</p>
+</div>
+
+
+<% candidates = @election.ssd_result.ranked_candidates.flatten -%>
+<% if candidates.size <= 7 -%>
+ <%= render_partial 'common/pref_tables' %>
+<% else %>
+
+ There are too many candidates in your elections to show the result
+ tables. <%= link_to "Click here", { :action => 'pref_tables', :id =>
+ @voter.password }, :popup => [] %> to view details.
+
+<% end -%>
+
<% matrix = @election.ssd_result.matrix %>
<% victories = @election.ssd_result.victories_and_ties %>
-<% if candidates.size <= 7 -%>
-
<p>Each number in the table below shows how many times the candidate on
the left beat the matching candidate on the top. The winner is on the
top of the left column.</p>
<% end -%>
</table>
</div>
-<% end -%>
</div>
<% unless @election.election_method == method -%>
-<%= render :partial => 'result', :object => @results[method]%>
+<%= render :partial => 'common/result', :object => @results[method]%>
<% end -%>
-<%= render :partial => 'methodinfo_' + method,
+<%= render :partial => 'common/methodinfo_' + method,
:object => @results[method] %>
</div>
--- /dev/null
+<h2>Method</h2>
+
+<p>This election was run using:
+<strong><%= ELECTION_TYPES[@election.election_method] %></strong></p>
+
+<p>View results using other methods:<br />
+<% type_hash = {}; ELECTION_TYPES.each {|k,v| type_hash[v] = k} %>
+<%= select_tag 'election_type_select', options_for_select(type_hash, @election.election_method) %></p>
+
+<script>
+var election_methods = new Array(<%= ELECTION_TYPES.keys.collect {|k| "'#{k}'"}.join(', ') %>);
+var method_select = $('election_type_select');
+
+function show_results_for() {
+ var test = $('test');
+
+ method_select.value;
+ var result_boxes = document.getElementsByClassName('resultbox');
+ for (i = 0; i < result_boxes.length; i++) {
+ result_box = result_boxes[i];
+ if (result_box.id == (method_select.value + "_result")) {
+ Element.show(result_box);
+ } else {
+ Element.hide(result_box);
+ }
+ }
+
+ //alert(method_select.value);
+}
+
+Event.observe(method_select, 'change', show_results_for);
+</script>
+
+<h2>Statistics</h2>
+<%= image_tag( graph_url( :action => 'votes_per_interval', :id => @election ))%>
+<br />
+<br />
+
-<h2>Your Vote</h2>
-
-<p>Please vote by dragging items in the list below into your preferred
-order.</p>
-
<div id="sortable_list">
<ol id="rankings-list">
<% for ranking in @voter.vote.rankings %>
:url => { :action => "sort_candidates", :id => @voter.vote.id },
:complete => visual_effect(:highlight, 'rankings-list') %>
-<div style="margin-left: 30pt;">
-<%= button_to "Confirm Vote", :action => 'review', :id => @voter.password %>
-</div>
--- /dev/null
+<%= render_partial 'common/pref_tables' %>
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title><%= @page_title || "Selectricity" %></title>
+ <%= stylesheet_link_tag "common", :media => "all" %>
+ <%= stylesheet_link_tag *(@stylesheets) %>
+ <%begin%>
+ <%= stylesheet_link_tag "ie6hacks", :media => "all" if
+ request.user_agent =~ /msie\s(5\.[5-9]|[6]\.[0-9]*).*(win)/i %>
+ <%rescue NoMethodError%>
+ <%end%>
+ <%= javascript_include_tag "prototype", "effects", "dragdrop", "controls" %>
+ </head>
+
+ <body>
+ <div>
+ <%= @content_for_layout %>
+ </div>
+
+ <div class="clear-div"></div>
+ <%= render_partial 'layouts/footer' %>
+ </div>
+ </body>
+</html>
<div id="header">
<div id="top-bar">
<% if session[:user]%>
- <%= link_to User.find(session[:user]).login.capitalize,
+ <%= link_to User.find(session[:user]).login.dowcase,
:controller => "account",
:action => "summary", :id => session[:user][:id] %>
- <%= link_to( 'Log out', :controller => 'account',
+ <%= link_to( 'log out', :controller => 'account',
:action => 'logout' )%>
<% else %>
<%= link_to("login", :controller => "account", :action => "login")
<div id="top-bar">
<div id="bar-left">
<% if session[:user] %>
- <%= link_to User.find(session[:user]).login.capitalize,
+ <%= link_to User.find(session[:user]).login.downcase,
:controller => "account",
:action => "summary", :id => session[:user][:id] %>
<%= link_to "logout", :controller => "account",
+++ /dev/null
-<div class="rbmoreinfo">
-<h4>About the Schulze Method</h4>
-
-<p>The <%= link_to "Schulze method",
-"http://en.wikipedia.org/wiki/Schulze_method" %> is a preferential
-voting system. It is based on the Condorcet method but includes a set of
-methods for resolving "circular" defeats.</p>
-
-<p>The Schulze method is also known as Schwartz Sequential Dropping
-(SSD), Cloneproof Schwartz Sequential Dropping (CSSD), Beatpath Method,
-Beatpath Winner, Path Voting, and Path Winner.</p>
-</div>
-
-<%= render :partial => 'pref_tables' %>
-
-<h2>Method</h2>
-
-<p>This election was run using:
-<strong><%= ELECTION_TYPES[@election.election_method] %></strong></p>
-
-<p>View results using other methods:<br />
-<% type_hash = {}; ELECTION_TYPES.each {|k,v| type_hash[v] = k} %>
-<%= select_tag 'election_type_select', options_for_select(type_hash, @election.election_method) %></p>
-
-<script>
-var election_methods = new Array(<%= ELECTION_TYPES.keys.collect {|k| "'#{k}'"}.join(', ') %>);
-var method_select = $('election_type_select');
-
-function show_results_for() {
- var test = $('test');
-
- method_select.value;
- var result_boxes = document.getElementsByClassName('resultbox');
- for (i = 0; i < result_boxes.length; i++) {
- result_box = result_boxes[i];
- if (result_box.id == (method_select.value + "_result")) {
- Element.show(result_box);
- } else {
- Element.hide(result_box);
- }
- }
-
- //alert(method_select.value);
-}
-
-Event.observe(method_select, 'change', show_results_for);
-</script>
-
-<h2>Statistics</h2>
-<%= image_tag( graph_url( :action => 'votes_per_interval', :id => @election ))%>
-<br />
-<br />
+<!-- common data to all sidebars -->
+<%= render_partial 'common/results_sidebar' %>
<h2>Voter Report</h2>
from <em>most preferred at the top</em> to <em>least preferred at the
bottom</em>. When you are done, press confirm to record your vote.</p>
-<%= render :partial => 'voter/sortable_vote' %>
+<%= render :partial => 'common/sortable_vote' %>
<%= button_to "Confirm Vote", quickaction_url( :action => 'confirm', :ident => @voter.election.name) %>
</div>
<div id="winner_box">
-<%= render :partial => 'result', :object => @results[@election.election_method] %>
+<%= render :partial => 'common/result', :object => @results[@election.election_method] %>
</div>
<% if @election.shortdesc %>
<%= @election.voters.reject {|v| not v.voted? }.length %>
</blockquote>
-<%= render :partial => 'result_box',
+<%= render :partial => 'common/result_box',
:locals => { :method => @election.election_method } %>
<% for result_type in @election.other_methods %>
-<%= render :partial => 'result_box',
+<%= render :partial => 'common/result_box',
:locals => { :method => result_type } %>
<% end %>
--- /dev/null
+<!-- common data to all sidebars -->
+<%= render_partial 'common/results_sidebar' %>
+
+<h2>Details</h2>
+
+<p><%= link_to "Auditing Information", { :action => 'details', :id => @voter.password }, :popup => [] %></p>
+
--- /dev/null
+<h2>Your Vote</h2>
+
+<p>Please vote by dragging items in the list below into your preferred
+order.</p>
+
+<%= render :partial => 'common/sortable_vote' %>
+
+<div style="margin-left: 30pt;">
+<%= button_to "Submit Vote", :action => 'review', :id => @voter.password %>
+</div>
--- /dev/null
+<div id="title-header">
+ <span class="header">Details</span>
+ <span class="subheader"><%= @election.name %></span>
+</div>
+
+<p>This page contains information useful for auditing elections and
+verify that votes were tabulated correctly.</p>
+
+<p>The following invididuals (in random order) voted in this
+election:</p>
+
+<ol>
+<%- @voters.each do |voter| -%>
+<li><%= voter.email %></li>
+<%- end -%>
+</ol>
+
+<p>The following table lists the votes cast in random order.</p>
+
+<p>The column marked <em>Verification Token</em> lists tokens that were
+given to voters at the time of voting. Voters can check to see that the
+vote that corresponds to their token was recorded correctly. The column
+marks "vote" lists the candidates in order of the voter's preference. To
+read these votes, please refer to the key below.</p>
+
+<table class="preftable">
+<tr>
+<th>Verification Token</th>
+<th>Vote</th>
+<%- @votes.each do |vote| -%>
+<tr>
+<td><%= vote.token %></td><td><%= vote.votestring%></td>
+</tr>
+<%- end -%>
+</table>
+
+<p style="margin-top: 1em;">Key:</p>
+
+<table class="preftable">
+<tr>
+<th>Code</th>
+<th>Candidate</th>
+<%- @election.candidates.sort.each_with_index do |c, i| -%>
+<tr>
+<td><%= (i + 65).chr %></td>
+<td><%= c.name %></td>
+</tr>
+<%- end -%>
+</table>
+
--- /dev/null
+<% require 'whois/whois' %>
+
+<div id="title-header">
+ <span class="header">Results</span>
+ <span class="subheader"><%= @election.name %></span>
+</div>
+
+<div id="winner_box">
+<%= render :partial => 'common/result', :object => @results[@election.election_method] %>
+</div>
+
+<% if @election.shortdesc %>
+ <p><strong>Vote Description:</strong></p>
+ <blockquote><em><%=h @election.shortdesc %></em>
+ <% if @election.longdesc -%>
+ <br />
+ <%= h(@election.longdesc) -%>
+ <% end -%>
+ </blockquote>
+<% end %>
+
+<p><strong>Number of voters:</strong></p>
+ <blockquote>
+ <%= @election.voters.reject {|v| not v.voted? }.length %>
+ </blockquote>
+
+<%= render :partial => 'common/result_box',
+ :locals => { :method => @election.election_method } %>
+
+<% for result_type in @election.other_methods %>
+
+<%= render :partial => 'common/result_box',
+ :locals => { :method => result_type } %>
+
+<% end %>
+
+
+<div class="clear-div"></div>
+
+<!--
+<%= image_tag( graph_url( :action => 'choices_positions', :id => @election ) ) %><br />
+-->
+
border: 1px black solid;
text-align: center;
font-weight: bold
+}
+
+.preftable {
+ font-family: verdana,arial,helvetica,sans-serif;
+ border-spacing: 0px;
+ border-width: 2px;
+ border-color: #999999;
+ border-style: solid;
+ caption-side: top;
+}
+
+.preftable th {
+ font-family: verdana,arial,helvetica,sans-serif;
+ border-width: 2px;
+ border-color: #999999;
+ border-style: solid;
+ text-align: center;
+ font-weight: bold;
+ padding: 5px 5px 5px 5px;
+ background-color: #999999;
+ color: #FFFFFF;
+}
+
+.preftable td {
+ border-collapse: collapse;
+ border-width: 1px;
+ border-color: #999999;
+ border-style: solid;
+ text-align: right;
+ padding-right: 5px;
+ padding-left: 5px;
+}
+
text-align: center;
margin-bottom: 1em;
}
-.preftable {
- font-family: verdana,arial,helvetica,sans-serif;
- border-spacing: 0px;
- border-width: 2px;
- border-color: #999999;
- border-style: solid;
- caption-side: top;
-}
-
-.preftable th {
- font-family: verdana,arial,helvetica,sans-serif;
- border-width: 2px;
- border-color: #999999;
- border-style: solid;
- text-align: center;
- font-weight: bold;
- padding: 5px 5px 5px 5px;
- background-color: #999999;
- color: #FFFFFF;
-}
-
-.preftable td {
- border-collapse: collapse;
- border-width: 1px;
- border-color: #999999;
- border-style: solid;
- text-align: right;
- padding-right: 5px;
- padding-left: 5px;
-}
.voterbox {
border-spacing: 0px;