https://wikimedia.org.au/w/index.php?title=Election_software/tally.inc_(Hare-Clark)&feed=atom&action=history
Election software/tally.inc (Hare-Clark) - Revision history
2024-03-29T05:09:52Z
Revision history for this page on the wiki
MediaWiki 1.40.1
https://wikimedia.org.au/w/index.php?title=Election_software/tally.inc_(Hare-Clark)&diff=15226&oldid=prev
TomH: add
2019-08-02T13:50:00Z
<p>add</p>
<table style="background-color: #fff; color: #202122;" data-mw="interface">
<col class="diff-marker" />
<col class="diff-content" />
<col class="diff-marker" />
<col class="diff-content" />
<tr class="diff-title" lang="en">
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">← Older revision</td>
<td colspan="2" style="background-color: #fff; color: #202122; text-align: center;">Revision as of 13:50, 2 August 2019</td>
</tr><tr><td colspan="2" class="diff-lineno" id="mw-diff-left-l1">Line 1:</td>
<td colspan="2" class="diff-lineno">Line 1:</td></tr>
<tr><td colspan="2" class="diff-side-deleted"></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;">[[Category:2013]]</ins></div></td></tr>
<tr><td colspan="2" class="diff-side-deleted"></td><td class="diff-marker" data-marker="+"></td><td style="color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;"><div><ins style="font-weight: bold; text-decoration: none;">[[Category:Elections]]</ins></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div><pre></div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div><pre></div></td></tr>
<tr><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div><?php</div></td><td class="diff-marker"></td><td style="background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;"><div><?php</div></td></tr>
</table>
TomH
https://wikimedia.org.au/w/index.php?title=Election_software/tally.inc_(Hare-Clark)&diff=10843&oldid=prev
Bilby: added countback
2013-10-27T15:42:41Z
<p>added countback</p>
<a href="https://wikimedia.org.au/w/index.php?title=Election_software/tally.inc_(Hare-Clark)&diff=10843&oldid=10839">Show changes</a>
Bilby
https://wikimedia.org.au/w/index.php?title=Election_software/tally.inc_(Hare-Clark)&diff=10839&oldid=prev
Bilby: Created page
2013-10-27T04:00:11Z
<p>Created page</p>
<p><b>New page</b></p><div><pre><br />
<?php<br />
<br />
$rowlength = 40;<br />
<br />
// --------------------------------------------------------------------<br />
// Step 0: Grab the category details from the database. <br />
// Nothing special here: each category in this case is a position.<br />
<br />
$sql = "SELECT * FROM Categories WHERE id=".$category;<br />
<br />
$result = mysql_query($sql);<br />
$row = mysql_fetch_array($result, MYSQL_ASSOC);<br />
<br />
$output .= "<h2>".$row['name']."</h2>";<br />
<br />
// Step 1: Grab the nominees<br />
<br />
$sql = "SELECT * FROM Nominees WHERE category=".$category;<br />
<br />
$numberOfNominees = 0;<br />
<br />
$result = mysql_query($sql);<br />
<br />
if ($result && mysql_num_rows($result) > 0)<br />
{ <br />
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))<br />
{<br />
$nomineeID[$numberOfNominees] = $row['id']; <br />
$nomineeDescription[$numberOfNominees] = $row['description'];<br />
$nomineePrecluded[$numberOfNominees] = 0; <br />
$numberOfNominees++;<br />
}<br />
}<br />
<br />
$output .= "<ol>";<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
$output .= "<li>".$nomineeDescription[$nominee]."</li>";<br />
}<br />
<br />
$output .= "</ol>";<br />
<br />
// Step 2: Let's load all the votes into an array.<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
$sql = "SELECT * FROM Votes, Voters WHERE voterid = Voters.id AND approved = 1 AND nomineeid = ".$nomineeID[$nominee];<br />
<br />
$result = mysql_query($sql);<br />
<br />
if ($result && mysql_num_rows($result) > 0)<br />
{<br />
while ($row = mysql_fetch_array($result, MYSQL_ASSOC))<br />
{<br />
$vote[$row['voterid']][$row['nomineeid']] = $row['vote'];<br />
}<br />
}<br />
}<br />
<br />
// ------------------------------------------------------------------------------------<br />
// Ok. It is possible that we need to preclude nominees from the election results.<br />
// This code drops them from the election.<br />
<br />
$finalNominees = 0;<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
if ($_REQUEST[$nomineeID[$nominee]."_checked"] == "on")<br />
{<br />
$vote = removeNominee($vote,$nomineeID[$nominee]);<br />
$output .= "<li>".$nomineeDescription[$nominee]." has been removed from the election.</li>";<br />
$nomineePrecluded[$nominee] = 1;<br />
}<br />
else<br />
{<br />
$finalNominees++;<br />
}<br />
}<br />
<br />
$round = 0;<br />
$finished = false;<br />
<br />
// ------------------------------------------------------------------------------------<br />
// Calculate the required quota.<br />
<br />
$output .= "<h3>Calculating Quota</h3>\n";<br />
$output .= "<p>Total non-precluded nominees: ".$finalNominees."</p>\n";<br />
<br />
$positions = stripslashes($_REQUEST['positions']);<br />
$output .= "<p>Positions available: ".$positions."</p>\n";<br />
<br />
// Check for valid votes<br />
$validVotes = 0;<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if (checkValidity($votes,1) == "valid") $validVotes++;<br />
$voterWeight[$voterID] = 1;<br />
}<br />
<br />
$output .= "<p>Valid votes: ".$validVotes."</p>\n";<br />
<br />
if ($validVotes > 0 && $positions > 0 && $finalNominees > 0)<br />
{<br />
$output .= "<p>Quota: Quota = (valid votes / (positions + 1)) + 1 (Droop’s Quota)<br />\n";<br />
$output .= "Quota: Quota = (".$validVotes." / (".$positions." + 1)) + 1<br />\n";<br />
$quota = ceil(($validVotes / ($positions + 1)) + 1);<br />
$output .= "Quota: ".$quota."</p>\n";<br />
<br />
// ------------------------------------------------------------------------------------<br />
$output .= "<h3>Calculating Result</h3>\n";<br />
<br />
while (!$finished)<br />
{<br />
if (++$roundCount > 50) ($finished = 1);<br />
$output .= "<h3>Round ".($round + 1)."</h3>\n";<br />
<br />
// Step 3: We need to confirm that the votes are good.<br />
// This checks for bad votes.<br />
<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
$vote[$voterID]['Valid'] = checkValidity($votes,1);<br />
}<br />
<br />
$votercount = 0;<br />
$tablecount = 0;<br />
<br />
$tables = "";<br />
<br />
// I need to list the voter IDs so that they can be checked. This displays them,<br />
// and also initialises the tables I'll need for display - I want to show all the results,<br />
// but don't want to do a next/previous thing as it want it possible to print everything, <br />
// so this breaks them up into separate tables based on a preset number of voters per table.<br />
<br />
$tables[$tablecount] .= "<tr bgcolor=\"#cccccc\">\n";<br />
$tables[$tablecount] .= "<td><br /></td>\n";<br />
<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if (($votercount > 0) && (($votercount % $rowlength) == 0))<br />
{<br />
$tables[$tablecount] .= "</tr>\n";<br />
<br />
$tablecount++;<br />
<br />
$tables[$tablecount] .= "<tr><td colspan=\"".($rowlength + 1)."\"><br /></td></tr><tr bgcolor=\"#cccccc\">\n";<br />
$tables[$tablecount] .= "<td><br /></td>\n";<br />
}<br />
<br />
$tables[$tablecount] .= "<td>".$voterID."</td>\n";<br />
<br />
$votercount++;<br />
}<br />
<br />
$tables[$tablecount] .= "</tr>\n";<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
$tablecount = -1;<br />
$votercount = 0;<br />
<br />
$nomineeCount[$nominee][$round] = 0;<br />
<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if ((($votercount % $rowlength) == 0))<br />
{<br />
$tables[$tablecount] .= "</tr>\n";<br />
<br />
$tablecount++;<br />
<br />
$tables[$tablecount] .= "<tr>\n<td bgcolor=\"#cccccc\">".($nominee + 1)."</td>\n";<br />
}<br />
<br />
$colour = "#ffffff";<br />
<br />
if ($votes[$nomineeID[$nominee]] == 1 && $vote[$voterID]['Valid'] == "valid") <br />
{ <br />
$colour = "#33ff66"; <br />
$nomineeCount[$nominee][$round] += 1 * $voterWeight[$voterID];<br />
<br />
if ($voterWeight[$voterID] != 1)<br />
{<br />
$colour = "#ffff00"; <br />
}<br />
}<br />
<br />
if ($vote[$voterID]['Valid'] == "invalid") <br />
{ <br />
$colour = "#ff9900"; <br />
}<br />
<br />
$tables[$tablecount] .= "<td bgcolor=\"".$colour."\">".$votes[$nomineeID[$nominee]]."</td>\n";<br />
<br />
$votercount++;<br />
}<br />
<br />
$tables[$tablecount] .= "</tr>\n";<br />
}<br />
<br />
$output .= '<table cellpadding="2" cellspacing="0" border="1">'."\n";<br />
<br />
for ($table = 0; $table <= $tablecount; $table++)<br />
{ <br />
$output .= $tables[$table];<br />
}<br />
<br />
$output .= "</table>\n";<br />
<br />
//Step : Work out if we have a winner.<br />
<br />
$biggest = 0;<br />
$noscoreCount = 0;<br />
$biggestCount = 0;<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
if($nomineeCount[$nominee][$round] > $biggest)<br />
{<br />
$biggest = $nomineeCount[$nominee][$round];<br />
$biggestCount = 1;<br />
}<br />
<br />
else if ($nomineeCount[$nominee][$round] == $biggest)<br />
{<br />
$biggestCount++;<br />
}<br />
<br />
if ($nomineeCount[$nominee][$round] == 0)<br />
{<br />
$noscoreCount++;<br />
}<br />
}<br />
<br />
$lowest = $biggest;<br />
$lowestCount = 0;<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
if ($nomineePrecluded[$nominee])<br />
{<br />
// Used for debugging to confirm that a nominee is now precluded<br />
}<br />
<br />
else if($nomineeCount[$nominee][$round] < $lowest)<br />
{<br />
$lowest = $nomineeCount[$nominee][$round];<br />
$lowestCount = 1;<br />
}<br />
<br />
else if ($nomineeCount[$nominee][$round] == $lowest)<br />
{<br />
$lowestCount++;<br />
}<br />
}<br />
<br />
$output .= '<br \><table cellpadding="2" cellspacing="0" border="1">'."\n<tr>\n<td><br /></td>\n";<br />
<br />
$round++;<br />
<br />
for ($roundnumber = 0; $roundnumber < $round; $roundnumber++)<br />
{<br />
$output .= "<td bgcolor=\"#cccccc\">Round ".($roundnumber + 1)."</td>\n";<br />
}<br />
<br />
$output .= "</tr>\n";<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
$output .= "<tr><td bgcolor=\"#cccccc\">".$nomineeDescription[$nominee]."</td>\n";<br />
for ($roundnumber = 0; $roundnumber < $round; $roundnumber++)<br />
{<br />
$output .= "<td";<br />
<br />
if ($roundnumber == $round - 1)<br />
{<br />
if ($nomineePrecluded[$nominee]) <br />
{<br />
$output .= " bgcolor=\"#ff0000\""; <br />
}<br />
else<br />
{<br />
if ($nomineeCount[$nominee][$roundnumber] == $biggest) { $output .= " bgcolor=\"#33ff66\""; }<br />
if ($nomineeCount[$nominee][$roundnumber] == $lowest) { $output .= " bgcolor=\"#ff9900\""; }<br />
}<br />
}<br />
<br />
$output .= ">".$nomineeCount[$nominee][$roundnumber]."</td>\n";<br />
}<br />
$output .= "</tr>\n";<br />
}<br />
<br />
$output .= "</table>\n";<br />
<br />
//Step : Report on the end of the first round.<br />
<br />
$output .= "<p>At the end of Round ".$round.", ";<br />
<br />
// See if anyone passed the quota<br />
if ($biggest >= $quota)<br />
{<br />
$output .= "there is a winner.</p>";<br />
<br />
$output .="<h3>Winner</h3>\n";<br />
<br />
$output .= "<ul>";<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
if ($nomineeCount[$nominee][$round-1] >= $quota) <br />
{ <br />
$output .= "<li>".$nomineeDescription[$nominee]."</li>\n";<br />
<br />
// Increase the winners count<br />
$winners++;<br />
<br />
// Have we enough winners to stop now?<br />
if ($winners == $positions)<br />
{<br />
$finished = true;<br />
}<br />
else<br />
{<br />
$nomineeWon[$nominee] = 1;<br />
$voteWeight = ($nomineeCount[$nominee][$round-1] - $quota) / $nomineeCount[$nominee][$round-1];<br />
<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if ($vote[$voterID]['Valid'] == "valid" AND $votes[$nomineeID[$nominee]] == 1)<br />
{<br />
$voterWeight[$voterID] = $voteWeight;<br />
}<br />
}<br />
<br />
$vote = removeNominee($vote, $nomineeID[$nominee]);<br />
<br />
$nomineePrecluded[$nominee] = 1;<br />
}<br />
}<br />
}<br />
<br />
$output .= "</ul>\n";<br />
<br />
$output .= "<p>As there are still positions to fill, preferences for successful voters have been reallocated.</p>";<br />
<br />
}<br />
<br />
/*<br />
else if ($biggestCount + $noscoreCount == $numberOfNominees)<br />
{<br />
if ($biggestCount == 1) { $output .= "there is a winner.</p>"; }<br />
if ($biggestCount > 1) { $output .= "there are ".$biggestCount." winners.</p>"; }<br />
<br />
$output .="<h3>Winner</h3>\n";<br />
<br />
$output .= "<ul>";<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
if ($nomineeCount[$nominee][$round-1] == $biggest) <br />
{ <br />
$output .= "<li>".$nomineeDescription[$nominee]."</li>\n";<br />
}<br />
}<br />
<br />
$output .= "</ul>\n";<br />
<br />
$finished = true;<br />
}<br />
*/ <br />
<br />
else<br />
{<br />
$output .= " there is no clear winner.</p>";<br />
<br />
if ($lowestCount >= 1)<br />
{ <br />
$lowestID = -1;<br />
$target = 0; // By default, we are going to remove the only nominee to get the lowest score.<br />
$targetCount = 0;<br />
<br />
if ($lowestCount > 1)<br />
{<br />
$output .= "<p>As there were ".$lowestCount." nominees with the lowest score, one will randomly be removed.<p>";<br />
$target = rand(0,$lowestCount-1);<br />
}<br />
<br />
for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)<br />
{<br />
if ($nomineeCount[$nominee][$round-1] == $lowest && !$nomineePrecluded[$nominee]) <br />
{ <br />
if ($targetCount == $target)<br />
{ <br />
$lowestID = $nominee; <br />
}<br />
$targetCount++;<br />
}<br />
}<br />
<br />
$output .= "<p>Removing votes for ".$nomineeDescription[$lowestID].".</p>";<br />
$nomineePrecluded[$lowestID] = 1; // Removes them from the count.<br />
<br />
$output .= "<p>Reset the weighting, as a candidate has been excluded.</p>";<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if (checkValidity($votes,1) == "valid") $validVotes++;<br />
$voterWeight[$voterID] = 1;<br />
}<br />
<br />
// Code to remove votes.<br />
<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if ($vote[$voterID]['Valid'] == "invalid") <br />
{<br />
unset($vote[$voterID]);<br />
}<br />
else<br />
{<br />
$found = false;<br />
<br />
$target = $votes[$nomineeID[$lowestID]];<br />
<br />
if ($target > 0)<br />
{<br />
$vote[$voterID][$nomineeID[$lowestID]] = 0;<br />
<br />
foreach($votes as $voteNomineeID => $voteScore)<br />
{<br />
if ($vote[$voterID][$voteNomineeID] >= $target)<br />
{<br />
$vote[$voterID][$voteNomineeID]--;<br />
}<br />
<br />
if ($vote[$voterID][$voteNomineeID] <= 0)<br />
{<br />
unset($vote[$voterID][$voteNomineeID]);<br />
}<br />
}<br />
}<br />
}<br />
}<br />
<br />
$output .= "<h4>Calculating new quota</h4>\n";<br />
<br />
$output .= "<p>Positions remaining: ".($positions - $winners)."</p>\n";<br />
<br />
// Check for valid votes<br />
$validVotes = 0;<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if (checkValidity($votes,1) == "valid") $validVotes++;<br />
}<br />
<br />
$output .= "<p>Valid votes: ".$validVotes."</p>\n";<br />
<br />
if ($validVotes > 0 && $positions > 0)<br />
{<br />
$output .= "<p>Quota: Quota = (valid votes / (positions + 1)) + 1 (Droop’s Quota)<br />\n";<br />
$output .= "Quota: Quota = (".$validVotes." / (".($positions - $winners)." + 1)) + 1<br />\n";<br />
$quota = ceil(($validVotes / (($positions - $winners) + 1)) + 1);<br />
$output .= "Quota: ".$quota."</p>\n";<br />
}<br />
}<br />
}<br />
}<br />
}<br />
<br />
// --------------------------------------------------------------------------------------<br />
<br />
function removeNominee($vote, $nominee)<br />
{<br />
// Code to remove votes.<br />
<br />
foreach ($vote as $voterID => $votes)<br />
{<br />
if ($vote[$voterID]['Valid'] == "invalid") <br />
{<br />
unset($vote[$voterID]);<br />
}<br />
else<br />
{<br />
$found = false;<br />
<br />
$target = $votes[$nominee];<br />
<br />
if ($target > 0)<br />
{<br />
$vote[$voterID][$nominee] = 0;<br />
<br />
foreach($votes as $voteNomineeID => $voteScore)<br />
{<br />
if ($vote[$voterID][$voteNomineeID] >= $target)<br />
{<br />
$vote[$voterID][$voteNomineeID]--;<br />
}<br />
<br />
if ($vote[$voterID][$voteNomineeID] <= 0)<br />
{<br />
unset($vote[$voterID][$voteNomineeID]);<br />
}<br />
}<br />
}<br />
}<br />
}<br />
<br />
return $vote;<br />
}<br />
<br />
<br />
// --------------------------------------------------------------------------------------<br />
<br />
function checkValidity($votes, $value)<br />
{<br />
$validvotes = 0;<br />
<br />
foreach ($votes as $key => $vote)<br />
{<br />
if ($vote == $value)<br />
{<br />
++$validvotes;<br />
}<br />
}<br />
<br />
$result = "invalid";<br />
<br />
if ($validvotes == 1)<br />
{<br />
$result = "valid";<br />
}<br />
<br />
return $result;<br />
}<br />
<br />
?><br />
<br />
</pre></div>
Bilby