Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 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 /** 18 * Matching question definition class. 19 * 20 * @package qtype_randomsamatch 21 * @copyright 2013 Jean-Michel Vedrine 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 require_once($CFG->dirroot . '/question/type/match/question.php'); 29 30 /** 31 * Represents a randomsamatch question. 32 * 33 * @copyright 22013 Jean-Michel Vedrine 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class qtype_randomsamatch_question extends qtype_match_question { 37 /** @var qtype_randomsamatch_question_loader helper for loading the shortanswer questions. */ 38 public $questionsloader; 39 40 public function start_attempt(question_attempt_step $step, $variant) { 41 $saquestions = $this->questionsloader->load_questions(); 42 foreach ($saquestions as $wrappedquestion) { 43 // Store and save stem text and format. 44 $this->stems[$wrappedquestion->id] = $wrappedquestion->questiontext; 45 $this->stemformat[$wrappedquestion->id] = $wrappedquestion->questiontextformat; 46 $step->set_qt_var('_stem_' . $wrappedquestion->id, $this->stems[$wrappedquestion->id]); 47 $step->set_qt_var('_stemformat_' . $wrappedquestion->id, $this->stemformat[$wrappedquestion->id]); 48 49 // Find, store and save right choice id. 50 $key = $this->find_right_answer($wrappedquestion); 51 $this->right[$wrappedquestion->id] = $key; 52 $step->set_qt_var('_right_' . $wrappedquestion->id, $key); 53 // No need to save saquestions, it will be saved by parent class in _stemorder. 54 } 55 56 // Save all the choices. 57 foreach ($this->choices as $key => $answer) { 58 $step->set_qt_var('_choice_' . $key, $answer); 59 } 60 61 parent::start_attempt($step, $variant); 62 } 63 64 /** 65 * Find the corresponding choice id of the first correct answer of a shortanswer question. 66 * choice is added to the randomsamatch question if it doesn't already exist. 67 * @param object $wrappedquestion short answer question. 68 * @return int correct choice id. 69 */ 70 public function find_right_answer($wrappedquestion) { 71 // We only take into account *one* (the first) correct answer. 72 while ($answer = array_shift($wrappedquestion->answers)) { 73 if (!question_state::graded_state_for_fraction( 74 $answer->fraction)->is_incorrect()) { 75 // Store this answer as a choice, only if this is a new one. 76 $key = array_search($answer->answer, $this->choices); 77 if ($key === false) { 78 $key = $answer->id; 79 $this->choices[$key] = $answer->answer; 80 } 81 return $key; 82 } 83 } 84 // We should never get there. 85 throw new coding_exception('shortanswerquestionwithoutrightanswer', $wrappedquestion->id); 86 87 } 88 89 public function apply_attempt_state(question_attempt_step $step) { 90 $saquestions = explode(',', $step->get_qt_var('_stemorder')); 91 foreach ($saquestions as $questionid) { 92 $this->stems[$questionid] = $step->get_qt_var('_stem_' . $questionid); 93 $this->stemformat[$questionid] = $step->get_qt_var('_stemformat_' . $questionid); 94 $key = $step->get_qt_var('_right_' . $questionid); 95 $this->right[$questionid] = $key; 96 $this->choices[$key] = $step->get_qt_var('_choice_' . $key); 97 } 98 parent::apply_attempt_state($step); 99 } 100 } 101 102 /** 103 * This class is responsible for loading the questions that a question needs from the database. 104 * 105 * @copyright 2013 Jean-Michel vedrine 106 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 107 */ 108 class qtype_randomsamatch_question_loader { 109 /** @var array hold available shortanswers questionid to choose from. */ 110 protected $availablequestions; 111 /** @var int how many questions to load. */ 112 protected $choose; 113 114 /** 115 * Constructor 116 * @param array $availablequestions array of available question ids. 117 * @param int $choose how many questions to load. 118 */ 119 public function __construct($availablequestions, $choose) { 120 $this->availablequestions = $availablequestions; 121 $this->choose = $choose; 122 } 123 124 /** 125 * Choose and load the desired number of questions. 126 * @return array of short answer questions. 127 */ 128 public function load_questions() { 129 if ($this->choose > count($this->availablequestions)) { 130 throw new coding_exception('notenoughtshortanswerquestions'); 131 } 132 133 $questionids = draw_rand_array($this->availablequestions, $this->choose); 134 $questions = array(); 135 foreach ($questionids as $questionid) { 136 $questions[] = question_bank::load_question($questionid); 137 } 138 return $questions; 139 } 140 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body