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
 * Question type class for the randomsamatch question type.
19
 *
20
 * @package    qtype_randomsamatch
21
 * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
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/questiontypebase.php');
29
require_once($CFG->dirroot . '/question/type/questionbase.php');
30
require_once($CFG->dirroot . '/question/type/numerical/question.php');
31
 
32
/**
33
 * The randomsamatch question type class.
34
 *
35
 * TODO: Make sure short answer questions chosen by a randomsamatch question
36
 * can not also be used by a random question
37
 *
38
 * @copyright  1999 onwards Martin Dougiamas  {@link http://moodle.com}
39
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40
 */
41
class qtype_randomsamatch extends question_type {
42
    /**
43
     * Cache of available shortanswer question ids from a particular category.
44
     * @var array two-dimensional array. The first key is a category id, the
45
     * second key is wether subcategories should be included.
46
     */
47
    private $availablesaquestionsbycategory = array();
48
    const MAX_SUBQUESTIONS = 10;
49
 
50
    public function is_usable_by_random() {
51
        return false;
52
    }
53
 
54
    public function get_question_options($question) {
55
        global $DB;
56
        parent::get_question_options($question);
57
        $question->options = $DB->get_record('qtype_randomsamatch_options',
58
                array('questionid' => $question->id));
59
 
60
        return true;
61
 
62
    }
63
 
64
    public function save_question_options($question) {
65
        global $DB;
66
 
67
        if (2 > $question->choose) {
68
            $result = new stdClass();
69
            $result->error = "At least two shortanswer questions need to be chosen!";
70
            return $result;
71
        }
72
 
73
        $context = $question->context;
74
 
75
        // Save the question options.
76
        $options = $DB->get_record('qtype_randomsamatch_options', array('questionid' => $question->id));
77
        if (!$options) {
78
            $options = new stdClass();
79
            $options->questionid = $question->id;
80
            $options->correctfeedback = '';
81
            $options->partiallycorrectfeedback = '';
82
            $options->incorrectfeedback = '';
83
            $options->id = $DB->insert_record('qtype_randomsamatch_options', $options);
84
        }
85
 
86
        $options->choose = $question->choose;
87
        $options->subcats = $question->subcats;
88
        $options = $this->save_combined_feedback_helper($options, $question, $context, true);
89
        $DB->update_record('qtype_randomsamatch_options', $options);
90
 
91
        $this->save_hints($question, true);
92
 
93
        return true;
94
    }
95
 
96
    protected function make_hint($hint) {
97
        return question_hint_with_parts::load_from_record($hint);
98
    }
99
 
100
    public function delete_question($questionid, $contextid) {
101
        global $DB;
102
        $DB->delete_records('qtype_randomsamatch_options', array('questionid' => $questionid));
103
 
104
        parent::delete_question($questionid, $contextid);
105
    }
106
 
107
    public function move_files($questionid, $oldcontextid, $newcontextid) {
108
        parent::move_files($questionid, $oldcontextid, $newcontextid);
109
 
110
        $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid);
111
        $this->move_files_in_hints($questionid, $oldcontextid, $newcontextid);
112
    }
113
 
114
    protected function delete_files($questionid, $contextid) {
115
        parent::delete_files($questionid, $contextid);
116
 
117
        $this->delete_files_in_combined_feedback($questionid, $contextid);
118
        $this->delete_files_in_hints($questionid, $contextid);
119
    }
120
 
121
    protected function initialise_question_instance(question_definition $question, $questiondata) {
122
        parent::initialise_question_instance($question, $questiondata);
123
        $availablesaquestions = $this->get_available_saquestions_from_category(
124
                $question->category, $questiondata->options->subcats);
125
        $question->shufflestems = false;
126
        $question->stems = array();
127
        $question->choices = array();
128
        $question->right = array();
129
        $this->initialise_combined_feedback($question, $questiondata);
130
        $question->questionsloader = new qtype_randomsamatch_question_loader(
131
                $availablesaquestions, $questiondata->options->choose);
132
    }
133
 
134
    public function can_analyse_responses() {
135
        return false;
136
    }
137
 
138
    /**
139
     * Get all the usable shortanswer questions from a particular question category.
140
     *
141
     * @param integer $categoryid the id of a question category.
142
     * @param bool $subcategories whether to include questions from subcategories.
143
     * @return array of question records.
144
     */
145
    public function get_available_saquestions_from_category($categoryid, $subcategories) {
146
        if (isset($this->availablesaquestionsbycategory[$categoryid][$subcategories])) {
147
            return $this->availablesaquestionsbycategory[$categoryid][$subcategories];
148
        }
149
 
150
        if ($subcategories) {
151
            $categoryids = question_categorylist($categoryid);
152
        } else {
153
            $categoryids = array($categoryid);
154
        }
155
 
156
        $questionids = question_bank::get_finder()->get_questions_from_categories(
157
                $categoryids, "qtype = 'shortanswer'");
158
        $this->availablesaquestionsbycategory[$categoryid][$subcategories] = $questionids;
159
        return $questionids;
160
    }
161
 
162
    /**
163
     * @param object $question
164
     * @return mixed either a integer score out of 1 that the average random
165
     * guess by a student might give or an empty string which means will not
166
     * calculate.
167
     */
168
    public function get_random_guess_score($question) {
169
        return 1/$question->options->choose;
170
    }
171
 
172
    /**
173
     * Defines the table which extends the question table. This allows the base questiontype
174
     * to automatically save, backup and restore the extra fields.
175
     *
176
     * @return an array with the table name (first) and then the column names (apart from id and questionid)
177
     */
178
    public function extra_question_fields() {
179
        return array('qtype_randomsamatch_options',
180
                     'choose',        // Number of shortanswer questions to choose.
181
                     'subcats',       // Questions can be choosen from subcategories.
182
                     );
183
    }
184
 
185
    /**
186
     * Imports the question from Moodle XML format.
187
     *
188
     * @param array $xml structure containing the XML data
189
     * @param object $fromform question object to fill: ignored by this function (assumed to be null)
190
     * @param qformat_xml $format format class exporting the question
191
     * @param object $extra extra information (not required for importing this question in this format)
192
     * @return object question object
193
     */
194
    public function import_from_xml($xml, $fromform, qformat_xml $format, $extra=null) {
195
        // Return if data type is not our own one.
196
        if (!isset($xml['@']['type']) || $xml['@']['type'] != $this->name()) {
197
            return false;
198
        }
199
 
200
        // Import the common question headers and set the corresponding field.
201
        $fromform = $format->import_headers($xml);
202
        $fromform->qtype = $this->name();
203
        $format->import_combined_feedback($fromform, $xml, true);
204
        $format->import_hints($fromform, $xml, true);
205
 
206
        $extras = $this->extra_question_fields();
207
        array_shift($extras);
208
        foreach ($extras as $extra) {
209
            $fromform->$extra = $format->getpath($xml, array('#', $extra, 0, '#'), '', true);
210
        }
211
 
212
        return $fromform;
213
    }
214
 
215
    /**
216
     * Exports the question to Moodle XML format.
217
     *
218
     * @param object $question question to be exported into XML format
219
     * @param qformat_xml $format format class exporting the question
220
     * @param object $extra extra information (not required for exporting this question in this format)
221
     * @return string containing the question data in XML format
222
     */
223
    public function export_to_xml($question, qformat_xml $format, $extra=null) {
224
        $expout = '';
225
        $expout .= $format->write_combined_feedback($question->options,
226
                                                    $question->id,
227
                                                    $question->contextid);
228
        $extraquestionfields = $this->extra_question_fields();
229
        array_shift($extraquestionfields);
230
        foreach ($extraquestionfields as $extra) {
231
            $expout .= "    <{$extra}>" . $question->options->$extra . "</{$extra}>\n";
232
        }
233
        return $expout;
234
    }
235
}