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