AutorÃa | Ultima modificación | Ver Log |
<?php// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** Question behaviour type for deferred feedback with CBM behaviour.** @package qbehaviour_deferredcbm* @copyright 2012 The Open University* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/defined('MOODLE_INTERNAL') || die();require_once(__DIR__ . '/../deferredfeedback/behaviourtype.php');/*** Question behaviour type information for deferred feedback with CBM behaviour.** @copyright 2012 The Open University* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later*/class qbehaviour_deferredcbm_type extends qbehaviour_deferredfeedback_type {public function adjust_random_guess_score($fraction) {return question_cbm::adjust_fraction($fraction, question_cbm::default_certainty());}public function summarise_usage(question_usage_by_activity $quba, question_display_options $options) {global $OUTPUT;$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() < 0.0000005) {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;// Add a note to explain the max mark.$summarydata['qbehaviour_cbm_grade_explanation'] = array('title' => '','content' => html_writer::tag('i', get_string('cbmgradeexplanation', 'qbehaviour_deferredcbm')) .$OUTPUT->help_icon('cbmgrades', 'qbehaviour_deferredcbm'),);// 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 - 0.0000005) {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 + 0.0000005) {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;}protected function format_probability($probability, $dp = 0) {return format_float($probability * 100, $dp) . '%';}public function calculate_bonus($total, $accuracy) {$expectedforaccuracy = max($accuracy * question_cbm::adjust_fraction(1, question_cbm::LOW) +(1 - $accuracy) * question_cbm::adjust_fraction(0, question_cbm::LOW),$accuracy * question_cbm::adjust_fraction(1, question_cbm::MED) +(1 - $accuracy) * question_cbm::adjust_fraction(0, question_cbm::MED),$accuracy * question_cbm::adjust_fraction(1, question_cbm::HIGH) +(1 - $accuracy) * question_cbm::adjust_fraction(0, question_cbm::HIGH));// The constant 0.1 here is determinted empirically from looking at lots// for CBM quiz results. See www.ucl.ac.uk/~ucgbarg/tea/IUPS_2013a.pdf.// It approximately maximises the reliability of accuracy + bonus.return 0.1 * ($total - $expectedforaccuracy);}}