MDL-27412 qtype_calculatedmulti Fix lots of coding style issues.
[moodle.git] / question / type / calculatedsimple / edit_calculatedsimple_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
83a15d02 17/**
18 * Defines the editing form for the calculated simplequestion type.
19 *
b04a4319
TH
20 * @package qtype
21 * @subpackage calculatedsimple
22 * @copyright 2007 Jamie Pratt me@jamiep.org
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25
26
a17b297d
TH
27defined('MOODLE_INTERNAL') || die();
28
29
b04a4319
TH
30/**
31 * Editing form for the calculated simplequestion type.
32 *
33 * @copyright 2007 Jamie Pratt me@jamiep.org
34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
83a15d02 35 */
83a15d02 36class question_edit_calculatedsimple_form extends question_edit_form {
37 /**
38 * Handle to the question type for this question.
39 *
40 * @var question_calculatedsimple_qtype
41 */
fe6ce234 42 public $qtypeobj;
0735b509 43
fe6ce234 44 public $wildcarddisplay ;
0735b509 45
fe6ce234 46 public $questiondisplay ;
83a15d02 47
48 public $datasetdefs;
49
50 public $reload = false ;
aeb15530 51
83a15d02 52 public $maxnumber = -1;
53
54 public $regenerate = true;
55
56 public $noofitems;
aeb15530 57
83a15d02 58 public $outsidelimit = false ;
aeb15530
PS
59
60 public $commentanswer = array();
61
83a15d02 62 public $answer = array();
63
64 public $nonemptyanswer = array();
aeb15530 65
a31697ba 66 public $numbererrors = array();
67
aeb15530
PS
68 public $formdata = array();
69
83a15d02 70 function question_edit_calculatedsimple_form(&$submiturl, &$question, &$category, &$contexts, $formeditable = true){
71 global $QTYPES, $SESSION, $CFG, $DB;
83a15d02 72 $this->regenerate = true;
73 $this->question = $question;
b003b818 74
83a15d02 75 $this->qtypeobj =& $QTYPES[$this->question->qtype];
76 //get the dataset definitions for this question
77 //coming here everytime even when using a NoSubmitButton
78 //so this will only set the values to the actual question database content which is not what we want
79 //so this should be removed from here
80 // get priority to paramdatasets
aeb15530 81
fe6ce234
DC
82 if ("1" == optional_param('reload','', PARAM_INT )) {
83 $this->reload = true;
83a15d02 84 }else {
fe6ce234 85 $this->reload = false;
83a15d02 86 }
fe6ce234 87 if (!$this->reload) { // use database data as this is first pass
0735b509 88 // question->id == 0 so no stored datasets
aeb15530 89 // else get datasets
2fa83505 90 // echo "<p>question <pre>";print_r($question);echo "</pre></p>";
fe6ce234
DC
91 if (!empty($question->id)) {
92
2fa83505 93 /* if (empty($question->options)) {
83a15d02 94 $this->get_question_options($question);
2fa83505 95 }*/
83a15d02 96 $this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, array());
aeb15530 97
83a15d02 98 if(!empty($this->datasetdefs)){
1d1f5784 99 foreach ($this->datasetdefs as $defid => $datasetdef) {
aeb15530 100 // first get the items in case their number does not correspond to itemcount
1d1f5784 101 if (isset($datasetdef->id)) {
0735b509 102 $this->datasetdefs[$defid]->items = $this->qtypeobj->get_database_dataset_items($datasetdef->id);
103 if ( $this->datasetdefs[$defid]->items != '') {
104 $datasetdef->itemcount = count($this->datasetdefs[$defid]->items);
105 } else {
106 $datasetdef->itemcount = 0 ;
107 }
1d1f5784 108 }
83a15d02 109 // Get maxnumber
110 if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) {
111 $this->maxnumber = $datasetdef->itemcount;
112 }
113 }
83a15d02 114 }
1d1f5784 115
83a15d02 116 $i = 0 ;
117 foreach($this->question->options->answers as $answer){
118 $this->answer[$i] = $answer ;
119 $i++;
aeb15530 120 }
83a15d02 121 $this->nonemptyanswer = $this->answer ;
aeb15530 122 }
83a15d02 123 $datasettoremove = false;
aeb15530
PS
124 $newdatasetvalues = false ;
125 $newdataset = false ;
126 }else {
83a15d02 127 // handle reload to get values from the form-elements
128 // answers, datasetdefs and data_items
aeb15530
PS
129 // In any case the validation step will warn the user of any error in settings the values.
130 // Verification for the specific dataset values as the other parameters
83a15d02 131 // unints, feeedback etc are handled elsewhere
132 // handle request buttons :
aeb15530 133 // 'analyzequestion' (Identify the wild cards {x..} present in answers)
83a15d02 134 // 'addbutton' (create new set of datatitems)
135 // 'updatedatasets' is handled automatically on each reload
aeb15530 136 // The analyzequestion is done every time on reload
83a15d02 137 // to detect any new wild cards so that the current display reflects
138 // the mandatory (i.e. in answers) datasets
139 // to implement : don't do any changes if the question is used in a quiz.
aeb15530
PS
140 // If new datadef, new properties should erase items.
141 // Most of the data
06f80c6c 142 $datasettoremove = false;
aeb15530
PS
143 $newdatasetvalues = false ;
144 $newdataset = false ;
0735b509 145 $dummyform = new stdClass();
146 $mandatorydatasets = array();
aeb15530 147 // should not test on adding a new answer
06f80c6c 148 // should test if there are already olddatasets or if the 'analyzequestion' submit button has been clicked
fe6ce234 149 if ('' != optional_param('datasetdef', '', PARAM_RAW) || '' != optional_param('analyzequestion', '', PARAM_RAW)){
aeb15530
PS
150
151 if ( $dummyform->answer = optional_param('answer', '', PARAM_NOTAGS)) { // there is always at least one answer...
2a2c5eff 152 $fraction = optional_param('fraction', '', PARAM_NUMBER);
aeb15530
PS
153 $tolerance = optional_param('tolerance', '', PARAM_NUMBER);
154 $tolerancetype = optional_param('tolerancetype', '', PARAM_NUMBER);
155 $correctanswerlength = optional_param('correctanswerlength', '', PARAM_INT);
156 $correctanswerformat = optional_param('correctanswerformat', '', PARAM_INT);
157
06f80c6c 158 foreach( $dummyform->answer as $key => $answer ) {
aeb15530 159 if(trim($answer) != ''){ // just look for non-empty
06f80c6c 160 $this->answer[$key]=new stdClass();
161 $this->answer[$key]->answer = $answer;
2a2c5eff 162 $this->answer[$key]->fraction = $fraction[$key];
06f80c6c 163 $this->answer[$key]->tolerance = $tolerance[$key];
164 $this->answer[$key]->tolerancetype = $tolerancetype[$key];
165 $this->answer[$key]->correctanswerlength = $correctanswerlength[$key];
166 $this->answer[$key]->correctanswerformat = $correctanswerformat[$key];
167 $this->nonemptyanswer[]= $this->answer[$key];
168 $mandatorydatasets +=$this->qtypeobj->find_dataset_names($answer);
169 }
0735b509 170 }
83a15d02 171 }
06f80c6c 172 $this->datasetdefs = array();
173 // rebuild datasetdefs from old values
aeb15530
PS
174 if ($olddef = optional_param('datasetdef', '', PARAM_RAW)){
175 $calcmin = optional_param('calcmin', '', PARAM_NUMBER);
176 $calclength = optional_param('calclength', '', PARAM_INT);
b003b818 177 $calcmax = optional_param('calcmax', '', PARAM_NUMBER);
aeb15530
PS
178 $oldoptions = optional_param('defoptions', '', PARAM_RAW);
179 $newdatasetvalues = false ;
b692e4aa
AB
180 $sizeofolddef = sizeof($olddef);
181 for($key = 1; $key <= $sizeofolddef; $key++) {
06f80c6c 182 $def = $olddef[$key] ;
0ff4bd08 183 $this->datasetdefs[$def]= new stdClass() ;
06f80c6c 184 $this->datasetdefs[$def]->type = 1;
185 $this->datasetdefs[$def]->category = 0;
186 // $this->datasets[$key]->name = $datasetname;
b003b818 187 $this->datasetdefs[$def]->options = $oldoptions[$key] ;
06f80c6c 188 $this->datasetdefs[$def]->calcmin = $calcmin[$key] ;
189 $this->datasetdefs[$def]->calcmax = $calcmax[$key] ;
190 $this->datasetdefs[$def]->calclength = $calclength[$key] ;
191 //then compare with new values
192 if (preg_match('~^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$~', $this->datasetdefs[$def]->options, $regs)) {
193 if( $this->datasetdefs[$def]->calcmin != $regs[2]||
194 $this->datasetdefs[$def]->calcmax != $regs[3] ||
195 $this->datasetdefs[$def]->calclength != $regs[4]){
196 $newdatasetvalues = true ;
aeb15530 197 }
06f80c6c 198 }
199 $this->datasetdefs[$def]->options="uniform:".$this->datasetdefs[$def]->calcmin.":".$this->datasetdefs[$def]->calcmax.":".$this->datasetdefs[$def]->calclength;
200 }
201 }// if (olddef...
aeb15530
PS
202 // detect new datasets
203 $newdataset = false ;
83a15d02 204 foreach ($mandatorydatasets as $datasetname) {
205 if (!isset($this->datasetdefs["1-0-$datasetname"])) {
83a15d02 206 $key = "1-0-$datasetname";
0ff4bd08 207 $this->datasetdefs[$key]=new stdClass() ;//"1-0-$datasetname";
83a15d02 208 $this->datasetdefs[$key]->type = 1;
209 $this->datasetdefs[$key]->category = 0;
210 $this->datasetdefs[$key]->name = $datasetname;
211 $this->datasetdefs[$key]->options = "uniform:1.0:10.0:1";
aeb15530 212 $newdataset = true ;
83a15d02 213 }else {
214 $this->datasetdefs["1-0-$datasetname"]->name = $datasetname ;
215 }
216 }
aeb15530 217 // remove obsolete datasets
83a15d02 218 $datasettoremove = false;
219 foreach ($this->datasetdefs as $defkey => $datasetdef){
220 if(!isset($datasetdef->name )){
83a15d02 221 $datasettoremove = true;
222 unset($this->datasetdefs[$defkey]);
223 }
06f80c6c 224 }
aeb15530 225 }
83a15d02 226 } // handle reload
227 // create items if $newdataset and noofitems > 0 and !$newdatasetvalues
228 // eliminate any items if $newdatasetvalues
229 // eliminate any items if $datasettoremove, $newdataset, $newdatasetvalues
230 if ($datasettoremove ||$newdataset ||$newdatasetvalues ) {
231 foreach ($this->datasetdefs as $defkey => $datasetdef){
232 $datasetdef->itemcount = 0;
233 unset($datasetdef->items);
234 }
235 }
236 $maxnumber = -1 ;
0cd89526 237 if ( "" !=optional_param('addbutton', '', PARAM_TEXT)){
06f80c6c 238 $maxnumber = optional_param('selectadd', '', PARAM_INT); //FIXME: sloppy coding
83a15d02 239 foreach ($this->datasetdefs as $defid => $datasetdef) {
240 $datasetdef->itemcount = $maxnumber;
241 unset($datasetdef->items);
242 for ($numberadded =1 ; $numberadded <= $maxnumber; $numberadded++){
0ff4bd08 243 $datasetitem = new stdClass();
83a15d02 244 $datasetitem->itemnumber = $numberadded;
245 $datasetitem->id = 0;
246 $datasetitem->value = $this->qtypeobj->generate_dataset_item($datasetdef->options);
247 $this->datasetdefs[$defid]->items[$numberadded]=$datasetitem ;
83a15d02 248 }//for number added
249 }// datasetsdefs end
250 $this->maxnumber = $maxnumber ;
83a15d02 251 }else {
0735b509 252 // Handle reload dataset items
0cd89526 253 if ( "" !=optional_param('definition','', PARAM_NOTAGS)&& !($datasettoremove ||$newdataset ||$newdatasetvalues )){
83a15d02 254 $i = 1;
aeb15530
PS
255 $fromformdefinition = optional_param('definition', '', PARAM_NOTAGS);
256 $fromformnumber = optional_param('number', '', PARAM_INT);
257 $fromformitemid = optional_param('itemid', '', PARAM_INT);
83a15d02 258 ksort($fromformdefinition);
aeb15530 259
83a15d02 260 foreach($fromformdefinition as $key => $defid) {
261 $addeditem = new stdClass();
262 $addeditem->id = $fromformitemid[$i] ;
263 $addeditem->value = $fromformnumber[$i];
264 $addeditem->itemnumber = ceil($i / count($this->datasetdefs));
265 $this->datasetdefs[$defid]->items[$addeditem->itemnumber]=$addeditem ;
266 $this->datasetdefs[$defid]->itemcount = $i ;
267 $i++;
268 }
269 }
270 if (isset($addeditem->itemnumber) && $this->maxnumber < $addeditem->itemnumber){
271 $this->maxnumber = $addeditem->itemnumber;
aeb15530 272 if(!empty($this->datasetdefs)){
83a15d02 273 foreach ($this->datasetdefs as $datasetdef) {
274 $datasetdef->itemcount = $this->maxnumber ;
275 }
276 }
277 }
278 }
279
83a15d02 280 parent::question_edit_form($submiturl, $question, $category, $contexts, $formeditable);
281 }
282
283 function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
aeab3f8d 284 $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
83a15d02 285 $mform->setType('answer', PARAM_NOTAGS);
286 $addrepeated = array();
287 $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
288 $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
289 $repeatedoptions['tolerance']['default'] = 0.01;
5e8a85aa 290 $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'qtype_numerical'), $this->qtypeobj->tolerance_types());
83a15d02 291 $addrepeated[] =& $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
292 $repeatedoptions['correctanswerlength']['default'] = 2;
293
5e8a85aa 294 $answerlengthformats = array('1' => get_string('decimalformat', 'qtype_numerical'), '2' => get_string('significantfiguresformat', 'qtype_numerical'));
83a15d02 295 $addrepeated[] =& $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
296 array_splice($repeated, 3, 0, $addrepeated);
5e8a85aa 297 $repeated[1]->setLabel(get_string('correctanswerformula', 'qtype_calculated').'=');
83a15d02 298
299 return $repeated;
300 }
301
302 /**
303 * Add question-type specific form fields.
304 *
305 * @param MoodleQuickForm $mform the form being built.
306 */
c7df5006 307 protected function definition_inner($mform) {
83a15d02 308 global $QTYPES;
309 $this->qtypeobj =& $QTYPES[$this->qtype()];
310 $strquestionlabel = $this->qtypeobj->comment_header($this->nonemptyanswer);
2fa83505 311 $label = get_string("sharedwildcards", "qtype_calculated");
b003b818 312 $mform->addElement('hidden', 'synchronize', 0);
83a15d02 313 $mform->addElement('hidden', 'initialcategory', 1);
d18e0fe6 314 $mform->setType('initialcategory', PARAM_INT);
83a15d02 315 $mform->addElement('hidden', 'reload', 1);
d18e0fe6 316 $mform->setType('reload', PARAM_INT);
a31697ba 317 $addfieldsname='updatequestion value';
83a15d02 318 $addstring=get_string("updatecategory", "qtype_calculated");
a31697ba 319 $mform->registerNoSubmitButton($addfieldsname);
fe6ce234
DC
320 // put a submit button to stop supplementary answers on update answers parameters
321 // $mform->insertElementBefore($mform->createElement('submit', $addfieldsname, $addstring), 'listcategory');
83a15d02 322
323 $creategrades = get_grade_options();
324 $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
fe6ce234 325 $creategrades->gradeoptions, 1, 1);
83a15d02 326
cf146692 327 $QTYPES['numerical']->add_units_options($mform,$this);
aeb15530 328
cf146692 329 $QTYPES['numerical']->add_units_elements($mform,$this);
83a15d02 330 $label = "<div class='mdl-align'></div><div class='mdl-align'>".get_string('wildcardrole', 'qtype_calculatedsimple')."</div>";
331 $mform->addElement('html', "<div class='mdl-align'>&nbsp;</div>");
332 $mform->addElement('html', $label);// explaining the role of datasets so other strings can be shortened
333
334 $mform->addElement('submit', 'analyzequestion', get_string('findwildcards','qtype_calculatedsimple'));
335 $mform->registerNoSubmitButton('analyzequestion');
336 $mform->closeHeaderBefore('analyzequestion');
337 if ( "" != optional_param('analyzequestion','', PARAM_RAW)) {
338
339 $this->wizarddisplay = true;
83a15d02 340
341 }else {
342 $this->wizwarddisplay = false;
343 }
344 if ($this->maxnumber != -1){
345 $this->noofitems = $this->maxnumber;
346 } else {
347 $this->noofitems = 0;
348 }
a31697ba 349 if(!empty($this->datasetdefs)){//So there are some datadefs
fe6ce234 350 // we put them on the page
0735b509 351 $key = 0;
352 $mform->addElement('header', 'additemhdr', get_string('wildcardparam', 'qtype_calculatedsimple'));
353 $idx = 1;
354 if(!empty($this->datasetdefs)){// unnecessary test
355 $j = (($this->noofitems) * count($this->datasetdefs))+1;//
356 foreach ($this->datasetdefs as $defkey => $datasetdef){
2fa83505 357 $mform->addElement('static', "na[$j]", get_string('param', 'qtype_calculated', $datasetdef->name));
0735b509 358 $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j);
359 $mform->addElement('hidden', "datasetdef[$idx]");
360 $mform->setType("datasetdef[$idx]", PARAM_RAW);
b003b818 361 $mform->addElement('hidden', "defoptions[$idx]");
aeb15530 362 $mform->setType("defoptions[$idx]", PARAM_RAW);
0735b509 363 $idx++;
364 $mform->addElement('static', "divider[$j]", '', '<hr />');
365 $j++;
366 }
367 }
368 //this should be done before the elements are created and stored as $this->formdata ;
369 //fill out all data sets and also the fields for the next item to add.
fe6ce234
DC
370 /*Here we do already the values error analysis so that
371 * we could force all wild cards values display if there is an error in values.
372 * as using a , in a number */
373 $this->numbererrors = array();
0735b509 374 if(!empty($this->datasetdefs)){
fe6ce234
DC
375 $j = $this->noofitems * count($this->datasetdefs);
376 for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--){
377 $data = array();
378 $numbererrors = array() ;
0ff4bd08 379 $comment = new stdClass();
fe6ce234
DC
380 $comment->stranswers = array();
381 $comment->outsidelimit = false ;
382 $comment->answers = array();
383
384 foreach ($this->datasetdefs as $defid => $datasetdef){
385 if (isset($datasetdef->items[$itemnumber])){
386 $this->formdata["definition[$j]"] = $defid;
387 $this->formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id;
388 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
389 $this->formdata["number[$j]"] = $number = $datasetdef->items[$itemnumber]->value;
390 if(! is_numeric($number)){
0ff4bd08 391 $a = new stdClass();
fe6ce234
DC
392 $a->name = '{'.$datasetdef->name.'}' ;
393 $a->value = $datasetdef->items[$itemnumber]->value ;
394 if (stristr($number,',')){
2fa83505 395 $this->numbererrors["number[$j]"]=get_string('nocommaallowed', 'qtype_calculated');
fe6ce234 396 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />";
aeb15530 397
fe6ce234 398 }else {
2fa83505 399 $this->numbererrors["number[$j]"]= get_string('notvalidnumber','qtype_calculated',$a);
0735b509 400 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />";
401 //$comment->outsidelimit = false ;
fe6ce234
DC
402 }
403 }else if( stristr($number,'x')){ // hexa will pass the test
0ff4bd08 404 $a = new stdClass();
fe6ce234
DC
405 $a->name = '{'.$datasetdef->name.'}' ;
406 $a->value = $datasetdef->items[$itemnumber]->value ;
407 $this->numbererrors['number['.$j.']']= get_string('hexanotallowed','qtype_calculated',$a);
408 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />";
409 } else if( is_nan($number)){
0ff4bd08 410 $a = new stdClass();
fe6ce234
DC
411 $a->name = '{'.$datasetdef->name.'}' ;
412 $a->value = $datasetdef->items[$itemnumber]->value ;
413 $this->numbererrors["number[$j]"]= get_string('notvalidnumber','qtype_calculated',$a);
414 $numbererrors .= $this->numbererrors['number['.$j.']']."<br />";
415 // $val = 1.0 ;
0735b509 416 }
0735b509 417 }
fe6ce234
DC
418 $j--;
419 }
420 if($this->noofitems != 0 ) {
421 if (empty($numbererrors)) {
422 if (!isset($this->question->id)) {
423 $this->question->id = 0 ;
424 }
425 $this->question->questiontext = !empty($this->question->questiontext)?$this->question->questiontext:'';
426 $comment = $this->qtypeobj->comment_on_datasetitems($this->qtypeobj, $this->question->id, $this->question->questiontext, $this->nonemptyanswer, $data, $itemnumber);
427 if ($comment->outsidelimit) {
428 $this->outsidelimit=$comment->outsidelimit ;
0735b509 429 }
fe6ce234
DC
430 $totalcomment='';
431
432 foreach ($this->nonemptyanswer as $key => $answer) {
433 $totalcomment .= $comment->stranswers[$key].'<br/>';
434 }
435
436 $this->formdata['answercomment['.$itemnumber.']'] = $totalcomment ;
437 }
0735b509 438 }
fe6ce234
DC
439 }
440 $this->formdata['selectdelete'] = '1';
441 $this->formdata['selectadd'] = '1';
442 $j = $this->noofitems * count($this->datasetdefs)+1;
443 $data = array(); // data for comment_on_datasetitems later
0735b509 444 $idx =1 ;
445 foreach ($this->datasetdefs as $defid => $datasetdef){
446 $this->formdata["datasetdef[$idx]"] = $defid;
447 $idx++;
448 }
fe6ce234
DC
449 $this->formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $this->formdata);
450 }
451
452
453 $addoptions = Array();
454 $addoptions['1']='1';
455 for ($i=10; $i<=100 ; $i+=10){
456 $addoptions["$i"]="$i";
457 }
458 $showoptions = Array();
459 $showoptions['1']='1';
460 $showoptions['2']='2';
461 $showoptions['5']='5';
462 for ($i=10; $i<=100 ; $i+=10){
463 $showoptions["$i"]="$i";
464 }
465 $mform->closeHeaderBefore('additemhdr');
466 $addgrp = array();
467 $addgrp[] =& $mform->createElement('submit', 'addbutton', get_string('generatenewitemsset', 'qtype_calculatedsimple'));
468 $addgrp[] =& $mform->createElement('select', "selectadd", '', $addoptions);
469 $addgrp[] = & $mform->createElement('static',"stat",'',get_string('newsetwildcardvalues', 'qtype_calculatedsimple'));
470 $mform->addGroup($addgrp, 'addgrp', '', ' ', false);
471 $mform->registerNoSubmitButton('addbutton');
472 $mform->closeHeaderBefore('addgrp');
473 $addgrp1 = array();
474 $addgrp1[] =& $mform->createElement('submit', 'showbutton', get_string('showitems', 'qtype_calculatedsimple'));
475 $addgrp1[] =& $mform->createElement('select', "selectshow",'' , $showoptions);
476 $addgrp1[] = & $mform->createElement('static',"stat",'',get_string('setwildcardvalues', 'qtype_calculatedsimple'));
477 $mform->addGroup($addgrp1, 'addgrp1', '', ' ', false);
478 $mform->registerNoSubmitButton('showbutton');
479 $mform->closeHeaderBefore('addgrp1');
480 $mform->addElement('static', "divideradd", '', '');
481 if ($this->noofitems == 0) {
482 $mform->addElement('static','warningnoitems','','<span class="error">'.get_string('youmustaddatleastonevalue', 'qtype_calculatedsimple').'</span>');
483 $mform->closeHeaderBefore('warningnoitems');
484 }else {
485 $mform->addElement('header', 'additemhdr1', get_string('wildcardvalues', 'qtype_calculatedsimple'));
486 $mform->closeHeaderBefore('additemhdr1');
487 // $mform->addElement('header', '', get_string('itemno', 'qtype_calculated', ""));
488 if( !empty($this->numbererrors) || $this->outsidelimit) {
489 $mform->addElement('static', "alert", '', '<span class="error">'.get_string('useadvance', 'qtype_calculatedsimple').'</span>');
0735b509 490 }
491
fe6ce234
DC
492 $mform->addElement('submit', 'updatedatasets', get_string('updatewildcardvalues', 'qtype_calculatedsimple'));
493 $mform->registerNoSubmitButton('updatedatasets');
494 $mform->setAdvanced("updatedatasets",true);
aeb15530 495
fe6ce234
DC
496 //------------------------------------------------------------------------------------------------------------------------------
497 $j = $this->noofitems * count($this->datasetdefs);
498 $k = 1 ;
0cd89526 499 if ("" != optional_param('selectshow', '', PARAM_INT)){
fe6ce234
DC
500 $k = optional_param('selectshow', '', PARAM_INT);
501 }
aeb15530 502
fe6ce234
DC
503 for ($i = $this->noofitems; $i >= 1 ; $i--){
504 foreach ($this->datasetdefs as $defkey => $datasetdef){
505 if($k > 0 || $this->outsidelimit || !empty($this->numbererrors ) ){
506 $mform->addElement('text',"number[$j]" , get_string('wildcard', 'qtype_calculatedsimple', $datasetdef->name));
507 $mform->setAdvanced("number[$j]",true);
508 if(!empty($this->numbererrors['number['.$j.']']) ){
509 $mform->addElement('static', "numbercomment[$j]",'','<span class="error">'.$this->numbererrors['number['.$j.']'].'</span>');
510 $mform->setAdvanced("numbercomment[$j]",true);
511 }
512 }else {
513 $mform->addElement('hidden',"number[$j]" , get_string('wildcard', 'qtype_calculatedsimple', $datasetdef->name));
514 }
515 $mform->setType("number[$j]", PARAM_NUMBER);
83a15d02 516
fe6ce234
DC
517 $mform->addElement('hidden', "itemid[$j]");
518 $mform->setType("itemid[$j]", PARAM_INT);
a31697ba 519
fe6ce234
DC
520 $mform->addElement('hidden', "definition[$j]");
521 $mform->setType("definition[$j]", PARAM_NOTAGS);
83a15d02 522
fe6ce234
DC
523 $j--;
524 }
525 if (!empty( $strquestionlabel) && ($k > 0 || $this->outsidelimit || !empty($this->numbererrors ) ) ){
526 // $repeated[] =& $mform->addElement('static', "answercomment[$i]", $strquestionlabel);
527 $mform->addElement('static', "answercomment[$i]", "<b>".get_string('setno', 'qtype_calculatedsimple', $i)."</b>&nbsp;&nbsp;".$strquestionlabel);
aeb15530 528
fe6ce234
DC
529 }
530 if($k > 0 || $this->outsidelimit || !empty($this->numbererrors )){
531 $mform->addElement('static', "divider1[$j]", '', '<hr />');
aeb15530 532
fe6ce234
DC
533 }
534 $k-- ;
535 }
536 }
537 // if ($this->outsidelimit){
538 // $mform->addElement('static','outsidelimit','','');
539 // }
540 }else {
541 $mform->addElement('static','warningnowildcards','','<span class="error">'.get_string('atleastonewildcard', 'qtype_calculatedsimple').'</span>');
542 $mform->closeHeaderBefore('warningnowildcards');
83a15d02 543 }
83a15d02 544
b003b818 545
fe6ce234 546 //------------------------------------------------------------------------------------------------------------------------------
83a15d02 547 //non standard name for button element needed so not using add_action_buttons
548 //hidden elements
549
550 $mform->addElement('hidden', 'id');
551 $mform->setType('id', PARAM_INT);
552
553 $mform->addElement('hidden', 'courseid');
554 $mform->setType('courseid', PARAM_INT);
555 $mform->setDefault('courseid', 0);
556
557 $mform->addElement('hidden', 'cmid');
558 $mform->setType('cmid', PARAM_INT);
559 $mform->setDefault('cmid', 0);
560 if (!empty($this->question->id)){
561 if ($this->question->formoptions->cansaveasnew){
fe6ce234
DC
562 $mform->addElement('header', 'additemhdr', get_string('converttocalculated', 'qtype_calculatedsimple'));
563 $mform->closeHeaderBefore('additemhdr');
aeb15530 564
83a15d02 565 $mform->addElement('checkbox', 'convert','' ,get_string('willconverttocalculated', 'qtype_calculatedsimple'));
fe6ce234 566 $mform->setDefault('convert', 0);
83a15d02 567
83a15d02 568 }
fe6ce234 569 }
83a15d02 570 }
571
fe6ce234 572 function data_preprocessing($question) {
a3e153c2 573 global $QTYPES;
fe6ce234
DC
574 $answer = $this->answer;
575 $default_values = array();
576 if (count($answer)) {
577 $key = 0;
578 foreach ($answer as $answer){
579 $default_values['answer['.$key.']'] = $answer->answer; // is necessary ? to-do test it
580 $default_values['fraction['.$key.']'] = $answer->fraction;
581 $default_values['tolerance['.$key.']'] = $answer->tolerance;
582 $default_values['tolerancetype['.$key.']'] = $answer->tolerancetype;
583 $default_values['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
584 $default_values['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
585
586 // prepare draft files
587 $draftid = file_get_submitted_draft_itemid('feedback['.$key.']');
588 $default_values['feedback['.$key.']']['text'] = file_prepare_draft_area(
589 $draftid, // draftid
590 $this->context->id, // context
591 'question', // component
592 'answerfeedback', // filarea
593 !empty($answer->id)?(int)$answer->id:null, // itemid
594 $this->fileoptions, // options
595 !empty($answer->feedback)?$answer->feedback:'' // text
596 );
597 $default_values['feedback['.$key.']']['format'] = !empty($answer->feedbackformat)?$answer->feedbackformat:editors_get_preferred_format();
598 $default_values['feedback['.$key.']']['itemid'] = $draftid;
599
600 $key++;
b003b818 601 }
fe6ce234
DC
602 }
603 $default_values['synchronize'] = 0 ;
604 $QTYPES['numerical']->set_numerical_unit_data($this, $question, $default_values);
605 /* if (isset($question->options)){
cf146692
PP
606 $default_values['unitgradingtype'] = $question->options->unitgradingtype ;
607 $default_values['unitpenalty'] = $question->options->unitpenalty ;
608 switch ($question->options->showunits){
609 case 'O' :
fe6ce234 610 case '1' :
cf146692
PP
611 $default_values['showunits0'] = $question->options->showunits ;
612 $default_values['unitrole'] = 0 ;
613 break;
614 case '2' :
fe6ce234 615 case '3' :
cf146692
PP
616 $default_values['showunits1'] = $question->options->showunits ;
617 $default_values['unitrole'] = 1 ;
618 break;
fe6ce234 619 }
cf146692
PP
620 $default_values['unitsleft'] = $question->options->unitsleft ;
621 $default_values['instructions'] = $question->options->instructions ;
622
623 if (isset($question->options->units)){
624 $units = array_values($question->options->units);
625 if (!empty($units)) {
626 foreach ($units as $key => $unit){
627 $default_values['unit['.$key.']'] = $unit->unit;
628 $default_values['multiplier['.$key.']'] = $unit->multiplier;
629 }
83a15d02 630 }
631 }
632 }
fe6ce234
DC
633 */
634 $key = 0 ;
83a15d02 635
636 $formdata = array();
637 $fromform = new stdClass();
a31697ba 638 //this should be done before the elements are created and stored as $this->formdata ;
83a15d02 639 //fill out all data sets and also the fields for the next item to add.
fe6ce234 640 /* if(!empty($this->datasetdefs)){
83a15d02 641 $j = $this->noofitems * count($this->datasetdefs);
fe6ce234 642 for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--){
83a15d02 643 $data = array();
644 foreach ($this->datasetdefs as $defid => $datasetdef){
645 if (isset($datasetdef->items[$itemnumber])){
646 $formdata["number[$j]"] = $datasetdef->items[$itemnumber]->value;
647 $formdata["definition[$j]"] = $defid;
648 $formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id;
649 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
650 }
651 $j--;
652 }
fe6ce234
DC
653 // echo "<p>answers avant comment <pre>";print_r($answer);echo"</pre></p>";
654 // echo "<p>data avant comment <pre>";print_r($data);echo"</pre></p>";
aeb15530 655
83a15d02 656 if($this->noofitems != 0 ) {
657 if(!isset($question->id)) $question->id = 0 ;
fe6ce234
DC
658 $comment = $this->qtypeobj->comment_on_datasetitems($question->id,$this->nonemptyanswer, $data, $itemnumber);//$this->
659 if ($comment->outsidelimit) {
660 $this->outsidelimit=$comment->outsidelimit ;
661 }
662 $totalcomment='';
663 // echo "<p> comment <pre>";print_r($comment);echo"</pre></p>";
83a15d02 664
fe6ce234
DC
665 foreach ($this->nonemptyanswer as $key => $answer) {
666 $totalcomment .= $comment->stranswers[$key].'<br/>';
667 }
83a15d02 668
fe6ce234
DC
669 $formdata['answercomment['.$itemnumber.']'] = $totalcomment ;
670 }
83a15d02 671 }
fe6ce234
DC
672 // $formdata['reload'] = '1';
673 // $formdata['nextpageparam[forceregeneration]'] = $this->regenerate;
83a15d02 674 $formdata['selectdelete'] = '1';
675 $formdata['selectadd'] = '1';
676 $j = $this->noofitems * count($this->datasetdefs)+1;
677 $data = array(); // data for comment_on_datasetitems later
678 $idx =1 ;
679 foreach ($this->datasetdefs as $defid => $datasetdef){
680 $formdata["datasetdef[$idx]"] = $defid;
681 $idx++;
682 }
683 $formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $formdata);
fe6ce234 684 }*/
a31697ba 685 $question = (object)((array)$question + $default_values+$this->formdata );
83a15d02 686
fe6ce234 687 return $question;
83a15d02 688 }
689
690 function qtype() {
691 return 'calculatedsimple';
692 }
693
694 function validation($data, $files) {
cf146692 695 global $QTYPES;
83a15d02 696 $errors = parent::validation($data, $files);
697 //verifying for errors in {=...} in question text;
698 $qtext = "";
fe6ce234
DC
699 $qtextremaining = $data['questiontext']['text'];
700 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']);
06f80c6c 701 foreach ($possibledatasets as $name => $value) {
83a15d02 702 $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
703 }
6dbcacee 704 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
83a15d02 705 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
706 $qtext =$qtext.$qtextsplits[0];
707 $qtextremaining = $qtextsplits[1];
708 if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
709 if(!isset($errors['questiontext'])){
710 $errors['questiontext'] = $formulaerrors.':'.$regs1[1] ;
711 }else {
712 $errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
713 }
714 }
715 }
716 $answers = $data['answer'];
717 $answercount = 0;
718 $maxgrade = false;
fe6ce234 719 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']);
83a15d02 720 $mandatorydatasets = array();
721 foreach ($answers as $key => $answer){
722 $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
723 }
724 if ( count($mandatorydatasets )==0){
a31697ba 725 foreach ($answers as $key => $answer){
2fa83505 726 $errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_calculated');
83a15d02 727 }
728 }
729 foreach ($answers as $key => $answer){
730 //check no of choices
731 // the * for everykind of answer not actually implemented
732 $trimmedanswer = trim($answer);
733 if (($trimmedanswer!='')||$answercount==0){
734 $eqerror = qtype_calculated_find_formula_errors($trimmedanswer);
735 if (FALSE !== $eqerror){
736 $errors['answer['.$key.']'] = $eqerror;
737 }
738 }
739 if ($trimmedanswer!=''){
740 if ('2' == $data['correctanswerformat'][$key]
741 && '0' == $data['correctanswerlength'][$key]) {
5e8a85aa 742 $errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed','qtype_calculated');
83a15d02 743 }
744 if (!is_numeric($data['tolerance'][$key])){
745 $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
746 }
747 if ($data['fraction'][$key] == 1) {
748 $maxgrade = true;
749 }
750
751 $answercount++;
752 }
753 //check grades
754
755 //TODO how should grade checking work here??
756 /*if ($answer != '') {
757 if ($data['fraction'][$key] > 0) {
758 $totalfraction += $data['fraction'][$key];
759 }
760 if ($data['fraction'][$key] > $maxfraction) {
761 $maxfraction = $data['fraction'][$key];
762 }
763 }*/
764 }
765 //grade checking :
766 /// Perform sanity checks on fractional grades
767 /*if ( ) {
768 if ($maxfraction != 1) {
769 $maxfraction = $maxfraction * 100;
770 $errors['fraction[0]'] = get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
771 }
772 } else {
773 $totalfraction = round($totalfraction,2);
774 if ($totalfraction != 1) {
775 $totalfraction = $totalfraction * 100;
776 $errors['fraction[0]'] = get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
777 }
778 }*/
cf146692 779 $QTYPES['numerical']->validate_numerical_options($data, $errors) ;
83a15d02 780 $units = $data['unit'];
781 if (count($units)) {
782 foreach ($units as $key => $unit){
783 if (is_numeric($unit)){
784 $errors['unit['.$key.']'] = get_string('mustnotbenumeric', 'qtype_calculated');
785 }
786 $trimmedunit = trim($unit);
787 $trimmedmultiplier = trim($data['multiplier'][$key]);
788 if (!empty($trimmedunit)){
789 if (empty($trimmedmultiplier)){
790 $errors['multiplier['.$key.']'] = get_string('youmustenteramultiplierhere', 'qtype_calculated');
791 }
792 if (!is_numeric($trimmedmultiplier)){
793 $errors['multiplier['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
794 }
795
796 }
797 }
798 }
799 if ($answercount==0){
800 $errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
801 }
802 if ($maxgrade == false) {
803 $errors['fraction[0]'] = get_string('fractionsnomax', 'question');
804 }
5e8a85aa 805 if (isset($data['savechanges']) && ($this->noofitems==0) ){
83a15d02 806 $errors['warning'] = get_string('warning', 'mnet');
aeb15530 807 }
83a15d02 808 if ($this->outsidelimit){
809 // if(!isset($errors['warning'])) $errors['warning']=' ';
810 $errors['outsidelimits'] = get_string('oneanswertrueansweroutsidelimits','qtype_calculated');
811 }
aeb15530 812 /*Here we use the already done the error analysis so that
0735b509 813 * we could force all wild cards values display if there is an error in values.
b003b818 814 * as using a , in a number *//*
83a15d02 815 $numbers = $data['number'];
816 foreach ($numbers as $key => $number){
817 if(! is_numeric($number)){
818 if (stristr($number,',')){
2fa83505 819 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
aeb15530 820 }else {
2fa83505 821 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
83a15d02 822 }
823 }else if( stristr($number,'x')){
2fa83505 824 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
83a15d02 825 } else if( is_nan($number)){
2fa83505 826 $errors['number['.$key.']'] = get_string('notvalidnumber', 'qtype_calculated');
aeb15530 827 }
83a15d02 828 }
b003b818 829 */
83a15d02 830 if ( $this->noofitems==0 ){
831 $errors['warning'] = get_string('warning', 'mnet');
832 }
833
834 return $errors;
835 }
836}