Skip to content

Instantly share code, notes, and snippets.

@MrsTonedOne
Created January 27, 2022 04:52
Show Gist options
  • Save MrsTonedOne/838d551036af7aae63499962e1633be4 to your computer and use it in GitHub Desktop.
Save MrsTonedOne/838d551036af7aae63499962e1633be4 to your computer and use it in GitHub Desktop.

Revisions

  1. MrsTonedOne created this gist Jan 27, 2022.
    136 changes: 136 additions & 0 deletions irvpolltallymorecomments.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,136 @@
    <?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);