| 1 | efrain | 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 core_question;
 | 
        
           |  |  | 18 |   | 
        
           |  |  | 19 | use core_question\engine\variants\least_used_strategy;
 | 
        
           |  |  | 20 | use qubaid_list;
 | 
        
           |  |  | 21 | use question_bank;
 | 
        
           |  |  | 22 | use question_engine;
 | 
        
           |  |  | 23 |   | 
        
           |  |  | 24 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 25 |   | 
        
           |  |  | 26 | global $CFG;
 | 
        
           |  |  | 27 | require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 | /**
 | 
        
           |  |  | 30 |  * Tests for the {@link core_question\engine\variants\least_used_strategy} class.
 | 
        
           |  |  | 31 |  *
 | 
        
           |  |  | 32 |  * @package    core_question
 | 
        
           |  |  | 33 |  * @copyright  2015 The Open University
 | 
        
           |  |  | 34 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 35 |  */
 | 
        
           | 1441 | ariadna | 36 | final class least_used_variant_strategy_test extends \advanced_testcase {
 | 
        
           | 1 | efrain | 37 |   | 
        
           | 11 | efrain | 38 |     public function test_question_with_one_variant_always_picks_that(): void {
 | 
        
           | 1 | efrain | 39 |         $question = \test_question_maker::make_question('shortanswer');
 | 
        
           |  |  | 40 |         $quba = question_engine::make_questions_usage_by_activity('test', \context_system::instance());
 | 
        
           |  |  | 41 |         $quba->set_preferred_behaviour('deferredfeedback');
 | 
        
           |  |  | 42 |         $slot = $quba->add_question($question);
 | 
        
           |  |  | 43 |         $quba->start_all_questions(new least_used_strategy(
 | 
        
           |  |  | 44 |                 $quba, new qubaid_list([])));
 | 
        
           |  |  | 45 |         $this->assertEquals(1, $quba->get_variant($slot));
 | 
        
           |  |  | 46 |     }
 | 
        
           |  |  | 47 |   | 
        
           | 11 | efrain | 48 |     public function test_synchronised_question_should_use_the_same_dataset(): void {
 | 
        
           | 1 | efrain | 49 |         // Actually, we cheat here. We use the same question twice, not two different synchronised questions.
 | 
        
           |  |  | 50 |         $question = \test_question_maker::make_question('calculated');
 | 
        
           |  |  | 51 |         $quba = question_engine::make_questions_usage_by_activity('test', \context_system::instance());
 | 
        
           |  |  | 52 |         $quba->set_preferred_behaviour('deferredfeedback');
 | 
        
           |  |  | 53 |         $slot1 = $quba->add_question($question);
 | 
        
           |  |  | 54 |         $slot2 = $quba->add_question($question);
 | 
        
           |  |  | 55 |         $quba->start_all_questions(new least_used_strategy(
 | 
        
           |  |  | 56 |                 $quba, new qubaid_list([])));
 | 
        
           |  |  | 57 |         $this->assertEquals($quba->get_variant($slot1), $quba->get_variant($slot2));
 | 
        
           |  |  | 58 |     }
 | 
        
           |  |  | 59 |   | 
        
           | 11 | efrain | 60 |     public function test_second_attempt_uses_other_dataset(): void {
 | 
        
           | 1 | efrain | 61 |         global $DB;
 | 
        
           |  |  | 62 |         $this->resetAfterTest();
 | 
        
           |  |  | 63 |         $generator = $this->getDataGenerator()->get_plugin_generator('core_question');
 | 
        
           |  |  | 64 |   | 
        
           |  |  | 65 |         $cat = $generator->create_question_category();
 | 
        
           |  |  | 66 |         $questiondata = $generator->create_question('calculated', null, ['category' => $cat->id]);
 | 
        
           |  |  | 67 |   | 
        
           |  |  | 68 |         // Create two dataset items.
 | 
        
           |  |  | 69 |         $adefinitionid = $DB->get_field_sql("
 | 
        
           |  |  | 70 |                     SELECT qdd.id
 | 
        
           |  |  | 71 |                       FROM {question_dataset_definitions} qdd
 | 
        
           |  |  | 72 |                       JOIN {question_datasets} qd ON qd.datasetdefinition = qdd.id
 | 
        
           |  |  | 73 |                      WHERE qd.question = ?
 | 
        
           |  |  | 74 |                        AND qdd.name = ?", [$questiondata->id, 'a']);
 | 
        
           |  |  | 75 |         $bdefinitionid = $DB->get_field_sql("
 | 
        
           |  |  | 76 |                     SELECT qdd.id
 | 
        
           |  |  | 77 |                       FROM {question_dataset_definitions} qdd
 | 
        
           |  |  | 78 |                       JOIN {question_datasets} qd ON qd.datasetdefinition = qdd.id
 | 
        
           |  |  | 79 |                      WHERE qd.question = ?
 | 
        
           |  |  | 80 |                        AND qdd.name = ?", [$questiondata->id, 'b']);
 | 
        
           |  |  | 81 |         $DB->set_field('question_dataset_definitions', 'itemcount', 2, ['id' => $adefinitionid]);
 | 
        
           |  |  | 82 |         $DB->set_field('question_dataset_definitions', 'itemcount', 2, ['id' => $bdefinitionid]);
 | 
        
           |  |  | 83 |         $DB->insert_record('question_dataset_items', ['definition' => $adefinitionid,
 | 
        
           |  |  | 84 |                 'itemnumber' => 1, 'value' => 3]);
 | 
        
           |  |  | 85 |         $DB->insert_record('question_dataset_items', ['definition' => $bdefinitionid,
 | 
        
           |  |  | 86 |                 'itemnumber' => 1, 'value' => 7]);
 | 
        
           |  |  | 87 |         $DB->insert_record('question_dataset_items', ['definition' => $adefinitionid,
 | 
        
           |  |  | 88 |                 'itemnumber' => 2, 'value' => 6]);
 | 
        
           |  |  | 89 |         $DB->insert_record('question_dataset_items', ['definition' => $bdefinitionid,
 | 
        
           |  |  | 90 |                 'itemnumber' => 2, 'value' => 4]);
 | 
        
           |  |  | 91 |   | 
        
           |  |  | 92 |         $question = question_bank::load_question($questiondata->id);
 | 
        
           |  |  | 93 |   | 
        
           |  |  | 94 |         $quba1 = question_engine::make_questions_usage_by_activity('test', \context_system::instance());
 | 
        
           |  |  | 95 |         $quba1->set_preferred_behaviour('deferredfeedback');
 | 
        
           |  |  | 96 |         $slot1 = $quba1->add_question($question);
 | 
        
           |  |  | 97 |         $quba1->start_all_questions(new least_used_strategy(
 | 
        
           |  |  | 98 |                 $quba1, new qubaid_list([])));
 | 
        
           |  |  | 99 |         question_engine::save_questions_usage_by_activity($quba1);
 | 
        
           |  |  | 100 |         $variant1 = $quba1->get_variant($slot1);
 | 
        
           |  |  | 101 |   | 
        
           |  |  | 102 |         // Second attempt should use the other variant.
 | 
        
           |  |  | 103 |         $quba2 = question_engine::make_questions_usage_by_activity('test', \context_system::instance());
 | 
        
           |  |  | 104 |         $quba2->set_preferred_behaviour('deferredfeedback');
 | 
        
           |  |  | 105 |         $slot2 = $quba2->add_question($question);
 | 
        
           |  |  | 106 |         $quba2->start_all_questions(new least_used_strategy(
 | 
        
           |  |  | 107 |                 $quba1, new qubaid_list([$quba1->get_id()])));
 | 
        
           |  |  | 108 |         question_engine::save_questions_usage_by_activity($quba2);
 | 
        
           |  |  | 109 |         $variant2 = $quba2->get_variant($slot2);
 | 
        
           |  |  | 110 |   | 
        
           |  |  | 111 |         $this->assertNotEquals($variant1, $variant2);
 | 
        
           |  |  | 112 |   | 
        
           |  |  | 113 |         // Third attempt uses either variant at random.
 | 
        
           |  |  | 114 |         $quba3 = question_engine::make_questions_usage_by_activity('test', \context_system::instance());
 | 
        
           |  |  | 115 |         $quba3->set_preferred_behaviour('deferredfeedback');
 | 
        
           |  |  | 116 |         $slot3 = $quba3->add_question($question);
 | 
        
           |  |  | 117 |         $quba3->start_all_questions(new least_used_strategy(
 | 
        
           |  |  | 118 |                 $quba1, new qubaid_list([$quba1->get_id(), $quba2->get_id()])));
 | 
        
           |  |  | 119 |         $variant3 = $quba3->get_variant($slot3);
 | 
        
           |  |  | 120 |   | 
        
           |  |  | 121 |         $this->assertTrue($variant3 == $variant1 || $variant3 == $variant2);
 | 
        
           |  |  | 122 |     }
 | 
        
           |  |  | 123 | }
 |