Updated the HEAD build version to 20090601
[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();
44
45
46 function question_edit_calculatedsimple_form(&$submiturl, &$question, &$category, &$contexts, $formeditable = true){
47 global $QTYPES, $SESSION, $CFG, $DB;
48 // echo "<p> QTYPES <pre>";print_r($QTYPES);echo"</pre></p>";
49 // echo "<p> session <pre>";print_r($SESSION);echo"</pre></p>";
50 // echo "<p> question <pre>";print_r($question);echo"</pre></p>";
51 $this->regenerate = true;
52 $this->question = $question;
53 $this->qtypeobj =& $QTYPES[$this->question->qtype];
54 //get the dataset definitions for this question
55 //coming here everytime even when using a NoSubmitButton
56 //so this will only set the values to the actual question database content which is not what we want
57 //so this should be removed from here
58 // get priority to paramdatasets
59
60 // question->id == 0 so no stored datasets
61 // else get datasets
62 if ( "1" == optional_param('reload','', PARAM_INT )) {
63 // echo "<p> optional reload exist </p>";
64 $this->reload = true ;
65 }else {
66 $this->reload = false ;
67 }
68 if(!$this->reload ){ // use database data as this is first pass
69 if ( !empty($question->id)) {
70 if (empty($question->options)) {
71 $this->get_question_options($question);
72 }
73 $this->datasetdefs = $this->qtypeobj->get_dataset_definitions($question->id, array());
74
75 if(!empty($this->datasetdefs)){
76 foreach ($this->datasetdefs as $datasetdef) {
77 // Get maxnumber
78 if ($this->maxnumber == -1 || $datasetdef->itemcount < $this->maxnumber) {
79 $this->maxnumber = $datasetdef->itemcount;
80 }
81 }
82 foreach ($this->datasetdefs as $defid => $datasetdef) {
83 if (isset($datasetdef->id)) {
84 $this->datasetdefs[$defid]->items = $DB->get_records_sql( // Use number as key!!
85 " SELECT itemnumber, definition, id, value
86 FROM {question_dataset_items}
87 WHERE definition = ? ", array($datasetdef->id));
88 }
89 }
90 }
91 $i = 0 ;
92 foreach($this->question->options->answers as $answer){
93 $this->answer[$i] = $answer ;
94 $i++;
95 }
96 $this->nonemptyanswer = $this->answer ;
97 }
98 $datasettoremove = false;
99 $newdatasetvalues = false ;
100 $newdataset = false ;
101 }else {
102 // handle reload to get values from the form-elements
103 // answers, datasetdefs and data_items
104 // verify for the specific dataset values as the other parameters
105 // unints, feeedback etc are handled elsewhere
106 // handle request buttons :
107 // 'analyzequestion' (Identify the wild cards {x..} present in answers)
108 // 'addbutton' (create new set of datatitems)
109 // 'updatedatasets' is handled automatically on each reload
110 // The analyzequestion is done every time on reload
111 // to detect any new wild cards so that the current display reflects
112 // the mandatory (i.e. in answers) datasets
113 // to implement : don't do any changes if the question is used in a quiz.
114 // If new datadef, new properties should erase items.
115 $dummyform = new stdClass();
116 $mandatorydatasets = array();
117
118 if ( $dummyform->answer =optional_param('answer')) { // there is always at least one answer...
119 $fraction = optional_param('fraction') ;
120 $feedback = optional_param('feedback') ;
121 $tolerance = optional_param('tolerance') ;
122 $tolerancetype = optional_param('tolerancetype') ;
123 $correctanswerlength = optional_param('correctanswerlength') ;
124 $correctanswerformat = optional_param('correctanswerformat') ;
125
126 foreach( $dummyform->answer as $key => $answer ) {
127 if(trim($answer) != ''){ // just look for non-empty
128 $this->answer[$key]=new stdClass();
129 $this->answer[$key]->answer = $answer;
130 $this->answer[$key]->fraction = $fraction[$key];
131 $this->answer[$key]->feedback = $feedback[$key];
132 $this->answer[$key]->tolerance = $tolerance[$key];
133 $this->answer[$key]->tolerancetype = $tolerancetype[$key];
134 $this->answer[$key]->correctanswerlength = $correctanswerlength[$key];
135 $this->answer[$key]->correctanswerformat = $correctanswerformat[$key];
136 $this->nonemptyanswer[]= $this->answer[$key];
137 $mandatorydatasets +=$this->qtypeobj->find_dataset_names($answer);
138 }
139 }
140 }
141 // echo "<p>this->answer <pre>";print_r($this->answer);echo"</pre></p>";
142 // echo "<p>this->answer <pre>";print_r($this->nonemptyanswer);echo"</pre></p>";
143 $this->datasetdefs = array();
144 // rebuild datasetdefs from old values
145 $olddef = optional_param('datasetdef');
146 $oldoptions = optional_param('defoptions');
147 $calcmin = optional_param('calcmin') ;
148 $calclength = optional_param('calclength') ;
149 $calcmax = optional_param('calcmax') ;
150 /* echo "<p> calcmin <pre>";print_r(optional_param('calcmin'));echo"</pre></p>";
151 echo "<p> calcmax <pre>";print_r(optional_param('calcmax'));echo"</pre></p>";
152 echo "<p> calclength <pre>";print_r(optional_param('calclength'));echo"</pre></p>";*/
153 $newdatasetvalues = false ;
154 // echo "<p> olddef <pre>";print_r(optional_param('datasetdef'));echo"</pre></p>";
155
156 for($key = 1 ; $key <= sizeof($olddef) ; $key++) {
157 $def = $olddef[$key] ;
158 $this->datasetdefs[$def]= new stdClass ;
159 $this->datasetdefs[$def]->type = 1;
160 $this->datasetdefs[$def]->category = 0;
161 // $this->datasets[$key]->name = $datasetname;
162 $this->datasetdefs[$def]->options = $oldoptions[$key] ;
163 $this->datasetdefs[$def]->calcmin = $calcmin[$key] ;
164 $this->datasetdefs[$def]->calcmax = $calcmax[$key] ;
165 $this->datasetdefs[$def]->calclength = $calclength[$key] ;
166 //then compare with new values
167 if (ereg('^(uniform|loguniform):([^:]*):([^:]*):([0-9]*)$', $this->datasetdefs[$def]->options, $regs)) {
168 if( $this->datasetdefs[$def]->calcmin != $regs[2]||
169 $this->datasetdefs[$def]->calcmax != $regs[3] ||
170 $this->datasetdefs[$def]->calclength != $regs[4]){
171 $newdatasetvalues = true ;
172 // echo "<p> new datasetdefs values ".$regs[2]."xx". $regs[3]."xx".$regs[4]."</p>";
173 }
174
175 }
176 $this->datasetdefs[$def]->options="uniform:".$this->datasetdefs[$def]->calcmin.":".$this->datasetdefs[$def]->calcmax.":".$this->datasetdefs[$def]->calclength;
177 }
178
179 // echo "<p>this datasetdefs <pre>";print_r($this->datasetdefs);echo"</pre></p>";
180 // detect new datasets
181 $newdataset = false ;
182 foreach ($mandatorydatasets as $datasetname) {
183 if (!isset($this->datasetdefs["1-0-$datasetname"])) {
184 // list($options, $selected) =
185 // $this->dataset_options($form, $datasetname);
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";
192 $newdataset = true ;
193 // echo "<p> new datasetdefs $datasetname </p>";
194 // $form->dataset[$key]=$selected ;
195 //$key++;
196 }else {
197 $this->datasetdefs["1-0-$datasetname"]->name = $datasetname ;
198 }
199 }
200 // remove obsolete datasets
201 $datasettoremove = false;
202 foreach ($this->datasetdefs as $defkey => $datasetdef){
203 if(!isset($datasetdef->name )){
204 // echo "<p> dataset $defkey to remove </p>";
205 $datasettoremove = true;
206 unset($this->datasetdefs[$defkey]);
207 }
208 }
209
210
211 } // handle reload
212 // create items if $newdataset and noofitems > 0 and !$newdatasetvalues
213 // eliminate any items if $newdatasetvalues
214 // eliminate any items if $datasettoremove, $newdataset, $newdatasetvalues
215 if ($datasettoremove ||$newdataset ||$newdatasetvalues ) {
216 foreach ($this->datasetdefs as $defkey => $datasetdef){
217 $datasetdef->itemcount = 0;
218 unset($datasetdef->items);
219 }
220 }
221 $maxnumber = -1 ;
222 if ( "" !=optional_param('addbutton')){
223 $maxnumber = optional_param('selectadd') ;
224 foreach ($this->datasetdefs as $defid => $datasetdef) {
225 $datasetdef->itemcount = $maxnumber;
226 unset($datasetdef->items);
227 for ($numberadded =1 ; $numberadded <= $maxnumber; $numberadded++){
228 $datasetitem = new stdClass;
229 // $datasetitem->definition = $datasetdef->id ;
230 $datasetitem->itemnumber = $numberadded;
231 $datasetitem->id = 0;
232 $datasetitem->value = $this->qtypeobj->generate_dataset_item($datasetdef->options);
233 $this->datasetdefs[$defid]->items[$numberadded]=$datasetitem ;
234 /* if (!$DB->insert_record('question_dataset_items', $datasetitem)) {
235 print_error('cannotinsert', 'question');
236 }*/
237 }//for number added
238 }// datasetsdefs end
239 $this->maxnumber = $maxnumber ;
240 // echo"<p> using create new items $this->maxnumber </p>";
241 }else {
242 // Handle reload dataset items
243 // echo"<p> using optional to build </p>";
244 if ( "" !=optional_param('definition')&& !($datasettoremove ||$newdataset ||$newdatasetvalues )){
245 $i = 1;
246 $fromformdefinition = optional_param('definition');
247 $fromformnumber = optional_param('number');
248 $fromformitemid = optional_param('itemid');
249 ksort($fromformdefinition);
250 // echo "<p> fromformdefinition <pre>";print_r($fromformdefinition);echo"</pre></p>";
251 // echo "<p> fromformnumber <pre>";print_r($fromformnumber);echo"</pre></p>";
252
253 foreach($fromformdefinition as $key => $defid) {
254 $addeditem = new stdClass();
255 $addeditem->id = $fromformitemid[$i] ;
256 $addeditem->value = $fromformnumber[$i];
257 $addeditem->itemnumber = ceil($i / count($this->datasetdefs));
258 $this->datasetdefs[$defid]->items[$addeditem->itemnumber]=$addeditem ;
259 $this->datasetdefs[$defid]->itemcount = $i ;
260 $i++;
261 }
262 }
263 if (isset($addeditem->itemnumber) && $this->maxnumber < $addeditem->itemnumber){
264 $this->maxnumber = $addeditem->itemnumber;
265 if(!empty($this->datasetdefs)){
266 foreach ($this->datasetdefs as $datasetdef) {
267 $datasetdef->itemcount = $this->maxnumber ;
268 }
269 }
270 }
271 }
272
273 // echo "<p>line 443 datasetdefs <pre>";print_r($this->datasetdefs);echo"</pre></p>";
274 //$key = 0 ;
275 // if ( "" !=optional_param('answer')) echo "<p> optional answer exist </p>";
276 // if ( "" !=optional_param('answer['.$key.']','', PARAM_NOTAGS)) echo "<p> optional $key exist </p>";
277 // if ( "" !=optional_param('noanswer','', PARAM_INT )) echo "<p> optional noanswer exist </p>";
278
279 parent::question_edit_form($submiturl, $question, $category, $contexts, $formeditable);
280 }
281
282 function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
283 $repeated = parent::get_per_answer_fields(&$mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
284 $mform->setType('answer', PARAM_NOTAGS);
285 $addrepeated = array();
286 $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
287 $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
288 $repeatedoptions['tolerance']['default'] = 0.01;
289 $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'quiz'), $this->qtypeobj->tolerance_types());
290 $addrepeated[] =& $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
291 $repeatedoptions['correctanswerlength']['default'] = 2;
292
293 $answerlengthformats = array('1' => get_string('decimalformat', 'quiz'), '2' => get_string('significantfiguresformat', 'quiz'));
294 $addrepeated[] =& $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
295 array_splice($repeated, 3, 0, $addrepeated);
296 $repeated[1]->setLabel(get_string('correctanswerformula', 'quiz').'=');
297
298 return $repeated;
299 }
300
301 /**
302 * Add question-type specific form fields.
303 *
304 * @param MoodleQuickForm $mform the form being built.
305 */
306 function definition_inner(&$mform) {
307 global $QTYPES;
308 $this->qtypeobj =& $QTYPES[$this->qtype()];
309 $strquestionlabel = $this->qtypeobj->comment_header($this->nonemptyanswer);
310 $label = get_string("sharedwildcards", "qtype_datasetdependent");
311 $mform->addElement('hidden', 'initialcategory', 1);
312 $mform->addElement('hidden', 'reload', 1);
313// $html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
314// $mform->insertElementBefore($mform->createElement('static','listcategory',$label,$html2),'name');
315 $addfieldsname='updatecategory';
316 $addstring=get_string("updatecategory", "qtype_calculated");
317 $mform->registerNoSubmitButton($addfieldsname);
318
319// $mform->insertElementBefore( $mform->createElement('submit', $addfieldsname, $addstring),'listcategory');
320
321 $creategrades = get_grade_options();
322 $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
323 $creategrades->gradeoptions, 1, 1);
324
325 $repeated = array();
326 $repeated[] =& $mform->createElement('header', 'unithdr', get_string('unithdr', 'qtype_numerical', '{no}'));
327
328 $repeated[] =& $mform->createElement('text', 'unit', get_string('unit', 'quiz'));
329 $mform->setType('unit', PARAM_NOTAGS);
330
331 $repeated[] =& $mform->createElement('text', 'multiplier', get_string('multiplier', 'quiz'));
332 $mform->setType('multiplier', PARAM_NUMBER);
333
334 if (isset($this->question->options)){
335 $countunits = count($this->question->options->units);
336 } else {
337 $countunits = 0;
338 }
339 if ($this->question->formoptions->repeatelements){
340 $repeatsatstart = $countunits + 1;
341 } else {
342 $repeatsatstart = $countunits;
343 }
344 $this->repeat_elements($repeated, $repeatsatstart, array(), 'nounits', 'addunits', 2, get_string('addmoreunitblanks', 'qtype_calculated', '{no}'));
345
346 if ($mform->elementExists('multiplier[0]')){
347 $firstunit =& $mform->getElement('multiplier[0]');
348 $firstunit->freeze();
349 $firstunit->setValue('1.0');
350 $firstunit->setPersistantFreeze(true);
351 }
352 //hidden elements
353 // $mform->addElement('hidden', 'wizard', 'datasetdefinitions');
354 // $mform->setType('wizard', PARAM_ALPHA);
355 // $mform->addElement('header', '', '');
356 $label = "<div class='mdl-align'></div><div class='mdl-align'>".get_string('wildcardrole', 'qtype_calculatedsimple')."</div>";
357 $mform->addElement('html', "<div class='mdl-align'>&nbsp;</div>");
358 $mform->addElement('html', $label);// explaining the role of datasets so other strings can be shortened
359
360 $mform->addElement('submit', 'analyzequestion', get_string('findwildcards','qtype_calculatedsimple'));
361 $mform->registerNoSubmitButton('analyzequestion');
362 $mform->closeHeaderBefore('analyzequestion');
363 if ( "" != optional_param('analyzequestion','', PARAM_RAW)) {
364
365 $this->wizarddisplay = true;
366 // echo "<p> session answer <pre>";print_r($SESSION);echo"</pre></p>";
367 // echo "<p> session answer <pre>";print_r($SESSION->calculated->questionform->answers);echo"</pre></p>";
368
369
370 }else {
371 $this->wizwarddisplay = false;
372 }
373 if ($this->maxnumber != -1){
374 $this->noofitems = $this->maxnumber;
375 } else {
376 $this->noofitems = 0;
377 }
378 if(!empty($this->datasetdefs)){
379
380 $key = 0;
381 $mform->addElement('header', 'additemhdr', get_string('wildcardparam', 'qtype_calculatedsimple'));
382 $idx = 1;
383 if(!empty($this->datasetdefs)){
384 $j = (($this->noofitems) * count($this->datasetdefs))+1;//
385 foreach ($this->datasetdefs as $defkey => $datasetdef){
386 $mform->addElement('static', "na[$j]", get_string('param', 'qtype_datasetdependent', $datasetdef->name));
387 $this->qtypeobj->custom_generator_tools_part($mform, $idx, $j);
388 $mform->addElement('hidden', "datasetdef[$idx]");
389 $mform->setType("datasetdef[$idx]", PARAM_RAW);
390 $idx++;
391 $mform->addElement('static', "divider[$j]", '', '<hr />');
392 $j++;
393 }
394 }
395 $addoptions = Array();
396 $addoptions['1']='1';
397 for ($i=10; $i<=100 ; $i+=10){
398 $addoptions["$i"]="$i";
399 }
400 $mform->closeHeaderBefore('additemhdr');
401 $addgrp = array();
402 $addgrp[] =& $mform->createElement('submit', 'addbutton', get_string('generatenewitemsset', 'qtype_calculatedsimple'));
403 $addgrp[] =& $mform->createElement('select', "selectadd", get_string('additem', 'qtype_datasetdependent'), $addoptions);
404 $addgrp[] = & $mform->createElement('static',"stat","Items",get_string('item(s)', 'qtype_datasetdependent'));
405 $mform->addGroup($addgrp, 'addgrp', '', ' ', false);
406 $mform->registerNoSubmitButton('addbutton');
407 $mform->closeHeaderBefore('addgrp');
408 $mform->addElement('static', "divideradd", '', '');
409 if ($this->noofitems == 0) {
410 $mform->addElement('static','warningnoitems','','<span class="error">'.get_string('youmustaddatleastoneitem', 'qtype_datasetdependent').'</span>');
411 $mform->closeHeaderBefore('warningnoitems');
412 }else {
413 $mform->addElement('header', 'additemhdr1', get_string('wildcarditems', 'qtype_calculatedsimple'));
414 $mform->closeHeaderBefore('additemhdr1');
415 // $mform->addElement('header', '', get_string('itemno', 'qtype_datasetdependent', ""));
416 // $mform->addElement('submit', 'updatedatasets', get_string('updatedatasetparam', 'qtype_datasetdependent'));
417 // $mform->registerNoSubmitButton('updatedatasets');
418 // $mform->setAdvanced("updatedatasets",true);
419
420//------------------------------------------------------------------------------------------------------------------------------
421 $j = $this->noofitems * count($this->datasetdefs);
422 for ($i = $this->noofitems; $i >= 1 ; $i--){
423 foreach ($this->datasetdefs as $defkey => $datasetdef){
424 $mform->addElement('text', "number[$j]", get_string('param', 'qtype_datasetdependent', $datasetdef->name));
425 $mform->setType("number[$j]", PARAM_NUMBER);
426 $mform->setAdvanced("number[$j]",true);
427 $mform->addElement('hidden', "itemid[$j]");
428 $mform->setType("itemid[$j]", PARAM_INT);
429
430 $mform->addElement('hidden', "definition[$j]");
431 $mform->setType("definition[$j]", PARAM_NOTAGS);
432
433 $j--;
434 }
435 if (!empty( $strquestionlabel)){
436 $repeated[] =& $mform->addElement('static', "answercomment[$i]", "<b>".get_string('itemno', 'qtype_datasetdependent', $i)."</b>&nbsp;&nbsp;".$strquestionlabel);
437 }
438 $mform->addElement('static', "divider1[$j]", '', '<hr />');
439
440 }
441 }
442 // if ($this->outsidelimit){
443 // $mform->addElement('static','outsidelimit','','');
444 // }
445 }else {
446 $mform->addElement('static','warningnowildcards','','<span class="error">'.get_string('atleastonewildcard', 'qtype_calculatedsimple').'</span>');
447 $mform->closeHeaderBefore('warningnowildcards');
448 }
449
450//------------------------------------------------------------------------------------------------------------------------------
451 //non standard name for button element needed so not using add_action_buttons
452 //hidden elements
453
454 $mform->addElement('hidden', 'id');
455 $mform->setType('id', PARAM_INT);
456
457 $mform->addElement('hidden', 'courseid');
458 $mform->setType('courseid', PARAM_INT);
459 $mform->setDefault('courseid', 0);
460
461 $mform->addElement('hidden', 'cmid');
462 $mform->setType('cmid', PARAM_INT);
463 $mform->setDefault('cmid', 0);
464 if (!empty($this->question->id)){
465 if ($this->question->formoptions->cansaveasnew){
466 $mform->addElement('header', 'additemhdr', get_string('converttocalculated', 'qtype_calculatedsimple'));
467 $mform->closeHeaderBefore('additemhdr');
468
469 $mform->addElement('checkbox', 'convert','' ,get_string('willconverttocalculated', 'qtype_calculatedsimple'));
470 $mform->setDefault('convert', 0);
471
472 }
473 }
474 // $mform->addElement('hidden', 'wizard', 'edit_calculatedsimple');
475 // $mform->setType('wizard', PARAM_ALPHA);
476/*
477 $mform->addElement('hidden', 'returnurl');
478 $mform->setType('returnurl', PARAM_LOCALURL);
479 $mform->setDefault('returnurl', 0);
480
481*/
482 }
483
484 function set_data($question) {
485 $answer = $this->answer;
486 $default_values = array();
487 if (count($answer)) {
488 $key = 0;
489 foreach ($answer as $answer){
490 $default_values['answer['.$key.']'] = $answer->answer;
491 $default_values['fraction['.$key.']'] = $answer->fraction;
492 $default_values['tolerance['.$key.']'] = $answer->tolerance;
493 $default_values['tolerancetype['.$key.']'] = $answer->tolerancetype;
494 $default_values['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
495 $default_values['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
496 $default_values['feedback['.$key.']'] = $answer->feedback;
497 $key++;
498 }
499 }
500 if (isset($question->options)){
501 $units = array_values($question->options->units);
502 // make sure the default unit is at index 0
503 usort($units, create_function('$a, $b',
504 'if (1.0 === (float)$a->multiplier) { return -1; } else '.
505 'if (1.0 === (float)$b->multiplier) { return 1; } else { return 0; }'));
506 if (count($units)) {
507 $key = 0;
508 foreach ($units as $unit){
509 $default_values['unit['.$key.']'] = $unit->unit;
510 $default_values['multiplier['.$key.']'] = $unit->multiplier;
511 $key++;
512 }
513 }
514 }
515 $key = 0 ;
516 // echo "<p> mandatorydatasets $key xx".optional_param("answer[0]",'', PARAM_NOTAGS)."YY".$this->_form->getElementValue('answer['.$key.']')."xx<p>";
517
518 $formdata = array();
519 $fromform = new stdClass();
520 //fill out all data sets and also the fields for the next item to add.
521 if(!empty($this->datasetdefs)){
522 $j = $this->noofitems * count($this->datasetdefs);
523 for ($itemnumber = $this->noofitems; $itemnumber >= 1; $itemnumber--){
524 $data = array();
525 foreach ($this->datasetdefs as $defid => $datasetdef){
526 if (isset($datasetdef->items[$itemnumber])){
527 $formdata["number[$j]"] = $datasetdef->items[$itemnumber]->value;
528 $formdata["definition[$j]"] = $defid;
529 $formdata["itemid[$j]"] = $datasetdef->items[$itemnumber]->id;
530 $data[$datasetdef->name] = $datasetdef->items[$itemnumber]->value;
531 }
532 $j--;
533 }
534 // echo "<p>answers avant comment <pre>";print_r($answer);echo"</pre></p>";
535 // echo "<p>data avant comment <pre>";print_r($data);echo"</pre></p>";
536
537 if($this->noofitems != 0 ) {
538 if(!isset($question->id)) $question->id = 0 ;
539 $comment = $this->qtypeobj->comment_on_datasetitems($question->id,$this->nonemptyanswer, $data, $itemnumber);//$this->
540 if ($comment->outsidelimit) {
541 $this->outsidelimit=$comment->outsidelimit ;
542 }
543 $totalcomment='';
544 // echo "<p> comment <pre>";print_r($comment);echo"</pre></p>";
545
546 foreach ($this->nonemptyanswer as $key => $answer) {
547 $totalcomment .= $comment->stranswers[$key].'<br/>';
548 }
549
550 $formdata['answercomment['.$itemnumber.']'] = $totalcomment ;
551 }
552 }
553 // $formdata['reload'] = '1';
554 // $formdata['nextpageparam[forceregeneration]'] = $this->regenerate;
555 $formdata['selectdelete'] = '1';
556 $formdata['selectadd'] = '1';
557 $j = $this->noofitems * count($this->datasetdefs)+1;
558 $data = array(); // data for comment_on_datasetitems later
559 $idx =1 ;
560 foreach ($this->datasetdefs as $defid => $datasetdef){
561 $formdata["datasetdef[$idx]"] = $defid;
562 $idx++;
563 }
564 $formdata = $this->qtypeobj->custom_generator_set_data($this->datasetdefs, $formdata);
565 }
566 $question = (object)((array)$question + $default_values+$formdata );
567 // echo "<p> question data <pre>";print_r($question);echo"</pre></p>";
568
569 parent::set_data($question);
570 }
571
572 function qtype() {
573 return 'calculatedsimple';
574 }
575
576 function validation($data, $files) {
577 $errors = parent::validation($data, $files);
578 //verifying for errors in {=...} in question text;
579 $qtext = "";
580 $qtextremaining = $data['questiontext'] ;
581 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
582 foreach ($possibledatasets as $name => $value) {
583 $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
584 }
585 // echo "numericalquestion qtextremaining <pre>";print_r($possibledatasets);
586 while (ereg('\{=([^[:space:]}]*)}', $qtextremaining, $regs1)) {
587 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
588 $qtext =$qtext.$qtextsplits[0];
589 $qtextremaining = $qtextsplits[1];
590 if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
591 if(!isset($errors['questiontext'])){
592 $errors['questiontext'] = $formulaerrors.':'.$regs1[1] ;
593 }else {
594 $errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
595 }
596 }
597 }
598 $answers = $data['answer'];
599 $answercount = 0;
600 $maxgrade = false;
601 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
602 $mandatorydatasets = array();
603 foreach ($answers as $key => $answer){
604 $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
605 }
606 if ( count($mandatorydatasets )==0){
607 // $errors['questiontext']=get_string('atleastonewildcard', 'qtype_datasetdependent');
608 foreach ($answers as $key => $answer){
609 $errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_datasetdependent');
610 }
611 }
612 foreach ($answers as $key => $answer){
613 //check no of choices
614 // the * for everykind of answer not actually implemented
615 $trimmedanswer = trim($answer);
616 if (($trimmedanswer!='')||$answercount==0){
617 $eqerror = qtype_calculated_find_formula_errors($trimmedanswer);
618 if (FALSE !== $eqerror){
619 $errors['answer['.$key.']'] = $eqerror;
620 }
621 }
622 if ($trimmedanswer!=''){
623 if ('2' == $data['correctanswerformat'][$key]
624 && '0' == $data['correctanswerlength'][$key]) {
625 $errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed','quiz');
626 }
627 if (!is_numeric($data['tolerance'][$key])){
628 $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
629 }
630 if ($data['fraction'][$key] == 1) {
631 $maxgrade = true;
632 }
633
634 $answercount++;
635 }
636 //check grades
637
638 //TODO how should grade checking work here??
639 /*if ($answer != '') {
640 if ($data['fraction'][$key] > 0) {
641 $totalfraction += $data['fraction'][$key];
642 }
643 if ($data['fraction'][$key] > $maxfraction) {
644 $maxfraction = $data['fraction'][$key];
645 }
646 }*/
647 }
648 //grade checking :
649 /// Perform sanity checks on fractional grades
650 /*if ( ) {
651 if ($maxfraction != 1) {
652 $maxfraction = $maxfraction * 100;
653 $errors['fraction[0]'] = get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
654 }
655 } else {
656 $totalfraction = round($totalfraction,2);
657 if ($totalfraction != 1) {
658 $totalfraction = $totalfraction * 100;
659 $errors['fraction[0]'] = get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
660 }
661 }*/
662 $units = $data['unit'];
663 if (count($units)) {
664 foreach ($units as $key => $unit){
665 if (is_numeric($unit)){
666 $errors['unit['.$key.']'] = get_string('mustnotbenumeric', 'qtype_calculated');
667 }
668 $trimmedunit = trim($unit);
669 $trimmedmultiplier = trim($data['multiplier'][$key]);
670 if (!empty($trimmedunit)){
671 if (empty($trimmedmultiplier)){
672 $errors['multiplier['.$key.']'] = get_string('youmustenteramultiplierhere', 'qtype_calculated');
673 }
674 if (!is_numeric($trimmedmultiplier)){
675 $errors['multiplier['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
676 }
677
678 }
679 }
680 }
681 if ($answercount==0){
682 $errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
683 }
684 if ($maxgrade == false) {
685 $errors['fraction[0]'] = get_string('fractionsnomax', 'question');
686 }
687 if (isset($data['backtoquiz']) && ($this->noofitems==0) ){
688 $errors['warning'] = get_string('warning', 'mnet');
689 }
690 if ($this->outsidelimit){
691 // if(!isset($errors['warning'])) $errors['warning']=' ';
692 $errors['outsidelimits'] = get_string('oneanswertrueansweroutsidelimits','qtype_calculated');
693 }
694 $numbers = $data['number'];
695 foreach ($numbers as $key => $number){
696 if(! is_numeric($number)){
697 if (stristr($number,',')){
698 $errors['number['.$key.']'] = get_string('The , cannot be used, use . as in 0.013 or 1.3e-2', 'qtype_datasetdependent');
699 }else {
700 $errors['number['.$key.']'] = get_string('This is not a valid number', 'qtype_datasetdependent');
701 }
702 }else if( stristr($number,'x')){
703 $errors['number['.$key.']'] = get_string('Hexadecimal format (i.e. 0X12d) is not allowed', 'qtype_datasetdependent');
704 } else if( is_nan($number)){
705 $errors['number['.$key.']'] = get_string('is a NAN number', 'qtype_datasetdependent');
706 }
707 }
708 if ( $this->noofitems==0 ){
709 $errors['warning'] = get_string('warning', 'mnet');
710 }
711
712 return $errors;
713 }
714}
715?>