You are here

function quiz_calculate_score in Quiz 7

Same name and namespace in other branches
  1. 8.4 quiz.module \quiz_calculate_score()
  2. 5.2 quiz.module \quiz_calculate_score()
  3. 5 quiz.module \quiz_calculate_score()
  4. 6.6 quiz.module \quiz_calculate_score()
  5. 6.2 quiz.module \quiz_calculate_score()
  6. 6.3 quiz.module \quiz_calculate_score()
  7. 6.4 quiz.module \quiz_calculate_score()
  8. 6.5 quiz.module \quiz_calculate_score()
  9. 7.6 quiz.module \quiz_calculate_score()
  10. 7.4 quiz.module \quiz_calculate_score()
  11. 7.5 quiz.module \quiz_calculate_score()

Calculates the score user received on quiz.

Parameters

$quiz: The quiz node.

$rid: Quiz result ID.

Return value

array Contains three elements: question_count, num_correct and percentage_score.

Related topics

4 calls to quiz_calculate_score()
quiz_admin_results in ./quiz.admin.inc
Quiz result report page for the quiz admin section
quiz_end_scoring in ./quiz.module
Score a completed quiz.
quiz_update_total_score in ./quiz.module
Update a score for a quiz.
quiz_user_results in ./quiz.pages.inc
Show result page for a given result id

File

./quiz.module, line 2709
Quiz Module

Code

function quiz_calculate_score($quiz, $rid) {

  // 1. Fetch all questions and their max scores
  $questions = db_query('SELECT a.question_nid, a.question_vid, n.type, r.max_score
    FROM {quiz_node_results_answers} a
    LEFT JOIN {node} n ON (question_nid = nid)
    LEFT OUTER JOIN {quiz_node_relationship} r ON (r.child_vid = a.question_vid) AND r.parent_vid = :vid
    WHERE result_id = :rid', array(
    ':vid' => $quiz->vid,
    ':rid' => $rid,
  ));

  // 2. Callback into the modules and let them do the scoring. @todo after 4.0: Why isn't the scores already saved? They should be
  // Fetched from the db, not calculated....
  $scores = array();
  $count = 0;
  foreach ($questions as $question) {

    // Questions picked from term id's won't be found in the quiz_node_relationship table
    if ($question->max_score === NULL && isset($quiz->tid) && $quiz->tid > 0) {
      $question->max_score = $quiz->max_score_for_random;
    }

    // Invoke hook_quiz_question_score().
    // We don't use module_invoke() because (1) we don't necessarily want to wed
    // quiz type to module, and (2) this is more efficient (no NULL checks).
    $mod = quiz_question_module_for_type($question->type);
    if (!$mod) {
      continue;
    }
    $function = $mod . '_quiz_question_score';
    if (function_exists($function)) {
      $score = $function($quiz, $question->question_nid, $question->question_vid, $rid);

      // Allow for max score to be considered.
      $scores[] = $score;
    }
    else {
      drupal_set_message(t('A quiz question could not be scored: No scoring info is available'), 'error');
      $dummy_score = new stdClass();
      $dummy_score->possible = 0;
      $dummy_score->attained = 0;
      $scores[] = $dummy_score;
    }
    ++$count;
  }

  // 3. Sum the results.
  $possible_score = 0;
  $total_score = 0;
  $is_evaluated = TRUE;
  foreach ($scores as $score) {
    $possible_score += $score->possible;
    $total_score += $score->attained;
    if (isset($score->is_evaluated)) {

      // Flag the entire quiz if one question has not been evaluated.
      $is_evaluated &= $score->is_evaluated;
    }
  }

  // 4. Return the score.
  return array(
    'question_count' => $count,
    'possible_score' => $possible_score,
    'numeric_score' => $total_score,
    'percentage_score' => $possible_score == 0 ? 0 : round($total_score * 100 / $possible_score),
    'is_evaluated' => $is_evaluated,
  );
}