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 * Calculated multiple-choice question definition class.
19 *
20 * @package    qtype
21 * @subpackage calculatedmulti
22 * @copyright  2011 The Open University
23 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26
27defined('MOODLE_INTERNAL') || die();
28
29require_once($CFG->dirroot . '/question/type/questionbase.php');
30require_once($CFG->dirroot . '/question/type/multichoice/question.php');
31require_once($CFG->dirroot . '/question/type/calculated/question.php');
32
33
34/**
35 * Represents a calculated multiple-choice multiple-response question.
36 *
37 * @copyright  2011 The Open University
38 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
39 */
40class qtype_calculatedmulti_single_question extends qtype_multichoice_single_question
41        implements qtype_calculated_question_with_expressions {
42
43    /** @var qtype_calculated_dataset_loader helper for loading the dataset. */
44    public $datasetloader;
45
46    /** @var qtype_calculated_variable_substituter stores the dataset we are using. */
47    public $vs;
48
49    /**
50     * @var bool wheter the dataset item to use should be chose based on attempt
51     * start time, rather than randomly.
52     */
53    public $synchronised;
54
55    public function start_attempt(question_attempt_step $step, $variant) {
56        qtype_calculated_question_helper::start_attempt($this, $step, $variant);
57        parent::start_attempt($step, $variant);
58    }
59
60    public function apply_attempt_state(question_attempt_step $step) {
61        qtype_calculated_question_helper::apply_attempt_state($this, $step);
62        parent::apply_attempt_state($step);
63    }
64
65    public function calculate_all_expressions() {
66        qtype_calculatedmulti_calculate_helper::calculate_all_expressions($this);
67    }
68
69    public function get_num_variants() {
70        return $this->datasetloader->get_number_of_items();
71    }
72
73    public function get_variants_selection_seed() {
74        if (!empty($this->synchronised) &&
75                $this->datasetloader->datasets_are_synchronised($this->category)) {
76            return 'category' . $this->category;
77        } else {
78            return parent::get_variants_selection_seed();
79        }
80    }
81}
82
83
84/**
85 * Represents a calculated multiple-choice multiple-response question.
86 *
87 * @copyright  2011 The Open University
88 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
89 */
90class qtype_calculatedmulti_multi_question extends qtype_multichoice_multi_question
91        implements qtype_calculated_question_with_expressions {
92
93    /** @var qtype_calculated_dataset_loader helper for loading the dataset. */
94    public $datasetloader;
95
96    /** @var qtype_calculated_variable_substituter stores the dataset we are using. */
97    public $vs;
98
99    /**
100     * @var bool wheter the dataset item to use should be chose based on attempt
101     * start time, rather than randomly.
102     */
103    public $synchronised;
104
105    public function start_attempt(question_attempt_step $step, $variant) {
106        qtype_calculated_question_helper::start_attempt($this, $step, $variant);
107        parent::start_attempt($step, $variant);
108    }
109
110    public function apply_attempt_state(question_attempt_step $step) {
111        qtype_calculated_question_helper::apply_attempt_state($this, $step);
112        parent::apply_attempt_state($step);
113    }
114
115    public function calculate_all_expressions() {
116        qtype_calculatedmulti_calculate_helper::calculate_all_expressions($this);
117    }
118
119    public function get_num_variants() {
120        return $this->datasetloader->get_number_of_items();
121    }
122
123    public function get_variants_selection_seed() {
124        if (!empty($this->synchronised) &&
125                $this->datasetloader->datasets_are_synchronised($this->category)) {
126            return 'category' . $this->category;
127        } else {
128            return parent::get_variants_selection_seed();
129        }
130    }
131}
132
133
134/**
135 * Helper to abstract common code between qtype_calculatedmulti_single_question
136 * and qtype_calculatedmulti_multi_question.
137 *
138 * @copyright  2011 The Open University
139 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
140 */
141abstract class qtype_calculatedmulti_calculate_helper {
142    /**
143     * Calculate all the exressions in a qtype_calculatedmulti_single_question
144     * or qtype_calculatedmulti_multi_question.
145     * @param unknown_type $question
146     */
147    public static function calculate_all_expressions(
148            qtype_calculated_question_with_expressions $question) {
149        $question->questiontext = $question->vs->replace_expressions_in_text(
150                $question->questiontext);
151        $question->generalfeedback = $question->vs->replace_expressions_in_text(
152                $question->generalfeedback);
153
154        foreach ($question->answers as $ans) {
155            if ($ans->answer && $ans->answer !== '*') {
156                $ans->answer = $question->vs->replace_expressions_in_text($ans->answer,
157                        $ans->correctanswerlength, $ans->correctanswerformat);
158            }
159            $ans->feedback = $question->vs->replace_expressions_in_text($ans->feedback,
160                    $ans->correctanswerlength, $ans->correctanswerformat);
161        }
162    }
163}