Differences Between: [Versions 400 and 402] [Versions 401 and 402] [Versions 402 and 403]
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 namespace qbank_statistics; 18 19 use core_question\statistics\questions\all_calculated_for_qubaid_condition; 20 use quiz_statistics\tests\statistics_helper; 21 use mod_quiz\quiz_attempt; 22 use mod_quiz\quiz_settings; 23 use question_engine; 24 25 /** 26 * Tests for question statistics. 27 * 28 * @package qbank_statistics 29 * @copyright 2021 Catalyst IT Australia Pty Ltd 30 * @author Nathan Nguyen <nathannguyen@catalyst-au.net> 31 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 */ 33 class helper_test extends \advanced_testcase { 34 35 /** 36 * Test quizzes that contain a specified question. 37 * 38 * @covers ::get_all_places_where_questions_were_attempted 39 * @throws \coding_exception 40 * @throws \dml_exception 41 */ 42 public function test_get_all_places_where_questions_were_attempted(): void { 43 $this->resetAfterTest(); 44 $this->setAdminUser(); 45 46 $rcm = new \ReflectionMethod(helper::class, 'get_all_places_where_questions_were_attempted'); 47 $rcm->setAccessible(true); 48 49 // Create a course. 50 $course = $this->getDataGenerator()->create_course(); 51 52 // Create three quizzes. 53 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 54 $quiz1 = $quizgenerator->create_instance([ 55 'course' => $course->id, 56 'grade' => 100.0, 'sumgrades' => 2, 57 'layout' => '1,2,0' 58 ]); 59 $quiz1context = \context_module::instance($quiz1->cmid); 60 61 $quiz2 = $quizgenerator->create_instance([ 62 'course' => $course->id, 63 'grade' => 100.0, 'sumgrades' => 2, 64 'layout' => '1,2,0' 65 ]); 66 $quiz2context = \context_module::instance($quiz2->cmid); 67 68 $quiz3 = $quizgenerator->create_instance([ 69 'course' => $course->id, 70 'grade' => 100.0, 'sumgrades' => 2, 71 'layout' => '1,2,0' 72 ]); 73 $quiz3context = \context_module::instance($quiz3->cmid); 74 75 // Create questions. 76 /** @var \core_question_generator $questiongenerator */ 77 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 78 $cat = $questiongenerator->create_question_category(); 79 $question1 = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id)); 80 $question2 = $questiongenerator->create_question('numerical', null, array('category' => $cat->id)); 81 82 // Add question 1 to quiz 1 and make an attempt. 83 quiz_add_quiz_question($question1->id, $quiz1); 84 // Quiz 1 attempt. 85 $this->submit_quiz($quiz1, [1 => ['answer' => 'frog']]); 86 87 // Add questions 1 and 2 to quiz 2. 88 quiz_add_quiz_question($question1->id, $quiz2); 89 quiz_add_quiz_question($question2->id, $quiz2); 90 $this->submit_quiz($quiz2, [1 => ['answer' => 'frog'], 2 => ['answer' => 10]]); 91 92 // Checking quizzes that use question 1. 93 $q1places = $rcm->invoke(null, [$question1->id]); 94 $this->assertCount(2, $q1places); 95 $this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz1context->id], $q1places[0]); 96 $this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz2context->id], $q1places[1]); 97 98 // Checking quizzes that contain question 2. 99 $q2places = $rcm->invoke(null, [$question2->id]); 100 $this->assertCount(1, $q2places); 101 $this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz2context->id], $q2places[0]); 102 103 // Add a random question to quiz3. 104 quiz_add_random_questions($quiz3, 0, $cat->id, 1, false); 105 $this->submit_quiz($quiz3, [1 => ['answer' => 'willbewrong']]); 106 107 // Quiz 3 will now be in one of these arrays. 108 $q1places = $rcm->invoke(null, [$question1->id]); 109 $q2places = $rcm->invoke(null, [$question2->id]); 110 if (count($q1places) == 3) { 111 $newplace = end($q1places); 112 } else { 113 $newplace = end($q2places); 114 } 115 $this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz3context->id], $newplace); 116 } 117 118 /** 119 * Create 2 quizzes. 120 * 121 * @return array return 2 quizzes 122 * @throws \coding_exception 123 */ 124 private function prepare_quizzes(): array { 125 // Create a course. 126 $course = $this->getDataGenerator()->create_course(); 127 128 // Make 2 quizzes. 129 $quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz'); 130 $layout = '1,2,0,3,4,0'; 131 $quiz1 = $quizgenerator->create_instance([ 132 'course' => $course->id, 133 'grade' => 100.0, 'sumgrades' => 2, 134 'layout' => $layout 135 ]); 136 137 $quiz2 = $quizgenerator->create_instance([ 138 'course' => $course->id, 139 'grade' => 100.0, 'sumgrades' => 2, 140 'layout' => $layout 141 ]); 142 143 /** @var \core_question_generator $questiongenerator */ 144 $questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question'); 145 $cat = $questiongenerator->create_question_category(); 146 147 $page = 1; 148 $questions = []; 149 foreach (explode(',', $layout) as $slot) { 150 if ($slot == 0) { 151 $page += 1; 152 continue; 153 } 154 155 $question = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]); 156 $questions[$slot] = $question; 157 quiz_add_quiz_question($question->id, $quiz1, $page); 158 quiz_add_quiz_question($question->id, $quiz2, $page); 159 } 160 161 return [$quiz1, $quiz2, $questions]; 162 } 163 164 /** 165 * Submit quiz answers 166 * 167 * @param object $quiz 168 * @param array $answers 169 * @throws \moodle_exception 170 */ 171 private function submit_quiz(object $quiz, array $answers): void { 172 // Create user. 173 $user = $this->getDataGenerator()->create_user(); 174 // Create attempt. 175 $quizobj = quiz_settings::create($quiz->id, $user->id); 176 $quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context()); 177 $quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour); 178 $timenow = time(); 179 $attempt = quiz_create_attempt($quizobj, 1, null, $timenow, false, $user->id); 180 quiz_start_new_attempt($quizobj, $quba, $attempt, 1, $timenow); 181 quiz_attempt_save_started($quizobj, $quba, $attempt); 182 // Submit attempt. 183 $attemptobj = quiz_attempt::create($attempt->id); 184 $attemptobj->process_submitted_actions($timenow, false, $answers); 185 $attemptobj->process_finish($timenow, false); 186 } 187 188 /** 189 * Generate attempt answers. 190 * 191 * @param array $correctanswerflags array of 1 or 0 192 * 1 : generate correct answer 193 * 0 : generate wrong answer 194 * 195 * @return array 196 */ 197 private function generate_attempt_answers(array $correctanswerflags): array { 198 $attempt = []; 199 for ($i = 1; $i <= 4; $i++) { 200 if (isset($correctanswerflags) && $correctanswerflags[$i - 1] == 1) { 201 // Correct answer. 202 $attempt[$i] = ['answer' => 'frog']; 203 } else { 204 $attempt[$i] = ['answer' => 'false']; 205 } 206 } 207 return $attempt; 208 } 209 210 /** 211 * 212 * Generate quizzes and submit answers. 213 * 214 * @param array $quiz1attempts quiz 1 attempts 215 * @param array $quiz2attempts quiz 2 attempts 216 * 217 * @return array 218 */ 219 private function prepare_and_submit_quizzes(array $quiz1attempts, array $quiz2attempts): array { 220 list($quiz1, $quiz2, $questions) = $this->prepare_quizzes(); 221 // Submit attempts of quiz1. 222 foreach ($quiz1attempts as $attempt) { 223 $this->submit_quiz($quiz1, $attempt); 224 } 225 // Submit attempts of quiz2. 226 foreach ($quiz2attempts as $attempt) { 227 $this->submit_quiz($quiz2, $attempt); 228 } 229 230 // Calculate the statistics. 231 $this->expectOutputRegex('~.*Calculations completed.*~'); 232 statistics_helper::run_pending_recalculation_tasks(); 233 234 return [$quiz1, $quiz2, $questions]; 235 } 236 237 /** 238 * To use private helper::extract_item_value function. 239 * 240 * @param all_calculated_for_qubaid_condition $statistics the batch of statistics. 241 * @param int $questionid a question id. 242 * @param string $item ane of the field names in all_calculated_for_qubaid_condition, e.g. 'facility'. 243 * @return float|null the required value. 244 */ 245 private function extract_item_value(all_calculated_for_qubaid_condition $statistics, 246 int $questionid, string $item): ?float { 247 $rcm = new \ReflectionMethod(helper::class, 'extract_item_value'); 248 $rcm->setAccessible(true); 249 return $rcm->invoke(null, $statistics, $questionid, $item); 250 } 251 252 /** 253 * To use private helper::load_statistics_for_place function (with mod_quiz component). 254 * 255 * @param \context $context the context to load the statistics for. 256 * @return all_calculated_for_qubaid_condition|null question statistics. 257 */ 258 private function load_quiz_statistics_for_place(\context $context): ?all_calculated_for_qubaid_condition { 259 $rcm = new \ReflectionMethod(helper::class, 'load_statistics_for_place'); 260 $rcm->setAccessible(true); 261 return $rcm->invoke(null, 'mod_quiz', $context); 262 } 263 264 /** 265 * Data provider for {@see test_load_question_facility()}. 266 * 267 * @return \Generator 268 */ 269 public function load_question_facility_provider(): \Generator { 270 yield 'Facility case 1' => [ 271 'Quiz 1 attempts' => [ 272 $this->generate_attempt_answers([1, 0, 0, 0]), 273 ], 274 'Expected quiz 1 facilities' => ['100.00%', '0.00%', '0.00%', '0.00%'], 275 'Quiz 2 attempts' => [ 276 $this->generate_attempt_answers([1, 0, 0, 0]), 277 $this->generate_attempt_answers([1, 1, 0, 0]), 278 ], 279 'Expected quiz 2 facilities' => ['100.00%', '50.00%', '0.00%', '0.00%'], 280 'Expected average facilities' => ['100.00%', '25.00%', '0.00%', '0.00%'], 281 ]; 282 yield 'Facility case 2' => [ 283 'Quiz 1 attempts' => [ 284 $this->generate_attempt_answers([1, 0, 0, 0]), 285 $this->generate_attempt_answers([1, 1, 0, 0]), 286 $this->generate_attempt_answers([1, 1, 1, 0]), 287 ], 288 'Expected quiz 1 facilities' => ['100.00%', '66.67%', '33.33%', '0.00%'], 289 'Quiz 2 attempts' => [ 290 $this->generate_attempt_answers([1, 0, 0, 0]), 291 $this->generate_attempt_answers([1, 1, 0, 0]), 292 $this->generate_attempt_answers([1, 1, 1, 0]), 293 $this->generate_attempt_answers([1, 1, 1, 1]), 294 ], 295 'Expected quiz 2 facilities' => ['100.00%', '75.00%', '50.00%', '25.00%'], 296 'Expected average facilities' => ['100.00%', '70.83%', '41.67%', '12.50%'], 297 ]; 298 } 299 300 /** 301 * Test question facility 302 * 303 * @dataProvider load_question_facility_provider 304 * 305 * @param array $quiz1attempts quiz 1 attempts 306 * @param array $expectedquiz1facilities expected quiz 1 facilities 307 * @param array $quiz2attempts quiz 2 attempts 308 * @param array $expectedquiz2facilities expected quiz 2 facilities 309 * @param array $expectedaveragefacilities expected average facilities 310 */ 311 public function test_load_question_facility( 312 array $quiz1attempts, 313 array $expectedquiz1facilities, 314 array $quiz2attempts, 315 array $expectedquiz2facilities, 316 array $expectedaveragefacilities) 317 : void { 318 $this->resetAfterTest(); 319 320 list($quiz1, $quiz2, $questions) = $this->prepare_and_submit_quizzes($quiz1attempts, $quiz2attempts); 321 322 // Quiz 1 facilities. 323 $stats = $this->load_quiz_statistics_for_place(\context_module::instance($quiz1->cmid)); 324 $quiz1facility1 = $this->extract_item_value($stats, $questions[1]->id, 'facility'); 325 $quiz1facility2 = $this->extract_item_value($stats, $questions[2]->id, 'facility'); 326 $quiz1facility3 = $this->extract_item_value($stats, $questions[3]->id, 'facility'); 327 $quiz1facility4 = $this->extract_item_value($stats, $questions[4]->id, 'facility'); 328 329 $this->assertEquals($expectedquiz1facilities[0], helper::format_percentage($quiz1facility1)); 330 $this->assertEquals($expectedquiz1facilities[1], helper::format_percentage($quiz1facility2)); 331 $this->assertEquals($expectedquiz1facilities[2], helper::format_percentage($quiz1facility3)); 332 $this->assertEquals($expectedquiz1facilities[3], helper::format_percentage($quiz1facility4)); 333 334 // Quiz 2 facilities. 335 $stats = $this->load_quiz_statistics_for_place(\context_module::instance($quiz2->cmid)); 336 $quiz2facility1 = $this->extract_item_value($stats, $questions[1]->id, 'facility'); 337 $quiz2facility2 = $this->extract_item_value($stats, $questions[2]->id, 'facility'); 338 $quiz2facility3 = $this->extract_item_value($stats, $questions[3]->id, 'facility'); 339 $quiz2facility4 = $this->extract_item_value($stats, $questions[4]->id, 'facility'); 340 341 $this->assertEquals($expectedquiz2facilities[0], helper::format_percentage($quiz2facility1)); 342 $this->assertEquals($expectedquiz2facilities[1], helper::format_percentage($quiz2facility2)); 343 $this->assertEquals($expectedquiz2facilities[2], helper::format_percentage($quiz2facility3)); 344 $this->assertEquals($expectedquiz2facilities[3], helper::format_percentage($quiz2facility4)); 345 346 // Average question facilities. 347 $averagefacility1 = helper::calculate_average_question_facility($questions[1]->id); 348 $averagefacility2 = helper::calculate_average_question_facility($questions[2]->id); 349 $averagefacility3 = helper::calculate_average_question_facility($questions[3]->id); 350 $averagefacility4 = helper::calculate_average_question_facility($questions[4]->id); 351 352 $this->assertEquals($expectedaveragefacilities[0], helper::format_percentage($averagefacility1)); 353 $this->assertEquals($expectedaveragefacilities[1], helper::format_percentage($averagefacility2)); 354 $this->assertEquals($expectedaveragefacilities[2], helper::format_percentage($averagefacility3)); 355 $this->assertEquals($expectedaveragefacilities[3], helper::format_percentage($averagefacility4)); 356 } 357 358 /** 359 * Data provider for {@see test_load_question_discriminative_efficiency()}. 360 * @return \Generator 361 */ 362 public function load_question_discriminative_efficiency_provider(): \Generator { 363 yield 'Discriminative efficiency' => [ 364 'Quiz 1 attempts' => [ 365 $this->generate_attempt_answers([1, 0, 0, 0]), 366 $this->generate_attempt_answers([1, 1, 0, 0]), 367 $this->generate_attempt_answers([1, 0, 1, 0]), 368 $this->generate_attempt_answers([1, 1, 1, 1]), 369 ], 370 'Expected quiz 1 discriminative efficiency' => ['N/A', '33.33%', '33.33%', '100.00%'], 371 'Quiz 2 attempts' => [ 372 $this->generate_attempt_answers([1, 1, 1, 1]), 373 $this->generate_attempt_answers([0, 0, 0, 0]), 374 $this->generate_attempt_answers([1, 0, 0, 1]), 375 $this->generate_attempt_answers([0, 1, 1, 0]), 376 ], 377 'Expected quiz 2 discriminative efficiency' => ['50.00%', '50.00%', '50.00%', '50.00%'], 378 'Expected average discriminative efficiency' => ['50.00%', '41.67%', '41.67%', '75.00%'], 379 ]; 380 } 381 382 /** 383 * Test discriminative efficiency 384 * 385 * @dataProvider load_question_discriminative_efficiency_provider 386 * 387 * @param array $quiz1attempts quiz 1 attempts 388 * @param array $expectedquiz1discriminativeefficiency expected quiz 1 discriminative efficiency 389 * @param array $quiz2attempts quiz 2 attempts 390 * @param array $expectedquiz2discriminativeefficiency expected quiz 2 discriminative efficiency 391 * @param array $expectedaveragediscriminativeefficiency expected average discriminative efficiency 392 */ 393 public function test_load_question_discriminative_efficiency( 394 array $quiz1attempts, 395 array $expectedquiz1discriminativeefficiency, 396 array $quiz2attempts, 397 array $expectedquiz2discriminativeefficiency, 398 array $expectedaveragediscriminativeefficiency 399 ): void { 400 $this->resetAfterTest(); 401 402 list($quiz1, $quiz2, $questions) = $this->prepare_and_submit_quizzes($quiz1attempts, $quiz2attempts); 403 404 // Quiz 1 discriminative efficiency. 405 $stats = $this->load_quiz_statistics_for_place(\context_module::instance($quiz1->cmid)); 406 $discriminativeefficiency1 = $this->extract_item_value($stats, $questions[1]->id, 'discriminativeefficiency'); 407 $discriminativeefficiency2 = $this->extract_item_value($stats, $questions[2]->id, 'discriminativeefficiency'); 408 $discriminativeefficiency3 = $this->extract_item_value($stats, $questions[3]->id, 'discriminativeefficiency'); 409 $discriminativeefficiency4 = $this->extract_item_value($stats, $questions[4]->id, 'discriminativeefficiency'); 410 411 $this->assertEquals($expectedquiz1discriminativeefficiency[0], 412 helper::format_percentage($discriminativeefficiency1, false), 413 "Failure in quiz 1 - question 1 discriminative efficiency"); 414 $this->assertEquals($expectedquiz1discriminativeefficiency[1], 415 helper::format_percentage($discriminativeefficiency2, false), 416 "Failure in quiz 1 - question 2 discriminative efficiency"); 417 $this->assertEquals($expectedquiz1discriminativeefficiency[2], 418 helper::format_percentage($discriminativeefficiency3, false), 419 "Failure in quiz 1 - question 3 discriminative efficiency"); 420 $this->assertEquals($expectedquiz1discriminativeefficiency[3], 421 helper::format_percentage($discriminativeefficiency4, false), 422 "Failure in quiz 1 - question 4 discriminative efficiency"); 423 424 // Quiz 2 discriminative efficiency. 425 $stats = $this->load_quiz_statistics_for_place(\context_module::instance($quiz2->cmid)); 426 $discriminativeefficiency1 = $this->extract_item_value($stats, $questions[1]->id, 'discriminativeefficiency'); 427 $discriminativeefficiency2 = $this->extract_item_value($stats, $questions[2]->id, 'discriminativeefficiency'); 428 $discriminativeefficiency3 = $this->extract_item_value($stats, $questions[3]->id, 'discriminativeefficiency'); 429 $discriminativeefficiency4 = $this->extract_item_value($stats, $questions[4]->id, 'discriminativeefficiency'); 430 431 $this->assertEquals($expectedquiz2discriminativeefficiency[0], 432 helper::format_percentage($discriminativeefficiency1, false), 433 "Failure in quiz 2 - question 1 discriminative efficiency"); 434 $this->assertEquals($expectedquiz2discriminativeefficiency[1], 435 helper::format_percentage($discriminativeefficiency2, false), 436 "Failure in quiz 2 - question 2 discriminative efficiency"); 437 $this->assertEquals($expectedquiz2discriminativeefficiency[2], 438 helper::format_percentage($discriminativeefficiency3, false), 439 "Failure in quiz 2 - question 3 discriminative efficiency"); 440 $this->assertEquals($expectedquiz2discriminativeefficiency[3], 441 helper::format_percentage($discriminativeefficiency4, false), 442 "Failure in quiz 2 - question 4 discriminative efficiency"); 443 444 // Average question discriminative efficiency. 445 $avgdiscriminativeefficiency1 = helper::calculate_average_question_discriminative_efficiency($questions[1]->id); 446 $avgdiscriminativeefficiency2 = helper::calculate_average_question_discriminative_efficiency($questions[2]->id); 447 $avgdiscriminativeefficiency3 = helper::calculate_average_question_discriminative_efficiency($questions[3]->id); 448 $avgdiscriminativeefficiency4 = helper::calculate_average_question_discriminative_efficiency($questions[4]->id); 449 450 $this->assertEquals($expectedaveragediscriminativeefficiency[0], 451 helper::format_percentage($avgdiscriminativeefficiency1, false), 452 "Failure in question 1 average discriminative efficiency"); 453 $this->assertEquals($expectedaveragediscriminativeefficiency[1], 454 helper::format_percentage($avgdiscriminativeefficiency2, false), 455 "Failure in question 2 average discriminative efficiency"); 456 $this->assertEquals($expectedaveragediscriminativeefficiency[2], 457 helper::format_percentage($avgdiscriminativeefficiency3, false), 458 "Failure in question 3 average discriminative efficiency"); 459 $this->assertEquals($expectedaveragediscriminativeefficiency[3], 460 helper::format_percentage($avgdiscriminativeefficiency4, false), 461 "Failure in question 4 average discriminative efficiency"); 462 } 463 464 /** 465 * Data provider for {@see test_load_question_discrimination_index()}. 466 * @return \Generator 467 */ 468 public function load_question_discrimination_index_provider(): \Generator { 469 yield 'Discrimination Index' => [ 470 'Quiz 1 attempts' => [ 471 $this->generate_attempt_answers([1, 0, 0, 0]), 472 $this->generate_attempt_answers([1, 1, 0, 0]), 473 $this->generate_attempt_answers([1, 0, 1, 0]), 474 $this->generate_attempt_answers([1, 1, 1, 1]), 475 ], 476 'Expected quiz 1 Discrimination Index' => ['N/A', '30.15%', '30.15%', '81.65%'], 477 'Quiz 2 attempts' => [ 478 $this->generate_attempt_answers([1, 1, 1, 1]), 479 $this->generate_attempt_answers([0, 0, 0, 0]), 480 $this->generate_attempt_answers([1, 0, 0, 1]), 481 $this->generate_attempt_answers([0, 1, 1, 0]), 482 ], 483 'Expected quiz 2 discrimination Index' => ['44.72%', '44.72%', '44.72%', '44.72%'], 484 'Expected average discrimination Index' => ['44.72%', '37.44%', '37.44%', '63.19%'], 485 ]; 486 } 487 488 /** 489 * Test discrimination index 490 * 491 * @dataProvider load_question_discrimination_index_provider 492 * 493 * @param array $quiz1attempts quiz 1 attempts 494 * @param array $expectedquiz1discriminationindex expected quiz 1 discrimination index 495 * @param array $quiz2attempts quiz 2 attempts 496 * @param array $expectedquiz2discriminationindex expected quiz 2 discrimination index 497 * @param array $expectedaveragediscriminationindex expected average discrimination index 498 */ 499 public function test_load_question_discrimination_index( 500 array $quiz1attempts, 501 array $expectedquiz1discriminationindex, 502 array $quiz2attempts, 503 array $expectedquiz2discriminationindex, 504 array $expectedaveragediscriminationindex 505 ): void { 506 $this->resetAfterTest(); 507 508 list($quiz1, $quiz2, $questions) = $this->prepare_and_submit_quizzes($quiz1attempts, $quiz2attempts); 509 510 // Quiz 1 discrimination index. 511 $stats = $this->load_quiz_statistics_for_place(\context_module::instance($quiz1->cmid)); 512 $discriminationindex1 = $this->extract_item_value($stats, $questions[1]->id, 'discriminationindex'); 513 $discriminationindex2 = $this->extract_item_value($stats, $questions[2]->id, 'discriminationindex'); 514 $discriminationindex3 = $this->extract_item_value($stats, $questions[3]->id, 'discriminationindex'); 515 $discriminationindex4 = $this->extract_item_value($stats, $questions[4]->id, 'discriminationindex'); 516 517 $this->assertEquals($expectedquiz1discriminationindex[0], 518 helper::format_percentage($discriminationindex1, false), 519 "Failure in quiz 1 - question 1 discrimination index"); 520 $this->assertEquals($expectedquiz1discriminationindex[1], 521 helper::format_percentage($discriminationindex2, false), 522 "Failure in quiz 1 - question 2 discrimination index"); 523 $this->assertEquals($expectedquiz1discriminationindex[2], 524 helper::format_percentage($discriminationindex3, false), 525 "Failure in quiz 1 - question 3 discrimination index"); 526 $this->assertEquals($expectedquiz1discriminationindex[3], 527 helper::format_percentage($discriminationindex4, false), 528 "Failure in quiz 1 - question 4 discrimination index"); 529 530 // Quiz 2 discrimination index. 531 $stats = $this->load_quiz_statistics_for_place(\context_module::instance($quiz2->cmid)); 532 $discriminationindex1 = $this->extract_item_value($stats, $questions[1]->id, 'discriminationindex'); 533 $discriminationindex2 = $this->extract_item_value($stats, $questions[2]->id, 'discriminationindex'); 534 $discriminationindex3 = $this->extract_item_value($stats, $questions[3]->id, 'discriminationindex'); 535 $discriminationindex4 = $this->extract_item_value($stats, $questions[4]->id, 'discriminationindex'); 536 537 $this->assertEquals($expectedquiz2discriminationindex[0], 538 helper::format_percentage($discriminationindex1, false), 539 "Failure in quiz 2 - question 1 discrimination index"); 540 $this->assertEquals($expectedquiz2discriminationindex[1], 541 helper::format_percentage($discriminationindex2, false), 542 "Failure in quiz 2 - question 2 discrimination index"); 543 $this->assertEquals($expectedquiz2discriminationindex[2], 544 helper::format_percentage($discriminationindex3, false), 545 "Failure in quiz 2 - question 3 discrimination index"); 546 $this->assertEquals($expectedquiz2discriminationindex[3], 547 helper::format_percentage($discriminationindex4, false), 548 "Failure in quiz 2 - question 4 discrimination index"); 549 550 // Average question discrimination index. 551 $avgdiscriminationindex1 = helper::calculate_average_question_discrimination_index($questions[1]->id); 552 $avgdiscriminationindex2 = helper::calculate_average_question_discrimination_index($questions[2]->id); 553 $avgdiscriminationindex3 = helper::calculate_average_question_discrimination_index($questions[3]->id); 554 $avgdiscriminationindex4 = helper::calculate_average_question_discrimination_index($questions[4]->id); 555 556 $this->assertEquals($expectedaveragediscriminationindex[0], 557 helper::format_percentage($avgdiscriminationindex1, false), 558 "Failure in question 1 average discrimination index"); 559 $this->assertEquals($expectedaveragediscriminationindex[1], 560 helper::format_percentage($avgdiscriminationindex2, false), 561 "Failure in question 2 average discrimination index"); 562 $this->assertEquals($expectedaveragediscriminationindex[2], 563 helper::format_percentage($avgdiscriminationindex3, false), 564 "Failure in question 3 average discrimination index"); 565 $this->assertEquals($expectedaveragediscriminationindex[3], 566 helper::format_percentage($avgdiscriminationindex4, false), 567 "Failure in question 4 average discrimination index"); 568 } 569 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body