[dw-free] /admin/misc/runoffpoll.bml can be removed
[commit: http://hg.dwscoalition.org/dw-free/rev/c0db56fd627d]
http://bugs.dwscoalition.org/show_bug.cgi?id=1758
Not using this anywhere.
Patch by
kareila.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=1758
Not using this anywhere.
Patch by
Files modified:
- htdocs/admin/misc/runoffpoll.bml
--------------------------------------------------------------------------------
diff -r 16b221eba307 -r c0db56fd627d htdocs/admin/misc/runoffpoll.bml
--- a/htdocs/admin/misc/runoffpoll.bml Sat Sep 05 05:55:56 2009 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,272 +0,0 @@
-<?page
-body<=
-<?_code
-{
- # This page is for calculating instant run voting for polls that match the
- # criteria of an instant run-off election:
- # - There should be more than one nominee and rank(eg. 1st, 2nd, 3rd etc.)
- # - Each set of nominees should match the other choices
- # - There should not be more choice ranks than there are nominees
- #
- # There are some quirks with how this works with our polls:
- # - An empty rank will cause following ranks to get bumped higher.
- # For example, if my first choice is apples, my second choice is left
- # blank, and my third choice is bananas; bananas become my second choice.
- # - The same nominee can be chosen for several ranks. Once a
- # candidate is eliminated they will never get counted again, only perhaps
- # in a tie breaker situation may there be some advantage to voting for
- # the same person across ranks.
- #
-
- use strict;
- use vars qw(%GET %POST);
- BML::decl_params(pollid => 'digits',
- lj_form_auth => qr/./,
- );
-
- my $remote = LJ::get_remote() or return "<?needlogin?>";
-
- my $lj_core = LJ::load_user("lj_core");
- return "You do not have access to this page"
- unless $lj_core->has_friend($remote);
-
- my $body = '';
-
- $body .= '<form action="runoffpoll" method="POST">';
- $body .= LJ::form_auth();
- $body .= "Enter the poll ID: ";
- $body .= LJ::html_text({
- name => 'pollid',
- size => '6',
- value => $POST{'pollid'} || undef,
- });
- $body .= LJ::html_submit("Calculate Results");
-
- if (LJ::did_post()) {
-
- my @errors;
- push @errors, $ML{'error.invalidform'}
- unless LJ::check_form_auth();
-
- my $pollid = ($POST{pollid} || $GET{pollid})+0;
- return LJ::error_list(@errors) if (@errors);
-
- # TODO check if poll ID is valid
- my $poll = LJ::Poll->new($pollid);
-
-
- # Stores a hash of who has been eliminated
- my %eliminate;
- my %answer;
-
- # SUBS
-
- # Return true if someone has majority
- my $has_majority = sub {
- my ($total, $vote_totals, $winner) = @_;
-
- foreach my $id (keys %$vote_totals) {
- if ($vote_totals->{$id} > ($total/2)) {
- $$winner = $id;
- return 1;
- }
- }
-
- return 0;
- };
-
- # Display totals
- my $total_display = sub {
- my ($combined_total, $vote_totals, $answer) = @_;
- my $ret;
- $ret .= "<table>";
- $ret .= "<tr><td></td><td valign='right'>Total Votes</td></tr>";
- foreach my $id (keys %$vote_totals) {
- $ret .= "<tr><td><b>$answer->{$id}</b></td><td valign='right'>$vote_totals->{$id}</td></tr>";
- $$combined_total += $vote_totals->{$id};
- }
- $ret .= "<tr><td> </td><td valign='right'>$$combined_total</td></tr>";
- $ret .= "</table>";
-
- return $ret;
- };
-
- # Instant Runoff Calculation
- my $instantrunoff = sub {
- my ($vote_runoff, $vote_totals, $body) = @_;
- my $lowest_vote;
- my %to_eliminate;
-
- # Note nominees without any votes
- foreach my $id (keys %answer) {
- $to_eliminate{$id} = 1 unless ($vote_totals->{$id});
- }
-
- # Starting at the bottom finding the lowest number of votes received
- # Find all IDs with the lowest number of votes and add them to
- # the eliminate hash
- foreach my $id (sort { $vote_totals->{$a} <=> $vote_totals->{$b} } keys %$vote_totals) {
- $lowest_vote = $vote_totals->{$id} unless ($lowest_vote);
- $to_eliminate{$id} = 1 if ($vote_totals->{$id} == $lowest_vote);
- }
-
- # If all candidates are tied then we can't eliminate them all
- # Instead we discard that round of votes
- if ((scalar keys %to_eliminate) == (scalar keys %answer)) {
- foreach my $uid (keys %$vote_runoff) {
- shift @{$vote_runoff->{$uid}};
- }
- $$body .= "<p>Action: All users are tied, go to the next ranked choice</p>";
-
- # Otherwise we add the lowest candidates to the eliminate hash
- # and discard all votes for candidates in the hash
- } else {
- my $elim_text = '';
- foreach my $id (keys %to_eliminate) {
- $eliminate{$id} = 1;
- $elim_text .= $answer{$id} . ",";
- }
- chop $elim_text;
- $$body .= "<p>Action: Eliminate " . (scalar (keys %to_eliminate)) . " candidates ($elim_text)</p>";
- }
-
- # Remove any candidates that are in the eliminated hash
- foreach my $uid (keys %$vote_runoff) {
- while ( $eliminate{$vote_runoff->{$uid}[0]} ) {
- shift @{$vote_runoff->{$uid}};
- }
- }
-
- };
-
-
- # Questions and Answers
- my @qs = $poll->questions;
- my %question;
- my $num_questions = scalar @qs;
- my $null = ' ';
- foreach my $q (@qs) {
- my $qid = $q->pollqid;
- $question{$qid}{type} = $q->type;
- $question{$qid}{text} = $q->qtext;
- @{$question{$qid}{answers}} = $q->items;
- }
-
- my $firstq = $qs[0]->pollqid;
- my $num_choices = 0; # total number of candidates to choose from
- foreach my $a (@{$question{$firstq}{answers}}) {
- $answer{$a->{pollitid}} = $a->{item};
- $num_choices++;
- }
-
- # Verify all answer items match up across questions
- foreach my $q (@qs) {
- foreach my $a ($q->items) {
- my $pollitid = $a->{pollitid};
- my $item = $a->{item};
- if ( $item ne $answer{$pollitid} ) {
- $body .= "<p>ERROR: Invalid Instant Runoff Poll, answers do not match.<br />" .
- "\"$item\" is not the same answer as \"$answer{$pollitid}\"</p>";
- return $body;
- }
- }
- }
-
- $body .= "<p>Answers verified</p>";
-
- # Get votes cast
- my %votes;
- foreach my $q (@qs) {
- foreach my $v ($q->answers) {
- $votes{$v->{userid}}[$v->{pollqid} - 1] = $v->{value};
- }
- }
-
- # Generate raw data as comma separated values
- my $us = LJ::load_userids(keys %votes);
- my $raw .= "<b>Raw Data</b><br />\n";
- foreach my $uid (keys %votes) {
- my $user = $us->{$uid};
- $raw .= $user ? $user->ljuser_display . " : " : "(unknown) : ";
- foreach my $num (0..($num_questions-1)) {
- my $vdisplay = $votes{$uid}[$num] || ' ';
- $raw .= "," unless ($num == 0);
- $raw .= "$answer{$votes{$uid}[$num]}";
- }
- $raw .= "<br />\n";
- }
-
-
- # Iterate through as many rounds as necessary until a winner is found
- # Or we have only two possible candidates left
- my $winner = undef;
- my $round = 1;
- my %vote_runoff = %votes;
- while ( !$winner && ($round <= $num_choices) ) {
- # Get totals for each vote option
- my %vote_totals;
- foreach my $uid (keys %vote_runoff) {
- $vote_totals{$vote_runoff{$uid}[0]}++ if ($vote_runoff{$uid}[0]);
- }
-
- my $combined_total = 0; # Number of votes counted
- $body .= "<hr /><h3>Round \#$round</h3>\n";
-
- # Display totals
- $body .= $total_display->(\$combined_total, \%vote_totals, \%answer);
-
- if ($has_majority->($combined_total, \%vote_totals, \$winner)) {
- $body .= "<hr /><h1> Winner is $answer{$winner} </h1>";
- } else {
- $instantrunoff->(\%vote_runoff, \%vote_totals, \$body);
- }
-
- $round++;
- }
-
- $body .= "<hr /><h1> It is a tie! </h1>" unless ($winner);;
-
- $body .= "<br />\n$raw";
-
- } else {
- # Show an example poll
- $body .= qq{
- <p><h3>Example Poll Markup</h3>
-<xmp><lj-poll name="Choose the next President of the United States" whovote="all" whoview="all">
- <lj-pq type="drop">
- 1st Choice for President
- <lj-pi>Hillary Clinton</lj-pi>
- <lj-pi>John McCain</lj-pi>
- <lj-pi>Cynthia McKinney</lj-pi>
- <lj-pi>Ralph Nader</lj-pi>
- <lj-pi>Barack Obama</lj-pi>
- <lj-pi>Wayne Allyn Root</lj-pi>
- </lj-pq>
- <lj-pq type="drop">
- 2nd Choice for President
- <lj-pi>Hillary Clinton</lj-pi>
- <lj-pi>John McCain</lj-pi>
- <lj-pi>Cynthia McKinney</lj-pi>
- <lj-pi>Ralph Nader</lj-pi>
- <lj-pi>Barack Obama</lj-pi>
- <lj-pi>Wayne Allyn Root</lj-pi>
- </lj-pq>
- <lj-pq type="drop">
- 3rd Choice for President
- <lj-pi>Hillary Clinton</lj-pi>
- <lj-pi>John McCain</lj-pi>
- <lj-pi>Cynthia McKinney</lj-pi>
- <lj-pi>Ralph Nader</lj-pi>
- <lj-pi>Barack Obama</lj-pi>
- <lj-pi>Wayne Allyn Root</lj-pi>
- </lj-pq>
-</lj-poll></xmp></p>
- };
- }
-
- return $body;
-}
-_code?>
-<=body
-title=><?_code return "Calculate Run Off Poll Results"; _code?>
-page?>
--------------------------------------------------------------------------------
