MDL-27505 Remove the ou-specific question types from the main branch.
[moodle.git] / question / type / calculated / edit_calculated_form.php
CommitLineData
aeb15530 1<?php
fe6ce234
DC
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
271ffe3f 17/**
18 * Defines the editing form for the calculated question type.
19 *
b04a4319
TH
20 * @package qtype
21 * @subpackage calculated
22 * @copyright 2007 Jamie Pratt me@jamiep.org
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
271ffe3f 24 */
25
b04a4319 26
a17b297d
TH
27defined('MOODLE_INTERNAL') || die();
28
29
271ffe3f 30/**
d3603157 31 * Calculated question type editing form definition.
b04a4319
TH
32 *
33 * @copyright 2007 Jamie Pratt me@jamiep.org
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
271ffe3f 35 */
36class question_edit_calculated_form extends question_edit_form {
9aa022fe 37 /**
38 * Handle to the question type for this question.
39 *
40 * @var question_calculated_qtype
41 */
d90b016b 42 public $qtypeobj;
fe6ce234
DC
43 public $questiondisplay;
44 public $activecategory;
45 public $categorychanged = false;
d90b016b 46 public $initialname = '';
fe6ce234
DC
47 public $reload = false;
48
d90b016b
PP
49 function question_edit_calculated_form(&$submiturl, &$question, &$category, &$contexts, $formeditable = true){
50 global $QTYPES, $SESSION, $CFG, $DB;
51 $this->question = $question;
52 $this->qtypeobj =& $QTYPES[$this->question->qtype];
53 if ( "1" == optional_param('reload','', PARAM_INT )) {
54 $this->reload = true ;
55 }else {
56 $this->reload = false ;
57 }
2aef1fe5 58
d90b016b
PP
59 if(!$this->reload ){ // use database data as this is first pass
60 if(isset($this->question->id )){
61 // remove prefix #{..}# if exists
62 $this->initialname = $question->name ;
63 $regs= array();
64 if(preg_match('~#\{([^[:space:]]*)#~',$question->name , $regs)){
65 $question->name = str_replace($regs[0], '', $question->name);
fe6ce234 66 };
d90b016b
PP
67 }
68 }else {
fe6ce234 69 }
d90b016b
PP
70 parent::question_edit_form($submiturl, $question, $category, $contexts, $formeditable);
71 }
fe6ce234 72
2aef1fe5 73 function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
fe6ce234
DC
74 // $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
75 $repeated = array();
28a27ef1 76 $repeated[] =& $mform->createElement('header', 'answerhdr', $label);
5e8a85aa 77 $repeated[] =& $mform->createElement('text', 'answer', get_string('answer', 'question'), array('size' => 50));
28a27ef1 78 $repeated[] =& $mform->createElement('select', 'fraction', get_string('grade'), $gradeoptions);
5e8a85aa 79 $repeated[] =& $mform->createElement('editor', 'feedback', get_string('feedback', 'question'), null, $this->editoroptions);
28a27ef1 80 $repeatedoptions['answer']['type'] = PARAM_RAW;
81 $repeatedoptions['fraction']['default'] = 0;
82 $answersoption = 'answers';
83
2aef1fe5 84 $mform->setType('answer', PARAM_NOTAGS);
85
86 $addrepeated = array();
fe6ce234 87 $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
5e8a85aa 88 $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'qtype_numerical'), $this->qtypeobj->tolerance_types());
2aef1fe5 89 $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
90 $repeatedoptions['tolerance']['default'] = 0.01;
2aef1fe5 91
92 $addrepeated[] =& $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
93 $repeatedoptions['correctanswerlength']['default'] = 2;
94
5e8a85aa 95 $answerlengthformats = array('1' => get_string('decimalformat', 'qtype_numerical'), '2' => get_string('significantfiguresformat', 'quiz'));
2aef1fe5 96 $addrepeated[] =& $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
97 array_splice($repeated, 3, 0, $addrepeated);
5e8a85aa 98 $repeated[1]->setLabel(get_string('correctanswerformula', 'qtype_calculated').'=');
28a27ef1 99
2aef1fe5 100 return $repeated;
101 }
102
271ffe3f 103 /**
104 * Add question-type specific form fields.
105 *
9aa022fe 106 * @param MoodleQuickForm $mform the form being built.
271ffe3f 107 */
c7df5006 108 protected function definition_inner(&$mform) {
9aa022fe 109 global $QTYPES;
92186abc 110 $this->qtypeobj =& $QTYPES[$this->qtype()];
cf146692 111 $label = get_string('sharedwildcards', 'qtype_calculated');
a6d46515 112 $mform->addElement('hidden', 'initialcategory', 1);
d90b016b 113 $mform->addElement('hidden', 'reload', 1);
d18e0fe6 114 $mform->setType('initialcategory', PARAM_INT);
a6d46515 115 $html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
116 $mform->insertElementBefore($mform->createElement('static','listcategory',$label,$html2),'name');
d90b016b
PP
117 if(isset($this->question->id )){
118 $mform->insertElementBefore($mform->createElement('static','initialname',get_string('questionstoredname','qtype_calculated'),$this->initialname),'name');
119 };
a6d46515 120 $addfieldsname='updatecategory';
121 $addstring=get_string("updatecategory", "qtype_calculated");
fe6ce234 122 $mform->registerNoSubmitButton($addfieldsname);
271e6dec 123
a6d46515 124 $mform->insertElementBefore( $mform->createElement('submit', $addfieldsname, $addstring),'listcategory');
28a27ef1 125 $mform->registerNoSubmitButton('createoptionbutton');
aeb15530 126
ab8b5142 127 //editing as regular
fe6ce234 128 $mform->setType('single', PARAM_INT);
aeb15530 129
fe6ce234
DC
130 $mform->addElement('hidden','shuffleanswers', '1');
131 $mform->setType('shuffleanswers', PARAM_INT);
132 $mform->addElement('hidden','answernumbering', 'abc');
133 $mform->setType('answernumbering', PARAM_SAFEDIR);
271ffe3f 134
271ffe3f 135 $creategrades = get_grade_options();
ab8b5142 136
fe6ce234 137 $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'), $creategrades->gradeoptions, 1, 1);
92186abc 138
271e6dec 139 $repeated = array();
271ffe3f 140
cf146692
PP
141 $QTYPES['numerical']->add_units_options($mform,$this);
142 $QTYPES['numerical']->add_units_elements($mform,$this);
fe6ce234 143
9aa022fe 144 //hidden elements
e593233a 145 $mform->addElement('hidden', 'synchronize', '');
d18e0fe6 146 $mform->setType('synchronize', PARAM_INT);
60b5ecd3 147 $mform->addElement('hidden', 'wizard', 'datasetdefinitions');
148 $mform->setType('wizard', PARAM_ALPHA);
271ffe3f 149 }
150
fe6ce234 151 function data_preprocessing($question) {
81053284
PP
152 global $QTYPES;
153
cf146692 154 $default_values = array();
271ffe3f 155 if (isset($question->options)){
156 $answers = $question->options->answers;
157 if (count($answers)) {
158 $key = 0;
159 foreach ($answers as $answer){
fe6ce234 160 $draftid = file_get_submitted_draft_itemid('feedback['.$key.']');
9af77e9d 161 $default_values['answer['.$key.']'] = $answer->answer;
92186abc 162 $default_values['fraction['.$key.']'] = $answer->fraction;
163 $default_values['tolerance['.$key.']'] = $answer->tolerance;
f7089b63 164 $default_values['tolerancetype['.$key.']'] = $answer->tolerancetype;
92186abc 165 $default_values['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
9aa022fe 166 $default_values['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
fe6ce234
DC
167 $default_values['feedback['.$key.']'] = array();
168 $default_values['feedback['.$key.']']['text'] = file_prepare_draft_area(
169 $draftid, // draftid
170 $this->context->id, // context
171 'question', // component
172 'answerfeedback', // filarea
173 !empty($answer->id)?(int)$answer->id:null, // itemid
174 $this->fileoptions, // options
175 $answer->feedback // text
176 );
177 $default_values['feedback['.$key.']']['format'] = $answer->feedbackformat;
178 $default_values['feedback['.$key.']']['itemid'] = $draftid;
271ffe3f 179 $key++;
180 }
181 }
fe6ce234
DC
182 $default_values['synchronize'] = $question->options->synchronize ;
183 // set unit data, prepare files in instruction area
184 $QTYPES['numerical']->set_numerical_unit_data($this, $question, $default_values);
81053284 185 }
28a27ef1 186 if (isset($question->options->single)){
cf146692
PP
187 $default_values['single'] = $question->options->single;
188 $default_values['answernumbering'] = $question->options->answernumbering;
189 $default_values['shuffleanswers'] = $question->options->shuffleanswers;
fe6ce234 190 // prepare feedback editor to display files in draft area
cf146692 191 }
8fc3e643 192 $default_values['submitbutton'] = get_string('nextpage', 'qtype_calculated');
193 $default_values['makecopy'] = get_string('makecopynextpage', 'qtype_calculated');
b800dc19 194 $default_values['returnurl'] = '0' ;
271e6dec 195 /* set the wild cards category display given that on loading the category element is
196 unselected when processing this function but have a valid value when processing the
0dd3e11c 197 update category button. The value can be obtain by
198 $qu->category =$this->_form->_elements[$this->_form->_elementIndex['category']]->_values[0];
199 but is coded using existing functions
fe6ce234 200 */
0ff4bd08
TH
201 $qu = new stdClass();
202 $el = new stdClass();
fe6ce234
DC
203 /* no need to call elementExists() here */
204 if ($this->_form->elementExists('category')){
79bb7202 205 $el=$this->_form->getElement('category');
fe6ce234 206 } else {
79bb7202 207 $el=$this->_form->getElement('categorymoveto');
fe6ce234
DC
208 }
209 if($value =$el->getSelected()) {
0dd3e11c 210 $qu->category =$value[0];
211 }else {
212 $qu->category=$question->category;// on load $question->category is set by question.php
271e6dec 213 }
0dd3e11c 214 $html2 = $this->qtypeobj->print_dataset_definitions_category($qu);
79bb7202 215 $this->_form->_elements[$this->_form->_elementIndex['listcategory']]->_text = $html2 ;
216 $question = (object)((array)$question + $default_values);
92186abc 217
fe6ce234 218 return $question;
271ffe3f 219 }
220
221 function qtype() {
222 return 'calculated';
223 }
224
a78890d5 225 function validation($data, $files) {
cf146692 226 global $QTYPES;
fe6ce234 227 // echo code left for testing period
28a27ef1 228
fe6ce234
DC
229 // echo "<p>question <pre>";print_r($this->question);echo "</pre></p>";
230 // echo "<p>data <pre>";print_r($data);echo "</pre></p>";
28a27ef1 231
fe93ba83 232 $errors = parent::validation($data, $files);
bfdc0bce 233 //verifying for errors in {=...} in question text;
234 $qtext = "";
fe6ce234
DC
235 $qtextremaining = $data['questiontext']['text'];
236 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']);
237 foreach ($possibledatasets as $name => $value) {
bfdc0bce 238 $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
239 }
fe6ce234
DC
240 // echo "numericalquestion qtextremaining <pre>";print_r($possibledatasets);
241 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
bfdc0bce 242 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
243 $qtext =$qtext.$qtextsplits[0];
244 $qtextremaining = $qtextsplits[1];
245 if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
246 if(!isset($errors['questiontext'])){
247 $errors['questiontext'] = $formulaerrors.':'.$regs1[1] ;
248 }else {
249 $errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
271e6dec 250 }
bfdc0bce 251 }
271e6dec 252 }
9af77e9d 253 $answers = $data['answer'];
271ffe3f 254 $answercount = 0;
a6d46515 255 $maxgrade = false;
fe6ce234 256 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']);
f6232d58 257 $mandatorydatasets = array();
258 foreach ($answers as $key => $answer){
a6d46515 259 $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
271e6dec 260 }
a6d46515 261 if ( count($mandatorydatasets )==0){
fe6ce234 262 // $errors['questiontext']=get_string('atleastonewildcard', 'qtype_datasetdependent');
f6232d58 263 foreach ($answers as $key => $answer){
9af77e9d 264 $errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_datasetdependent');
271e6dec 265 }
266 }
fe6ce234
DC
267 // regular calculated
268 foreach ($answers as $key => $answer){
269 //check no of choices
270 // the * for everykind of answer not actually implemented
271 $trimmedanswer = trim($answer);
272 if (($trimmedanswer!='')||$answercount==0){
273 $eqerror = qtype_calculated_find_formula_errors($trimmedanswer);
274 if (FALSE !== $eqerror){
275 $errors['answer['.$key.']'] = $eqerror;
9aa022fe 276 }
fe6ce234
DC
277 }
278 if ($trimmedanswer!=''){
279 if ('2' == $data['correctanswerformat'][$key]
280 && '0' == $data['correctanswerlength'][$key]) {
5e8a85aa 281 $errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed', 'qtype_calculated');
99a77ee5 282 }
fe6ce234
DC
283 if (!is_numeric($data['tolerance'][$key])){
284 $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
a6d46515 285 }
fe6ce234
DC
286 if ($data['fraction'][$key] == 1) {
287 $maxgrade = true;
288 }
289
290 $answercount++;
291 }
292 //check grades
aeb15530 293
fe6ce234 294 //TODO how should grade checking work here??
99a77ee5 295 /*if ($answer != '') {
296 if ($data['fraction'][$key] > 0) {
297 $totalfraction += $data['fraction'][$key];
298 }
299 if ($data['fraction'][$key] > $maxfraction) {
300 $maxfraction = $data['fraction'][$key];
301 }
302 }*/
fe6ce234 303 }
aeb15530 304
fe6ce234
DC
305 //grade checking :
306 /// Perform sanity checks on fractional grades
99a77ee5 307 /*if ( ) {
308 if ($maxfraction != 1) {
309 $maxfraction = $maxfraction * 100;
310 $errors['fraction[0]'] = get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
9aa022fe 311 }
99a77ee5 312 } else {
313 $totalfraction = round($totalfraction,2);
314 if ($totalfraction != 1) {
315 $totalfraction = $totalfraction * 100;
316 $errors['fraction[0]'] = get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
9aa022fe 317 }
cf146692 318 }
fe6ce234 319 $units = $data['unit'];
99a77ee5 320 if (count($units)) {
321 foreach ($units as $key => $unit){
322 if (is_numeric($unit)){
323 $errors['unit['.$key.']'] = get_string('mustnotbenumeric', 'qtype_calculated');
9aa022fe 324 }
99a77ee5 325 $trimmedunit = trim($unit);
326 $trimmedmultiplier = trim($data['multiplier'][$key]);
327 if (!empty($trimmedunit)){
328 if (empty($trimmedmultiplier)){
329 $errors['multiplier['.$key.']'] = get_string('youmustenteramultiplierhere', 'qtype_calculated');
330 }
331 if (!is_numeric($trimmedmultiplier)){
332 $errors['multiplier['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
333 }
aeb15530 334
9aa022fe 335 }
fe6ce234 336 }
cf146692 337 }*/
fe6ce234
DC
338 $QTYPES['numerical']->validate_numerical_options($data, $errors) ;
339 if ($answercount==0){
340 $errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
341 }
342 if ($maxgrade == false) {
343 $errors['fraction[0]'] = get_string('fractionsnomax', 'question');
344 }
345
9aa022fe 346
271ffe3f 347 return $errors;
348 }
349}