Skip to content

Instantly share code, notes, and snippets.

@MrStonedOne
Created January 27, 2022 04:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MrStonedOne/838d551036af7aae63499962e1633be4 to your computer and use it in GitHub Desktop.
Save MrStonedOne/838d551036af7aae63499962e1633be4 to your computer and use it in GitHub Desktop.
<?php
//Record the votes:
$votes = array(); //array of ckeys assoicated to an array of dicts with vote metadata for each pick the player picked
$candidates = array(); //array of dicts
//grab each vote from the db
while ($row = $res->fetch_assoc()) {
$vote = array();
$ckey = $row['ckey'];
$cid = $row['optionid'];
$cname = $row['text'];
$vid = $row['id']; //saved because the voteid is used to determine their ranked choice ordering
//is this the first vote we've seen for a given candidate?
if (!isset($candidates[$cid])) {
//set up their metadata array for use later
$candidates[$cid] = array();
$candidates[$cid]['CANDIDATE'] = $cname;
$candidates[$cid]['CANDIDATE_ID'] = $cid;
$candidates[$cid]['VOTES'] = 0;
$candidates[$cid]['VALUE'] = 0;
$candidates[$cid]['VALUE_STR'] = '';
}
//is this the first vote we've processed for this ckey?
if (!isset($votes[$ckey]))
$votes[$ckey] = array();
$vote['CID'] = $cid;
$vote['ID'] = $vid;
$votes[$ckey][$cid] = $vote;
}
$res->free();
//This function will handle sorting candidates by their first picks.
$candidatecmp = function ($a, $b) {
global $totalsort, $reversesort;
if ($reversesort) {
$aa = $a;
$a = $b;
$b = $aa;
}
if ($totalsort)
return $b['VALUE'] - $a['VALUE'];
if ($b['VOTES'] == $a['VOTES']) {
if ($b['VALUE'] == $a['VALUE'])
return 0;
$val = $b['VALUE'] - $a['VALUE'];
while ($val < 1 && $val > -1)
$val *= 10;
return $val;
}
return $b['VOTES'] - $a['VOTES'];
};
//this function handles making sure a user's votes are sorted by their ranked choice
$votecmp = function ($a, $b) {
return $a['ID'] - $b['ID'] ;
};
//tie breaker record keeping
$initalvalue = count($candidates);
//first round special prep code: loop thru each user who voted
foreach ($votes as &$vote) {
//sort their picks to match how the user sorted them when voting
if (!uasort($vote, $votecmp))
die ('Error sorting votes');
//record their top pick on the candidate's array.
$candidates[array_keys($vote)[0]]['VOTES']++;
//tie breaker record keeping
$value = $initalvalue;
foreach ($vote as $pick => $array) {
$candidates[$pick]['VALUE'] += $value;
if ($lineartotal)
$value -= 1;
else
$value /= 2;
}
}
//sort candidates by the number of top picks they got.
if (!uasort($candidates, $candidatecmp))
die ('Error sorting canidate list');
//round the tie breaker metric into a new datafield for displaying to the user.
foreach ($candidates as &$candidate) {
$candidate['VALUE_STR'] = round($candidate['VALUE']);
}
$roundcount = 0;
$rounds = array();
//set up the first "round".
$round = array();
$round['ROUND_NUMBER'] = ++$roundcount;
$round['IPV_ROUND_RES'] = $candidates;
$rounds[] = $round;
if ($finalize) //save it to the database if told to do so.
submit_finalized_round($candidates, $finalize_token, $id, $roundcount);
//kill off the bottom candidate and re-sort as long as there are mutiple candidates.
while (count($candidates) > 1) {
$round = array();
$round['ROUND_NUMBER'] = ++$roundcount;
//grab the bottom candidate
$loser = array_keys($candidates)[count($candidates)-1];
//reset the 'votes gained this round' metric from what it was to 0
foreach($candidates as &$candidate) {
$candidate['DIFF'] = 0;
}
//go thru each player and see if their top pick is the loser.
foreach ($votes as &$vote) {
if (array_keys($vote)[0] == $loser) {
unset($vote[$loser]); //remove their vote for the loser.
$candidates[array_keys($vote)[0]]['VOTES']++; //look at who the new top pick is, and add one to that candidate's top pick count.
$candidates[array_keys($vote)[0]]['DIFF']++; //also add one to said candidate's 'votes gain this round' metric
} else { //they picked somebody else, but we still got to remove the loser from their priority list.
unset($vote[$loser]);
}
}
//delete the loser.
unset($candidates[$loser]);
//resort the candidate by number of top picks.
if (!uasort($candidates, $candidatecmp))
die ('Error sorting candidate list');
//save the the new sorted candidate list to the round.
$round['IPV_ROUND_RES'] = $candidates;
//save this round to the list of rounds.
$rounds[] = $round;
if ($finalize) //save this round to the database if requested to do so.
submit_finalized_round($candidates, $finalize_token, $id, $roundcount);
}
//make the rounds list available to the html engine.
$tpl->setvar('IPV_ROUNDS', $rounds);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment