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