You are here

function _advpoll_calculate_bordacount in Advanced Poll 6.3

Same name and namespace in other branches
  1. 5 modes/ranking.inc \_advpoll_calculate_bordacount()
  2. 6 modes/ranking.inc \_advpoll_calculate_bordacount()
  3. 6.2 modes/ranking.inc \_advpoll_calculate_bordacount()

Calculate the results using borda count.

Parameters

$node: The node object for the current poll.

Return value

Should return an object that include the following attributes -results : 2d array listing the aggregate preference, including ties -rounds : 2d array listing the per-choice vote count for each round and a status message indicating who was eliminated -totalVoters : the total number of voters who participated

1 call to _advpoll_calculate_bordacount()
advpoll_calculate_results_ranking in modes/ranking.inc
Calculate the results for a ranking poll based on the algorithm.

File

modes/ranking.inc, line 403
Handle ranking votes, e.g. choice A is preferred over choice B, which in turn is preferred over choice C.

Code

function _advpoll_calculate_bordacount($node) {
  $votes = array();

  // ORDER BY value ASC lets us ensure no gaps.
  $result = db_query("SELECT * FROM {votingapi_vote} v WHERE content_type = '%s' AND content_id = %d ORDER BY value ASC", 'advpoll', $node->nid);
  while ($vobj = db_fetch_object($result)) {
    $votes[] = $vobj;
  }
  if (count($votes) == 0) {

    // No votes yet.
    return array();
  }

  // Aggregate votes by user (uid if logged in, IP if anonymous)
  // in ascending order of value.
  $user_votes = array();
  foreach ($votes as $vote) {
    if ($vote->uid == 0) {

      // Anonymous user.
      $key = $vote->vote_source;
    }
    else {

      // Logged-in user.
      $key = $vote->uid;
    }
    $user_votes[$key][$vote->value] = $vote->tag;
  }
  $choice_votes = array();
  $total_choices = count($node->choice);
  $total_points = 0;

  // Loop through each user's vote
  foreach ($user_votes as $uid => $user_vote) {
    foreach ($user_vote as $ranking => $choice) {

      // Negative values are possible if choices were removed after vote
      $vote_value = max($total_choices - $ranking, 0);
      isset($choice_votes[$choice]) ? $choice_votes[$choice] += $vote_value : ($choice_votes[$choice] = $vote_value);
      $total_points += $vote_value;
    }
  }

  // Add any remaining choices that received no votes.
  foreach ($node->choice as $i => $choice) {
    if (!isset($choice_votes[$i])) {

      // Didn't receive any votes
      $choice_votes[$i] = 0;
    }
  }

  // Sort descending (although there may be ties).
  arsort($choice_votes);

  // Figure out the final ranking.
  $ranking = array();
  $previous_total = -1;
  $cur_result = -1;
  foreach ($choice_votes as $choice => $total) {
    if ($total != $previous_total) {

      // Didn't tie with the previous score.
      $cur_result++;
    }
    $ranking[$cur_result]['choices'][] = $choice;
    $ranking[$cur_result]['raw_score'] = $total;
    $ranking[$cur_result]['view_score'] = format_plural($total, '1 point', '@count points');
    $ranking[$cur_result]['percentage'] = $total_points ? $total / $total_points : 0;
    $previous_total = $total;
  }
  $total_votes = count($user_votes);
  $result_obj->ranking = $ranking;
  $result_obj->total_votes = $total_votes;
  $result_obj->total_points = $total_points;
  return $result_obj;
}