Differences Between: [Versions 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for (some of) /question/engine/statistics.php 19 * 20 * @package quiz_statistics 21 * @category phpunit 22 * @copyright 2008 Jamie Pratt 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 global $CFG; 29 require_once($CFG->libdir . '/questionlib.php'); 30 require_once($CFG->dirroot . '/mod/quiz/locallib.php'); 31 require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php'); 32 33 class testable_all_calculated_for_qubaid_condition extends \core_question\statistics\questions\all_calculated_for_qubaid_condition { 34 35 /** 36 * Disabling caching in tests so we are always sure to force the calculation of stats right then and there. 37 * 38 * @param qubaid_condition $qubaids 39 */ 40 public function cache($qubaids) { 41 42 } 43 } 44 45 /** 46 * Test helper subclass of question_statistics 47 * 48 * @copyright 2010 The Open University 49 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 50 */ 51 class testable_question_statistics extends \core_question\statistics\questions\calculator { 52 53 /** 54 * @var object[] 55 */ 56 protected $lateststeps; 57 58 protected $statscollectionclassname = 'testable_all_calculated_for_qubaid_condition'; 59 60 public function set_step_data($states) { 61 $this->lateststeps = $states; 62 } 63 64 protected function get_random_guess_score($questiondata) { 65 return 0; 66 } 67 68 /** 69 * @param $qubaids qubaid_condition is ignored in this test 70 * @return array with two items 71 * - $lateststeps array of latest step data for the question usages 72 * - $summarks array of total marks for each usage, indexed by usage id 73 */ 74 protected function get_latest_steps($qubaids) { 75 $summarks = array(); 76 $fakeusageid = 0; 77 foreach ($this->lateststeps as $step) { 78 // The same 'sumgrades' field is available in step data for every slot, we will ignore all slots but slot 1. 79 // The step for slot 1 is always the first one in the csv file for each usage, we will use that to separate steps from 80 // each usage. 81 if ($step->slot == 1) { 82 $fakeusageid++; 83 $summarks[$fakeusageid] = $step->sumgrades; 84 } 85 unset($step->sumgrades); 86 $step->questionusageid = $fakeusageid; 87 } 88 89 return array($this->lateststeps, $summarks); 90 } 91 92 protected function cache_stats($qubaids) { 93 // No caching wanted for tests. 94 } 95 } 96 /** 97 * Unit tests for (some of) question_statistics. 98 * 99 * @copyright 2008 Jamie Pratt 100 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 101 */ 102 class quiz_statistics_question_stats_testcase extends basic_testcase { 103 /** @var testable_all_calculated_for_qubaid_condition object created to test class. */ 104 protected $qstats; 105 106 public function test_qstats() { 107 global $CFG; 108 // Data is taken from randomly generated attempts data generated by 109 // contrib/tools/generators/qagenerator/. 110 $steps = $this->get_records_from_csv(__DIR__.'/fixtures/mdl_question_states.csv'); 111 // Data is taken from questions mostly generated by 112 // contrib/tools/generators/generator.php. 113 $questions = $this->get_records_from_csv(__DIR__.'/fixtures/mdl_question.csv'); 114 $calculator = new testable_question_statistics($questions); 115 $calculator->set_step_data($steps); 116 $this->qstats = $calculator->calculate(null); 117 118 // Values expected are taken from contrib/tools/quiz_tools/stats.xls. 119 $facility = array(0, 0, 0, 0, null, null, null, 41.19318182, 81.36363636, 120 71.36363636, 65.45454545, 65.90909091, 36.36363636, 59.09090909, 50, 121 59.09090909, 63.63636364, 45.45454545, 27.27272727, 50); 122 $this->qstats_q_fields('facility', $facility, 100); 123 $sd = array(0, 0, 0, 0, null, null, null, 1912.733589, 251.2738111, 124 322.6312277, 333.4199022, 337.5811591, 492.3659639, 503.2362797, 125 511.7663157, 503.2362797, 492.3659639, 509.6471914, 455.8423058, 511.7663157); 126 $this->qstats_q_fields('sd', $sd, 1000); 127 $effectiveweight = array(0, 0, 0, 0, 0, 0, 0, 26.58464457, 3.368456046, 128 3.253955259, 7.584083694, 3.79658376, 3.183278505, 4.532356904, 129 7.78856243, 10.08351572, 8.381139345, 8.727645713, 7.946277111, 4.769500946); 130 $this->qstats_q_fields('effectiveweight', $effectiveweight); 131 $discriminationindex = array(null, null, null, null, null, null, null, 132 25.88327077, 1.170256965, -4.207816809, 28.16930644, -2.513606859, 133 -12.99017581, -8.900638238, 8.670004606, 29.63337745, 15.18945843, 134 16.21079629, 15.52451404, -8.396734802); 135 $this->qstats_q_fields('discriminationindex', $discriminationindex); 136 $discriminativeefficiency = array(null, null, null, null, null, null, null, 137 27.23492723, 1.382386552, -4.691171307, 31.12404354, -2.877487579, 138 -17.5074184, -10.27568922, 10.86956522, 34.58997279, 17.4790556, 139 20.14359793, 22.06477733, -10); 140 $this->qstats_q_fields('discriminativeefficiency', $discriminativeefficiency); 141 } 142 143 public function qstats_q_fields($fieldname, $values, $multiplier=1) { 144 foreach ($this->qstats->get_all_slots() as $slot) { 145 $value = array_shift($values); 146 if ($value !== null) { 147 $this->assertEqualsWithDelta($value, $this->qstats->for_slot($slot)->{$fieldname} * $multiplier, 1E-6); 148 } else { 149 $this->assertEquals($value, $this->qstats->for_slot($slot)->{$fieldname} * $multiplier); 150 } 151 } 152 } 153 154 public function get_fields_from_csv($line) { 155 $line = trim($line); 156 $items = preg_split('!,!', $line); 157 $cnt = count($items); 158 for ($key = 0; $key < $cnt; $key++) { 159 if ($items[$key]!='') { 160 if ($start = ($items[$key][0]=='"')) { 161 $items[$key] = substr($items[$key], 1); 162 while (!$end = ($items[$key][strlen($items[$key])-1]=='"')) { 163 $item = $items[$key]; 164 unset($items[$key]); 165 $key++; 166 $items[$key] = $item . ',' . $items[$key]; 167 } 168 $items[$key] = substr($items[$key], 0, strlen($items[$key])-1); 169 } 170 171 } 172 } 173 return $items; 174 } 175 176 public function get_records_from_csv($filename) { 177 $filecontents = file($filename, FILE_IGNORE_NEW_LINES); 178 $records = array(); 179 // Skip the first line containing field names. 180 $keys = $this->get_fields_from_csv(array_shift($filecontents)); 181 while (null !== ($line = array_shift($filecontents))) { 182 $data = $this->get_fields_from_csv($line); 183 $arraykey = reset($data); 184 $object = new stdClass(); 185 foreach ($keys as $key) { 186 $value = array_shift($data); 187 if ($value !== null) { 188 $object->{$key} = $value; 189 } else { 190 $object->{$key} = ''; 191 } 192 } 193 $records[$arraykey] = $object; 194 } 195 return $records; 196 } 197 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body