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