Election software/tally.inc

From Wikimedia Australia
Jump to navigation Jump to search
<?php

$rowlength = 40;

// --------------------------------------------------------------------
// Step 0: Grab the category details from the database. 
// Nothing special here: each category in this case is a position.

$sql = "SELECT * FROM Categories WHERE id=".$category;

$result = mysql_query($sql);
$row = mysql_fetch_array($result, MYSQL_ASSOC);

$output .= "<h2>".$row['name']."</h2>";

// Step 1: Grab the nominees

$sql = "SELECT * FROM Nominees WHERE category=".$category;

$numberOfNominees = 0;

$result = mysql_query($sql);

if ($result && mysql_num_rows($result) > 0)
{	
	while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
	{
		$nomineeID[$numberOfNominees] 			= $row['id']; 
		$nomineeDescription[$numberOfNominees] 	= $row['description'];
		
		$numberOfNominees++;
	}
}

$output .= "<ol>";

for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
{
	$output .= "<li>".$nomineeDescription[$nominee]."</li>";
}

$output .= "</ol>";

// Step 2: Let's load all the votes into an array.

for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
{
	$sql = "SELECT * FROM Votes, Voters WHERE voterid = Voters.id AND approved = 1 AND nomineeid = ".$nomineeID[$nominee];
	
	$result = mysql_query($sql);
	
	if ($result && mysql_num_rows($result) > 0)
	{
		while ($row = mysql_fetch_array($result, MYSQL_ASSOC))
		{
			$vote[$row['voterid']][$row['nomineeid']] = $row['vote'];
		}
	}
}

// ------------------------------------------------------------------------------------
// Ok. It is possible that we need to preclude nominees from the election results.
// This code drops them from the election.

for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
{
    if ($_REQUEST[$nomineeID[$nominee]."_checked"] == "on")
    {
		$vote = removeNominee($vote,$nomineeID[$nominee]);
		$output .= "<li>".$nomineeDescription[$nominee]." has been removed from the election.</li>";
	}
}

$round = 0;
$finished = false;

while (!$finished)
{

	$output .= "<h3>Round ".($round + 1)."</h3>\n";

	// Step 3: We need to confirm that the votes are good. The assumption
	// This checks for bad votes.

	foreach ($vote as $voterID => $votes)
	{
		$vote[$voterID]['Valid'] = checkValidity($votes,1);
	}

	$votercount = 0;
	$tablecount = 0;

	$tables = "";

	// I need to list the voter IDs so that they can be checked. This displays them,
	// and also initialises the tables I'll need for display - I want to show all the results,
	// but don't want to do a next/previous thing as it want it possibe to print everything, 
	// so this breaks them up into separate tables based on a preset number of voters per table.

	$tables[$tablecount] .= "<tr bgcolor=\"#cccccc\">\n";
	$tables[$tablecount] .= "<td><br /></td>\n";

	foreach ($vote as $voterID => $votes)
	{
		if (($votercount > 0) && (($votercount % $rowlength) == 0))
		{
			$tables[$tablecount] .= "</tr>\n";
		
			$tablecount++;
		
			$tables[$tablecount] .= "<tr><td colspan=\"".($rowlength + 1)."\"><br /></td></tr><tr bgcolor=\"#cccccc\">\n";
			$tables[$tablecount] .= "<td><br /></td>\n";
		}
	
		$tables[$tablecount] .= "<td>".$voterID."</td>\n";
	
		$votercount++;
	}

	$tables[$tablecount] .= "</tr>\n";

	for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
	{
		$tablecount = -1;
		$votercount = 0;

		foreach ($vote as $voterID => $votes)
		{
			if ((($votercount % $rowlength) == 0))
			{
				$tables[$tablecount] .= "</tr>\n";
		
				$tablecount++;
	
				$tables[$tablecount] .= "<tr>\n<td bgcolor=\"#cccccc\">".($nominee + 1)."</td>\n";
			}
	
			$colour = "#ffffff";
		
			if ($votes[$nomineeID[$nominee]] == 1 && $vote[$voterID]['Valid'] == "valid") 
			{ 
				$colour = "#33ff66"; 
				$nomineeCount[$nominee][$round]++;
			}
		
			if ($vote[$voterID]['Valid'] == "invalid") 
			{ 
				$colour = "#ff9900"; 
			}
		
			$tables[$tablecount] .= "<td bgcolor=\"".$colour."\">".$votes[$nomineeID[$nominee]]."</td>\n";
	
			$votercount++;
		}
	
		$tables[$tablecount] .= "</tr>\n";
	}

	$output .= '<table cellpadding="2" cellspacing="0" border="1">'."\n";
	
	for ($table = 0; $table <= $tablecount; $table++)
	{	
		$output .= $tables[$table];
	}

	$output .= "</table>\n";

	//Step : Work out if we have a winner.

	$biggest = 0;
	$noscoreCount = 0;
	$biggestCount = 0;

	for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
	{
		if($nomineeCount[$nominee][$round] > $biggest)
		{
			$biggest = $nomineeCount[$nominee][$round];
			$biggestCount = 1;
		}
	
		else if ($nomineeCount[$nominee][$round] == $biggest)
		{
			$biggestCount++;
		}
	
		if ($nomineeCount[$nominee][$round] == 0)
		{
			$noscoreCount++;
		}
	}

	$lowest = $biggest;
	$lowestCount = 0;

	for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
	{
		if($nomineeCount[$nominee][$round] < $lowest && $nomineeCount[$nominee][$round] > 0)
		{
			$lowest = $nomineeCount[$nominee][$round];
			$lowestCount = 1;
		}
	
		else if ($nomineeCount[$nominee][$round] == $lowest)
		{
			$lowestCount++;
		}
	}

	$output .= '<br \><table cellpadding="2" cellspacing="0" border="1">'."\n<tr>\n<td><br /></td>\n";

	$round++;

	for ($roundnumber = 0; $roundnumber < $round; $roundnumber++)
	{
		$output .= "<td bgcolor=\"#cccccc\">Round ".($roundnumber + 1)."</td>\n";
	}

	$output .= "</tr>\n";

	for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
	{
		$output .= "<tr><td bgcolor=\"#cccccc\">".$nomineeDescription[$nominee]."</td>\n";
		for ($roundnumber = 0; $roundnumber < $round; $roundnumber++)
		{
			$output .= "<td";
		
			if ($roundnumber == $round - 1)
			{
				if ($nomineeCount[$nominee][$roundnumber] == $biggest) { $output .= " bgcolor=\"#33ff66\""; }
				if ($nomineeCount[$nominee][$roundnumber] == $lowest) { $output .= " bgcolor=\"#ff9900\""; }
			}
		
			$output .= ">".$nomineeCount[$nominee][$roundnumber]."</td>\n";
		}
		$output .= "</tr>\n";
	}

	$output .= "</table>\n";

	//Step : Report on the end of the first round.

	$output .= "<p>At the end of Round ".$round.", ";

	if ($biggestCount + $noscoreCount == $numberOfNominees)
	{
		if ($biggestCount == 1) { $output .= "there is a winner.</p>"; }
		if ($biggestCount > 1) { $output .= "there are ".$biggestCount." winners.</p>"; }
	
		$output .="<h3>Winner</h3>\n";
	
		$output .= "<ul>";
		
		for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
		{
			if ($nomineeCount[$nominee][$round-1] == $biggest) 
			{ 
				$output .= "<li>".$nomineeDescription[$nominee]."</li>\n";
			}
		}
		
		$output .= "</ul>\n";	
	
	
		$finished = true;
	}
	else
	{
		$output .= " there is no clear winner.</p>";

		if ($lowestCount >= 1)
		{	
			$lowestID = -1;
			$target = 0; // By default, we are going to remove the only nominee to get the lowest score.
			$targetCount = 0;
		
			if ($lowestCount > 1)
			{
				$output .= "<p>As there were ".$lowestCount." nominees with the lowest score, one will randomly be removed.<p>";
				$target = rand(0,$lowestCount-1);
			}
		
			for ($nominee = 0; $nominee < $numberOfNominees; $nominee++)
			{
				if ($nomineeCount[$nominee][$round-1] == $lowest) 
				{ 
					if ($targetCount == $target)
					{	
						$lowestID = $nominee; 
					}
					$targetCount++;
				}
			}
		
			$output .= "<p>Removing votes for ".$nomineeDescription[$lowestID].".</p>";
		
			// Code to remove votes.
		
			foreach ($vote as $voterID => $votes)
			{
				if ($vote[$voterID]['Valid'] == "invalid") 
				{
					unset($vote[$voterID]);
				}
				else
				{
					$found = false;
				
					$target = $votes[$nomineeID[$lowestID]];
				
					if ($target > 0)
					{
						$vote[$voterID][$nomineeID[$lowestID]] = 0;
				
						foreach($votes as $voteNomineeID => $voteScore)
						{
							if ($vote[$voterID][$voteNomineeID] >= $target)
							{
								$vote[$voterID][$voteNomineeID]--;
							}
					
							if ($vote[$voterID][$voteNomineeID] <= 0)
							{
								unset($vote[$voterID][$voteNomineeID]);
							}
						}
					}
				}
			}
		}
	}
}

// --------------------------------------------------------------------------------------

function removeNominee($vote, $nominee)
{
			// Code to remove votes.
		
			foreach ($vote as $voterID => $votes)
			{
				if ($vote[$voterID]['Valid'] == "invalid") 
				{
					unset($vote[$voterID]);
				}
				else
				{
					$found = false;
				
					$target = $votes[$nominee];
				
					if ($target > 0)
					{
						$vote[$voterID][$nominee] = 0;
				
						foreach($votes as $voteNomineeID => $voteScore)
						{
							if ($vote[$voterID][$voteNomineeID] >= $target)
							{
								$vote[$voterID][$voteNomineeID]--;
							}
					
							if ($vote[$voterID][$voteNomineeID] <= 0)
							{
								unset($vote[$voterID][$voteNomineeID]);
							}
						}
					}
				}
			}
			
			return $vote;
}


// --------------------------------------------------------------------------------------

function checkValidity($votes, $value)
{
	$validvotes = 0;
	
	foreach ($votes as $key => $vote)
	{
		if ($vote == $value)
		{
			++$validvotes;
		}
	}
	
	$result = "invalid";
	
	if ($validvotes == 1)
	{
		$result = "valid";
	}
	
	return $result;
}

?>