public function summarise_usage(question_usage_by_activity $quba, question_display_options $options)
 {
     $summarydata = parent::summarise_usage($quba, $options);
     if ($options->marks < question_display_options::MARK_AND_MAX) {
         return $summarydata;
     }
     // Prepare accumulators to hold the data we are about to collect.
     $notansweredcount = 0;
     $notansweredweight = 0;
     $attemptcount = array(question_cbm::HIGH => 0, question_cbm::MED => 0, question_cbm::LOW => 0);
     $totalweight = array(question_cbm::HIGH => 0, question_cbm::MED => 0, question_cbm::LOW => 0);
     $totalrawscore = array(question_cbm::HIGH => 0, question_cbm::MED => 0, question_cbm::LOW => 0);
     $totalcbmscore = array(question_cbm::HIGH => 0, question_cbm::MED => 0, question_cbm::LOW => 0);
     // Loop through the data, and add it to the accumulators.
     foreach ($quba->get_attempt_iterator() as $qa) {
         if (strpos($qa->get_behaviour_name(), 'cbm') === false || $qa->get_max_mark() < 5.0E-7) {
             continue;
         }
         $gradedstep = $qa->get_last_step_with_behaviour_var('_rawfraction');
         if (!$gradedstep->has_behaviour_var('_rawfraction')) {
             $notansweredcount += 1;
             $notansweredweight += $qa->get_max_mark();
             continue;
         }
         $certainty = $qa->get_last_behaviour_var('certainty');
         if (is_null($certainty) || $certainty == -1) {
             // Certainty -1 has never been used in standard Moodle, but is
             // used in Tony-Gardiner Medwin's patches to mean 'No idea' which
             // we intend to implement: MDL-42077. In the mean time, avoid
             // errors for people who have used TGM's patches.
             $certainty = question_cbm::default_certainty();
         }
         $attemptcount[$certainty] += 1;
         $totalweight[$certainty] += $qa->get_max_mark();
         $totalrawscore[$certainty] += $qa->get_max_mark() * $gradedstep->get_behaviour_var('_rawfraction');
         $totalcbmscore[$certainty] += $qa->get_mark();
     }
     // Hence compute some statistics.
     $totalquestions = $notansweredcount + array_sum($attemptcount);
     $grandtotalweight = $notansweredweight + array_sum($totalweight);
     $accuracy = array_sum($totalrawscore) / $grandtotalweight;
     $averagecbm = array_sum($totalcbmscore) / $grandtotalweight;
     $cbmbonus = $this->calculate_bonus($averagecbm, $accuracy);
     $accuracyandbonus = $accuracy + $cbmbonus;
     // Now we can start generating some of the summary: overall values.
     $summarydata['qbehaviour_cbm_entire_quiz_heading'] = array('title' => '', 'content' => html_writer::tag('h3', get_string('forentirequiz', 'qbehaviour_deferredcbm', $totalquestions), array('class' => 'qbehaviour_deferredcbm_summary_heading')));
     $summarydata['qbehaviour_cbm_entire_quiz_cbm_average'] = array('title' => get_string('averagecbmmark', 'qbehaviour_deferredcbm'), 'content' => format_float($averagecbm, $options->markdp));
     $summarydata['qbehaviour_cbm_entire_quiz_accuracy'] = array('title' => get_string('accuracy', 'qbehaviour_deferredcbm'), 'content' => $this->format_probability($accuracy, 1));
     $summarydata['qbehaviour_cbm_entire_quiz_cbm_bonus'] = array('title' => get_string('cbmbonus', 'qbehaviour_deferredcbm'), 'content' => $this->format_probability($cbmbonus, 1));
     $summarydata['qbehaviour_cbm_entire_quiz_accuracy_and_bonus'] = array('title' => get_string('accuracyandbonus', 'qbehaviour_deferredcbm'), 'content' => $this->format_probability($accuracyandbonus, 1));
     if ($notansweredcount && array_sum($attemptcount) > 0) {
         $totalquestions = array_sum($attemptcount);
         $grandtotalweight = array_sum($totalweight);
         $accuracy = array_sum($totalrawscore) / $grandtotalweight;
         $averagecbm = array_sum($totalcbmscore) / $grandtotalweight;
         $cbmbonus = $this->calculate_bonus($averagecbm, $accuracy);
         $accuracyandbonus = $accuracy + $cbmbonus;
         $summarydata['qbehaviour_cbm_answered_quiz_heading'] = array('title' => '', 'content' => html_writer::tag('h3', get_string('foransweredquestions', 'qbehaviour_deferredcbm', $totalquestions), array('class' => 'qbehaviour_deferredcbm_summary_heading')));
         $summarydata['qbehaviour_cbm_answered_quiz_cbm_average'] = array('title' => get_string('averagecbmmark', 'qbehaviour_deferredcbm'), 'content' => format_float($averagecbm, $options->markdp));
         $summarydata['qbehaviour_cbm_answered_quiz_accuracy'] = array('title' => get_string('accuracy', 'qbehaviour_deferredcbm'), 'content' => $this->format_probability($accuracy, 1));
         $summarydata['qbehaviour_cbm_answered_quiz_cbm_bonus'] = array('title' => get_string('cbmbonus', 'qbehaviour_deferredcbm'), 'content' => $this->format_probability($cbmbonus, 1));
         $summarydata['qbehaviour_cbm_answered_quiz_accuracy_and_bonus'] = array('title' => get_string('accuracyandbonus', 'qbehaviour_deferredcbm'), 'content' => $this->format_probability($accuracyandbonus, 1));
     }
     // Now per-certainty level values.
     $summarydata['qbehaviour_cbm_judgement_heading'] = array('title' => '', 'content' => html_writer::tag('h3', get_string('breakdownbycertainty', 'qbehaviour_deferredcbm'), array('class' => 'qbehaviour_deferredcbm_summary_heading')));
     foreach ($attemptcount as $certainty => $count) {
         $key = 'qbehaviour_cbm_judgement' . $certainty;
         $title = question_cbm::get_short_string($certainty);
         if ($count == 0) {
             $summarydata[$key] = array('title' => $title, 'content' => get_string('noquestions', 'qbehaviour_deferredcbm'));
             continue;
         }
         $lowerlimit = question_cbm::optimal_probablility_low($certainty);
         $upperlimit = question_cbm::optimal_probablility_high($certainty);
         $fraction = $totalrawscore[$certainty] / $totalweight[$certainty];
         $a = new stdClass();
         $a->responses = $count;
         $a->idealrangelow = $this->format_probability($lowerlimit);
         $a->idealrangehigh = $this->format_probability($upperlimit);
         $a->fraction = html_writer::tag('span', $this->format_probability($fraction), array('class' => 'qbehaviour_deferredcbm_actual_percentage'));
         if ($fraction < $lowerlimit - 5.0E-7) {
             if (pow($fraction - $lowerlimit, 2) * $count > 0.5) {
                 // Rough indicator of significance: t > 1.5 or 1.8.
                 $judgement = 'overconfident';
             } else {
                 $judgement = 'slightlyoverconfident';
             }
         } else {
             if ($fraction > $upperlimit + 5.0E-7) {
                 if (pow($fraction - $upperlimit, 2) * $count > 0.5) {
                     $judgement = 'underconfident';
                 } else {
                     $judgement = 'slightlyunderconfident';
                 }
             } else {
                 $judgement = 'judgementok';
             }
         }
         $a->judgement = html_writer::tag('span', get_string($judgement, 'qbehaviour_deferredcbm'), array('class' => 'qbehaviour_deferredcbm_' . $judgement));
         $summarydata[$key] = array('title' => $title, 'content' => get_string('judgementsummary', 'qbehaviour_deferredcbm', $a));
     }
     return $summarydata;
 }
 public function test_adjust_random_guess_score()
 {
     $this->assertEquals(0, $this->behaviourtype->adjust_random_guess_score(0));
     $this->assertEquals(1, $this->behaviourtype->adjust_random_guess_score(1));
 }