MDL-19057 No more exceptions in tests for oracle. If tests fail, MDL-20339 can be...
[moodle.git] / question / type / calculated / edit_calculated_form.php
CommitLineData
4d41f4ee 1<?php // $Id$
271ffe3f 2/**
3 * Defines the editing form for the calculated question 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
9e20fbc2 8 * @package questionbank
9 * @subpackage questiontypes
271ffe3f 10 */
11
12/**
13 * calculated editing form definition.
14 */
15class question_edit_calculated_form extends question_edit_form {
9aa022fe 16 /**
17 * Handle to the question type for this question.
18 *
19 * @var question_calculated_qtype
20 */
21 var $qtypeobj;
2aef1fe5 22
23 function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
aeab3f8d 24 $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
2aef1fe5 25 $mform->setType('answer', PARAM_NOTAGS);
26
27 $addrepeated = array();
28 $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
29 $repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
30 $repeatedoptions['tolerance']['default'] = 0.01;
31 $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'quiz'), $this->qtypeobj->tolerance_types());
32
33 $addrepeated[] =& $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
34 $repeatedoptions['correctanswerlength']['default'] = 2;
35
36 $answerlengthformats = array('1' => get_string('decimalformat', 'quiz'), '2' => get_string('significantfiguresformat', 'quiz'));
37 $addrepeated[] =& $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
38 array_splice($repeated, 3, 0, $addrepeated);
39 $repeated[1]->setLabel(get_string('correctanswerformula', 'quiz').'=');
40
41 return $repeated;
42 }
43
271ffe3f 44 /**
45 * Add question-type specific form fields.
46 *
9aa022fe 47 * @param MoodleQuickForm $mform the form being built.
271ffe3f 48 */
49 function definition_inner(&$mform) {
9aa022fe 50 global $QTYPES;
92186abc 51 $this->qtypeobj =& $QTYPES[$this->qtype()];
a6d46515 52 $label = get_string("sharedwildcards", "qtype_datasetdependent");
53 $mform->addElement('hidden', 'initialcategory', 1);
54 $html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
55 $mform->insertElementBefore($mform->createElement('static','listcategory',$label,$html2),'name');
56 $addfieldsname='updatecategory';
57 $addstring=get_string("updatecategory", "qtype_calculated");
58 $mform->registerNoSubmitButton($addfieldsname);
271e6dec 59
a6d46515 60 $mform->insertElementBefore( $mform->createElement('submit', $addfieldsname, $addstring),'listcategory');
271ffe3f 61
271ffe3f 62 $creategrades = get_grade_options();
2aef1fe5 63 $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
64 $creategrades->gradeoptions, 1, 1);
92186abc 65
271e6dec 66 $repeated = array();
9aa022fe 67 $repeated[] =& $mform->createElement('header', 'unithdr', get_string('unithdr', 'qtype_numerical', '{no}'));
271ffe3f 68
9aa022fe 69 $repeated[] =& $mform->createElement('text', 'unit', get_string('unit', 'quiz'));
3a298174 70 $mform->setType('unit', PARAM_NOTAGS);
271ffe3f 71
9aa022fe 72 $repeated[] =& $mform->createElement('text', 'multiplier', get_string('multiplier', 'quiz'));
3a298174 73 $mform->setType('multiplier', PARAM_NUMBER);
9aa022fe 74
75 if (isset($this->question->options)){
76 $countunits = count($this->question->options->units);
77 } else {
78 $countunits = 0;
79 }
271e6dec 80 if ($this->question->formoptions->repeatelements){
81 $repeatsatstart = $countunits + 1;
82 } else {
83 $repeatsatstart = $countunits;
84 }
3a298174 85 $this->repeat_elements($repeated, $repeatsatstart, array(), 'nounits', 'addunits', 2, get_string('addmoreunitblanks', 'qtype_calculated', '{no}'));
271ffe3f 86
79bb7202 87 if ($mform->elementExists('multiplier[0]')){
88 $firstunit =& $mform->getElement('multiplier[0]');
89 $firstunit->freeze();
90 $firstunit->setValue('1.0');
91 $firstunit->setPersistantFreeze(true);
92 }
9aa022fe 93 //hidden elements
e593233a 94 $mform->addElement('hidden', 'synchronize', '');
95 if (isset($this->question->options)&& isset($this->question->options->synchronize) ){
96 $mform->setDefault("synchronize", $this->question->options->synchronize);
97 } else {
98 $mform->setDefault("synchronize", 0 );
99 }
60b5ecd3 100 $mform->addElement('hidden', 'wizard', 'datasetdefinitions');
101 $mform->setType('wizard', PARAM_ALPHA);
92186abc 102
271ffe3f 103
104 }
105
32db0d42 106 function set_data($question) {
271ffe3f 107 if (isset($question->options)){
108 $answers = $question->options->answers;
109 if (count($answers)) {
110 $key = 0;
111 foreach ($answers as $answer){
9af77e9d 112 $default_values['answer['.$key.']'] = $answer->answer;
92186abc 113 $default_values['fraction['.$key.']'] = $answer->fraction;
114 $default_values['tolerance['.$key.']'] = $answer->tolerance;
f7089b63 115 $default_values['tolerancetype['.$key.']'] = $answer->tolerancetype;
92186abc 116 $default_values['correctanswerlength['.$key.']'] = $answer->correctanswerlength;
9aa022fe 117 $default_values['correctanswerformat['.$key.']'] = $answer->correctanswerformat;
271ffe3f 118 $default_values['feedback['.$key.']'] = $answer->feedback;
119 $key++;
120 }
121 }
9aa022fe 122 $units = array_values($question->options->units);
123 // make sure the default unit is at index 0
271e6dec 124 usort($units, create_function('$a, $b',
9aa022fe 125 'if (1.0 === (float)$a->multiplier) { return -1; } else '.
126 'if (1.0 === (float)$b->multiplier) { return 1; } else { return 0; }'));
127 if (count($units)) {
128 $key = 0;
129 foreach ($units as $unit){
130 $default_values['unit['.$key.']'] = $unit->unit;
131 $default_values['multiplier['.$key.']'] = $unit->multiplier;
132 $key++;
133 }
134 }
92186abc 135 }
8fc3e643 136 $default_values['submitbutton'] = get_string('nextpage', 'qtype_calculated');
137 $default_values['makecopy'] = get_string('makecopynextpage', 'qtype_calculated');
271e6dec 138 /* set the wild cards category display given that on loading the category element is
139 unselected when processing this function but have a valid value when processing the
0dd3e11c 140 update category button. The value can be obtain by
141 $qu->category =$this->_form->_elements[$this->_form->_elementIndex['category']]->_values[0];
142 but is coded using existing functions
271e6dec 143 */
0dd3e11c 144 $qu = new stdClass;
145 $el = new stdClass;
271e6dec 146 /* no need to call elementExists() here */
79bb7202 147 if ($this->_form->elementExists('category')){
148 $el=$this->_form->getElement('category');
149 } else {
150 $el=$this->_form->getElement('categorymoveto');
151 }
0dd3e11c 152 if($value =$el->getSelected()) {
153 $qu->category =$value[0];
154 }else {
155 $qu->category=$question->category;// on load $question->category is set by question.php
271e6dec 156 }
0dd3e11c 157 $html2 = $this->qtypeobj->print_dataset_definitions_category($qu);
79bb7202 158 $this->_form->_elements[$this->_form->_elementIndex['listcategory']]->_text = $html2 ;
159 $question = (object)((array)$question + $default_values);
92186abc 160
32db0d42 161 parent::set_data($question);
271ffe3f 162 }
163
164 function qtype() {
165 return 'calculated';
166 }
167
a78890d5 168 function validation($data, $files) {
fe93ba83 169 $errors = parent::validation($data, $files);
bfdc0bce 170 //verifying for errors in {=...} in question text;
171 $qtext = "";
172 $qtextremaining = $data['questiontext'] ;
173 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
174 foreach ($possibledatasets as $name => $value) {
175 $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
176 }
271e6dec 177 // echo "numericalquestion qtextremaining <pre>";print_r($possibledatasets);
6dbcacee 178 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
bfdc0bce 179 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
180 $qtext =$qtext.$qtextsplits[0];
181 $qtextremaining = $qtextsplits[1];
182 if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
183 if(!isset($errors['questiontext'])){
184 $errors['questiontext'] = $formulaerrors.':'.$regs1[1] ;
185 }else {
186 $errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
271e6dec 187 }
bfdc0bce 188 }
271e6dec 189 }
9af77e9d 190 $answers = $data['answer'];
271ffe3f 191 $answercount = 0;
a6d46515 192 $maxgrade = false;
f6232d58 193 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']);
194 $mandatorydatasets = array();
195 foreach ($answers as $key => $answer){
a6d46515 196 $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
271e6dec 197 }
a6d46515 198 if ( count($mandatorydatasets )==0){
199 // $errors['questiontext']=get_string('atleastonewildcard', 'qtype_datasetdependent');
f6232d58 200 foreach ($answers as $key => $answer){
9af77e9d 201 $errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_datasetdependent');
271e6dec 202 }
203 }
9aa022fe 204 foreach ($answers as $key => $answer){
205 //check no of choices
a6d46515 206 // the * for everykind of answer not actually implemented
271ffe3f 207 $trimmedanswer = trim($answer);
845b703b 208 if (($trimmedanswer!='')||$answercount==0){
9aa022fe 209 $eqerror = qtype_calculated_find_formula_errors($trimmedanswer);
210 if (FALSE !== $eqerror){
9af77e9d 211 $errors['answer['.$key.']'] = $eqerror;
9aa022fe 212 }
8fc3e643 213 }
845b703b 214 if ($trimmedanswer!=''){
9aa022fe 215 if ('2' == $data['correctanswerformat'][$key]
216 && '0' == $data['correctanswerlength'][$key]) {
217 $errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed','quiz');
218 }
219 if (!is_numeric($data['tolerance'][$key])){
220 $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
221 }
a6d46515 222 if ($data['fraction'][$key] == 1) {
223 $maxgrade = true;
224 }
9aa022fe 225
271ffe3f 226 $answercount++;
227 }
9aa022fe 228 //check grades
229
230 //TODO how should grade checking work here??
231 /*if ($answer != '') {
232 if ($data['fraction'][$key] > 0) {
233 $totalfraction += $data['fraction'][$key];
234 }
235 if ($data['fraction'][$key] > $maxfraction) {
236 $maxfraction = $data['fraction'][$key];
237 }
238 }*/
239 }
240 //grade checking :
241 /// Perform sanity checks on fractional grades
242 /*if ( ) {
243 if ($maxfraction != 1) {
244 $maxfraction = $maxfraction * 100;
245 $errors['fraction[0]'] = get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction);
246 }
247 } else {
248 $totalfraction = round($totalfraction,2);
249 if ($totalfraction != 1) {
250 $totalfraction = $totalfraction * 100;
251 $errors['fraction[0]'] = get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction);
252 }
253 }*/
254 $units = $data['unit'];
255 if (count($units)) {
256 foreach ($units as $key => $unit){
257 if (is_numeric($unit)){
258 $errors['unit['.$key.']'] = get_string('mustnotbenumeric', 'qtype_calculated');
259 }
260 $trimmedunit = trim($unit);
261 $trimmedmultiplier = trim($data['multiplier'][$key]);
262 if (!empty($trimmedunit)){
263 if (empty($trimmedmultiplier)){
264 $errors['multiplier['.$key.']'] = get_string('youmustenteramultiplierhere', 'qtype_calculated');
265 }
266 if (!is_numeric($trimmedmultiplier)){
267 $errors['multiplier['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
268 }
269
270 }
271 }
271ffe3f 272 }
273 if ($answercount==0){
9af77e9d 274 $errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
271ffe3f 275 }
a6d46515 276 if ($maxgrade == false) {
277 $errors['fraction[0]'] = get_string('fractionsnomax', 'question');
278 }
9aa022fe 279
271ffe3f 280 return $errors;
281 }
282}
6dbcacee 283?>