Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
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
/**
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
    /** @var int the number of subquestions to randomly create. */
41
    public $choose;
42
 
43
    /** @var bool whether to include questions from subactegories when making the random selection. */
44
    public $subcats;
45
 
46
    public function start_attempt(question_attempt_step $step, $variant) {
47
        $saquestions = $this->questionsloader->load_questions();
48
        foreach ($saquestions as $wrappedquestion) {
49
            // Store and save stem text and format.
50
            $this->stems[$wrappedquestion->id] = $wrappedquestion->questiontext;
51
            $this->stemformat[$wrappedquestion->id] = $wrappedquestion->questiontextformat;
52
            $step->set_qt_var('_stem_' . $wrappedquestion->id, $this->stems[$wrappedquestion->id]);
53
            $step->set_qt_var('_stemformat_' . $wrappedquestion->id, $this->stemformat[$wrappedquestion->id]);
54
 
55
            // Find, store and save right choice id.
56
            $key = $this->find_right_answer($wrappedquestion);
57
            $this->right[$wrappedquestion->id] = $key;
58
            $step->set_qt_var('_right_' . $wrappedquestion->id, $key);
59
            // No need to save saquestions, it will be saved by parent class in _stemorder.
60
        }
61
 
62
        // Save all the choices.
63
        foreach ($this->choices as $key => $answer) {
64
            $step->set_qt_var('_choice_' . $key, $answer);
65
        }
66
 
67
        parent::start_attempt($step, $variant);
68
    }
69
 
70
    /**
71
     * Find the corresponding choice id of the first correct answer of a shortanswer question.
72
     * choice is added to the randomsamatch question if it doesn't already exist.
73
     * @param object $wrappedquestion short answer question.
74
     * @return int correct choice id.
75
     */
76
    public function find_right_answer($wrappedquestion) {
77
        // We only take into account *one* (the first) correct answer.
78
        while ($answer = array_shift($wrappedquestion->answers)) {
79
            if (!question_state::graded_state_for_fraction(
80
                    $answer->fraction)->is_incorrect()) {
81
                // Store this answer as a choice, only if this is a new one.
82
                $key = array_search($answer->answer, $this->choices);
83
                if ($key === false) {
84
                    $key = $answer->id;
85
                    $this->choices[$key] = $answer->answer;
86
                }
87
                return $key;
88
            }
89
        }
90
        // We should never get there.
91
        throw new coding_exception('shortanswerquestionwithoutrightanswer', $wrappedquestion->id);
92
 
93
    }
94
 
95
    public function apply_attempt_state(question_attempt_step $step) {
96
        $saquestions = explode(',', $step->get_qt_var('_stemorder'));
97
        foreach ($saquestions as $questionid) {
98
            $this->stems[$questionid] = $step->get_qt_var('_stem_' . $questionid);
99
            $this->stemformat[$questionid] = $step->get_qt_var('_stemformat_' . $questionid);
100
            $key = $step->get_qt_var('_right_' . $questionid);
101
            $this->right[$questionid] = $key;
102
            $this->choices[$key] = $step->get_qt_var('_choice_' . $key);
103
        }
104
        parent::apply_attempt_state($step);
105
    }
106
}
107
 
108
/**
109
 * This class is responsible for loading the questions that a question needs from the database.
110
 *
111
 * @copyright  2013 Jean-Michel vedrine
112
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
113
 */
114
class qtype_randomsamatch_question_loader {
115
    /** @var array hold available shortanswers questionid to choose from. */
116
    protected $availablequestions;
117
    /** @var int how many questions to load. */
118
    protected $choose;
119
 
120
    /**
121
     * Constructor
122
     * @param array $availablequestions array of available question ids.
123
     * @param int $choose how many questions to load.
124
     */
125
    public function __construct($availablequestions, $choose) {
126
        $this->availablequestions = $availablequestions;
127
        $this->choose = $choose;
128
    }
129
 
130
    /**
131
     * Choose and load the desired number of questions.
132
     * @return array of short answer questions.
133
     */
134
    public function load_questions() {
135
        if ($this->choose > count($this->availablequestions)) {
136
            throw new coding_exception('notenoughtshortanswerquestions');
137
        }
138
 
139
        $questionids = draw_rand_array($this->availablequestions, $this->choose);
140
        $questions = array();
141
        foreach ($questionids as $questionid) {
142
            $questions[] = question_bank::load_question($questionid);
143
        }
144
        return $questions;
145
    }
146
}