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