You are here

function quiz_calculate_score in Quiz 6.4

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.5 quiz.module \quiz_calculate_score()
  8. 7.6 quiz.module \quiz_calculate_score()
  9. 7 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 2581
Quiz Module

Code

function quiz_calculate_score($quiz, $rid) {

  // 1. Fetch all questions and their max scores
  $sql = 'SELECT a.question_nid, a.question_vid, n.type, r.max_score, qt.max_score as term_max_score
  FROM {quiz_node_results_answers} a
  LEFT JOIN {node} n ON (a.question_nid = n.nid)
  LEFT OUTER JOIN {quiz_node_relationship} r ON (r.child_vid = a.question_vid AND r.parent_vid = %d)
  LEFT OUTER JOIN {quiz_terms} qt ON (a.tid = qt.tid AND qt.vid = %d)
  WHERE a.result_id = %d';
  $results = db_query($sql, $quiz->vid, $quiz->vid, $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;
  while ($question = db_fetch_object($results)) {

    // Questions picked from term id's won't be found in the quiz_node_relationship table
    if ($question->max_score === NULL) {
      if ($quiz->randomization == 3 && $question->term_max_score !== NULL) {
        $question->max_score = $question->term_max_score;
      }
      elseif (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);
      if ($score->possible != $question->max_score) {
        $score_weight = $score->possible > 0 ? $question->max_score / $score->possible : 0;
        $score->possible = $question->max_score;
        $score->attained *= $score_weight;
      }
      $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,
  );
}