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