MDL-20636 Fix @package names and PHPdoc layout.
[moodle.git] / question / type / calculatedmulti / questiontype.php
CommitLineData
2d279432
PP
1<?php
2
fe6ce234
DC
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
d3603157
TH
18/**
19 * Question type class for the calculated multiple-choice question type.
20 *
21 * @package qtype
22 * @subpackage calculatedmulti
23 * @copyright 2009 Pierre Pichet
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
27
28/**
29 * The calculated multiple-choice question type.
30 *
31 * @copyright 2009 Pierre Pichet
32 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
33 */
2d279432
PP
34class question_calculatedmulti_qtype extends question_calculated_qtype {
35
f5382dd2 36
2d279432 37 // Used by the function custom_generator_tools:
fe6ce234 38 public $calcgenerateidhasbeenadded = false;
2d279432
PP
39 public $virtualqtype = false;
40
41 function name() {
42 return 'calculatedmulti';
43 }
44
45 function has_wildcards_in_responses($question, $subqid) {
46 return true;
47 }
48
49 function requires_qtypes() {
50 return array('multichoice');
51 }
2d279432 52
2d279432
PP
53
54 function save_question_options($question) {
2d279432 55 global $CFG, $DB, $QTYPES ;
fe6ce234 56 $context = $question->context;
2d279432
PP
57 if (isset($question->answer) && !isset($question->answers)) {
58 $question->answers = $question->answer;
59 }
60 // calculated options
fe6ce234 61 $update = true ;
2d279432
PP
62 $options = $DB->get_record("question_calculated_options", array("question" => $question->id));
63 if (!$options) {
64 $update = false;
0ff4bd08 65 $options = new stdClass();
2d279432
PP
66 $options->question = $question->id;
67 }
68 $options->synchronize = $question->synchronize;
2d279432
PP
69 $options->single = $question->single;
70 $options->answernumbering = $question->answernumbering;
71 $options->shuffleanswers = $question->shuffleanswers;
fe6ce234
DC
72
73 // save question feedback files
74 foreach (array('correct', 'partiallycorrect', 'incorrect') as $feedbacktype) {
75 $feedbackname = $feedbacktype . 'feedback';
76 $feedbackformat = $feedbackname . 'format';
77 $feedback = $question->$feedbackname;
78 $options->$feedbackformat = $feedback['format'];
cde2709a
DC
79 if (isset($feedback['files'])) {
80 $options->$feedbackname = trim($feedback['text']);
81 $files = $feedback['files'];
82 foreach ($files as $file) {
83 $this->import_file($question->context, 'qtype_calculatedmulti', $feedbackname, $question->id, $file);
84 }
85 } else {
f5382dd2 86 $options->$feedbackname = file_save_draft_area_files($feedback['itemid'], $context->id, 'qtype_calculatedmulti', $feedbackname, $question->id, $this->fileoptionsa , trim($feedback['text']));
cde2709a 87 }
fe6ce234
DC
88 }
89
2d279432 90 if ($update) {
fe6ce234 91 $DB->update_record("question_calculated_options", $options);
2d279432 92 } else {
fe6ce234 93 $DB->insert_record("question_calculated_options", $options);
2d279432
PP
94 }
95
96 // Get old versions of the objects
97 if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) {
98 $oldanswers = array();
99 }
100
101 if (!$oldoptions = $DB->get_records('question_calculated', array('question' => $question->id), 'answer ASC')) {
102 $oldoptions = array();
103 }
104
105 // Save the units.
fe6ce234
DC
106 $virtualqtype = $this->get_virtual_qtype($question);
107 // TODO: What is this?
108 // $result = $virtualqtype->save_numerical_units($question);
2d279432
PP
109 if (isset($result->error)) {
110 return $result;
111 } else {
112 $units = &$result->units;
113 }
114 // Insert all the new answers
115 if (isset($question->answer) && !isset($question->answers)) {
fe6ce234 116 $question->answers = $question->answer;
2d279432
PP
117 }
118 foreach ($question->answers as $key => $dataanswer) {
cde2709a
DC
119 if (is_array($dataanswer)) {
120 $dataanswer = $dataanswer['text'];
121 }
fe6ce234 122 if ( trim($dataanswer) != '' ) {
0ff4bd08 123 $answer = new stdClass();
2d279432
PP
124 $answer->question = $question->id;
125 $answer->answer = trim($dataanswer);
126 $answer->fraction = $question->fraction[$key];
fe6ce234
DC
127 $answer->feedback = trim($question->feedback[$key]['text']);
128 $answer->feedbackformat = $question->feedback[$key]['format'];
cde2709a
DC
129 if (isset($question->feedback[$key]['files'])) {
130 $files = $question->feedback[$key]['files'];
131 }
2d279432
PP
132
133 if ($oldanswer = array_shift($oldanswers)) { // Existing answer, so reuse it
134 $answer->id = $oldanswer->id;
f5382dd2 135 $answer->feedback = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, $this->fileoptionsa, $answer->feedback);
2d279432
PP
136 $DB->update_record("question_answers", $answer);
137 } else { // This is a completely new answer
138 $answer->id = $DB->insert_record("question_answers", $answer);
cde2709a
DC
139 if (isset($files)) {
140 $feedbacktext = $answer->feedback;
141 foreach ($files as $file) {
142 $this->import_file($context, 'question', 'answerfeedback', $answer->id, $file);
143 }
144 } else {
f5382dd2 145 $feedbacktext = file_save_draft_area_files($question->feedback[$key]['itemid'], $context->id, 'question', 'answerfeedback', $answer->id, $this->fileoptionsa, $answer->feedback);
cde2709a 146 }
fe6ce234 147 $DB->set_field('question_answers', 'feedback', $feedbacktext, array('id'=>$answer->id));
2d279432
PP
148 }
149
150 // Set up the options object
151 if (!$options = array_shift($oldoptions)) {
0ff4bd08 152 $options = new stdClass();
2d279432
PP
153 }
154 $options->question = $question->id;
155 $options->answer = $answer->id;
156 $options->tolerance = trim($question->tolerance[$key]);
157 $options->tolerancetype = trim($question->tolerancetype[$key]);
158 $options->correctanswerlength = trim($question->correctanswerlength[$key]);
159 $options->correctanswerformat = trim($question->correctanswerformat[$key]);
160
161 // Save options
162 if (isset($options->id)) { // reusing existing record
163 $DB->update_record('question_calculated', $options);
164 } else { // new options
165 $DB->insert_record('question_calculated', $options);
166 }
167 }
168 }
169 // delete old answer records
170 if (!empty($oldanswers)) {
171 foreach($oldanswers as $oa) {
172 $DB->delete_records('question_answers', array('id' => $oa->id));
173 }
174 }
175
176 // delete old answer records
177 if (!empty($oldoptions)) {
178 foreach($oldoptions as $oo) {
179 $DB->delete_records('question_calculated', array('id' => $oo->id));
180 }
181 }
2d279432
PP
182
183
184 if( isset($question->import_process)&&$question->import_process){
185 $this->import_datasets($question);
fe6ce234 186 }
2d279432
PP
187 // Report any problems.
188 if (!empty($result->notice)) {
189 return $result;
190 }
191 return true;
192 }
193
194 function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {
195 // Find out how many datasets are available
d90b016b 196 global $CFG, $DB, $QTYPES, $OUTPUT ;
fe6ce234
DC
197 $maxnumber = (int)$DB->get_field_sql(
198 "SELECT MIN(a.itemcount)
199 FROM {question_dataset_definitions} a, {question_datasets} b
200 WHERE b.question = ? AND a.id = b.datasetdefinition", array($question->id));
201 if (!$maxnumber) {
2d279432
PP
202 print_error('cannotgetdsforquestion', 'question', '', $question->id);
203 }
fe6ce234
DC
204 $sql = "SELECT i.*
205 FROM {question_datasets} d, {question_dataset_definitions} i
206 WHERE d.question = ? AND d.datasetdefinition = i.id AND i.category != 0";
2d279432 207 if (!$question->options->synchronize || !$records = $DB->get_records_sql($sql, array($question->id))) {
fe6ce234
DC
208 $synchronize_calculated = false ;
209 } else {
210 // i.e records is true so test coherence
211 $coherence = true ;
0ff4bd08 212 $a = new stdClass() ;
fe6ce234
DC
213 $a->qid = $question->id ;
214 $a->qcat = $question->category ;
215 foreach($records as $def ){
d90b016b
PP
216 if ($def->category != $question->category){
217 $a->name = $def->name;
218 $a->sharedcat = $def->category ;
219 $coherence = false ;
220 break;
221 }
222 }
223 if(!$coherence){
fe6ce234
DC
224 echo $OUTPUT->notification(get_string('nocoherencequestionsdatyasetcategory','qtype_calculated',$a));
225 }
226
227 $synchronize_calculated = true ;
228 }
2d279432
PP
229
230 // Choose a random dataset
d90b016b
PP
231 // maxnumber sould not be breater than 100
232 if ($maxnumber > CALCULATEDQUESTIONMAXITEMNUMBER ){
233 $maxnumber = CALCULATEDQUESTIONMAXITEMNUMBER ;
234 }
2d279432
PP
235 if ( $synchronize_calculated === false ) {
236 $state->options->datasetitem = rand(1, $maxnumber);
237 }else{
fe6ce234 238 $state->options->datasetitem = intval( $maxnumber * substr($attempt->timestart,-2) /100 ) ;
2d279432
PP
239 if ($state->options->datasetitem < 1) {
240 $state->options->datasetitem =1 ;
241 } else if ($state->options->datasetitem > $maxnumber){
242 $state->options->datasetitem = $maxnumber ;
243 }
fe6ce234
DC
244
245 };
2d279432 246 $state->options->dataset =
fe6ce234
DC
247 $this->pick_question_dataset($question,$state->options->datasetitem);
248 // create an array of answerids ??? why so complicated ???
249 $answerids = array_values(array_map(create_function('$val',
250 'return $val->id;'), $question->options->answers));
251 // Shuffle the answers if required
252 if (!empty($cmoptions->shuffleanswers) and !empty($question->options->shuffleanswers)) {
253 $answerids = swapshuffle($answerids);
254 }
255 $state->options->order = $answerids;
256 // Create empty responses
257 if ($question->options->single) {
258 $state->responses = array('' => '');
259 } else {
260 $state->responses = array();
261 }
262 return true;
2d279432 263 }
fe6ce234 264
2d279432
PP
265 function save_session_and_responses(&$question, &$state) {
266 global $DB;
fe6ce234 267 $responses = 'dataset'.$state->options->datasetitem.'-' ;
2d279432
PP
268 $responses .= implode(',', $state->options->order) . ':';
269 $responses .= implode(',', $state->responses);
fe6ce234
DC
270
271 // Set the legacy answer field
f685e830 272 $DB->set_field('question_states', 'answer', $responses, array('id'=> $state->id));
2d279432
PP
273 return true;
274 }
275
276 function create_runtime_question($question, $form) {
78a6d0ba 277 $question = default_questiontype::create_runtime_question($question, $form);
2d279432
PP
278 $question->options->answers = array();
279 foreach ($form->answers as $key => $answer) {
280 $a->answer = trim($form->answer[$key]);
281 $a->fraction = $form->fraction[$key];//new
fe6ce234 282 $a->tolerance = $form->tolerance[$key];
2d279432
PP
283 $a->tolerancetype = $form->tolerancetype[$key];
284 $a->correctanswerlength = $form->correctanswerlength[$key];
285 $a->correctanswerformat = $form->correctanswerformat[$key];
286 $question->options->answers[] = clone($a);
287 }
288
289 return $question;
290 }
291
2d279432 292 function convert_answers (&$question, &$state){
fe6ce234
DC
293 foreach ($question->options->answers as $key => $answer) {
294 $answer->answer = $this->substitute_variables($answer->answer, $state->options->dataset);
295 //evaluate the equations i.e {=5+4)
296 $qtext = "";
297 $qtextremaining = $answer->answer ;
298 // while (preg_match('~\{(=)|%[[:digit]]\.=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
299 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
300
301 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
302 $qtext = $qtext.$qtextsplits[0];
303 $qtextremaining = $qtextsplits[1];
304 if (empty($regs1[1])) {
305 $str = '';
306 } else {
307 if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
308 $str=$formulaerrors ;
309 }else {
310 eval('$str = '.$regs1[1].';');
311 $texteval= qtype_calculated_calculate_answer(
312 $str, $state->options->dataset, $answer->tolerance,
313 $answer->tolerancetype, $answer->correctanswerlength,
314 $answer->correctanswerformat, '');
2d279432 315 $str = $texteval->answer;
fe6ce234 316 }
2d279432 317 }
fe6ce234 318 $qtext = $qtext.$str ;
2d279432 319 }
fe6ce234 320 $answer->answer = $qtext.$qtextremaining ; ;
2d279432 321 }
fe6ce234 322 }
2d279432 323
fe6ce234
DC
324 function get_default_numerical_unit($question, $virtualqtype){
325 $unit = '';
326 return $unit ;
327 }
2d279432
PP
328 function grade_responses(&$question, &$state, $cmoptions) {
329 // Forward the grading to the virtual qtype
330 // We modify the question to look like a multichoice question
fe6ce234 331 // for grading nothing to do
2d279432
PP
332/* $numericalquestion = fullclone($question);
333 foreach ($numericalquestion->options->answers as $key => $answer) {
334 $answer = $numericalquestion->options->answers[$key]->answer; // for PHP 4.x
335 $numericalquestion->options->answers[$key]->answer = $this->substitute_variables_and_eval($answer,
336 $state->options->dataset);
fe6ce234
DC
337}*/
338 $virtualqtype = $this->get_virtual_qtype( $question);
2d279432
PP
339 return $virtualqtype->grade_responses($question, $state, $cmoptions) ;
340 }
341
2d279432 342
2d279432
PP
343
344 // ULPGC ecastro
345 function get_actual_response(&$question, &$state) {
346 // Substitute variables in questiontext before giving the data to the
347 // virtual type
348 $virtualqtype = $this->get_virtual_qtype( $question);
349 $unit = '' ;//$virtualqtype->get_default_numerical_unit($question);
350
351 // We modify the question to look like a multichoice question
352 $numericalquestion = clone($question);
353 $this->convert_answers ($numericalquestion, $state);
354 $this->convert_questiontext ($numericalquestion, $state);
355 /* $numericalquestion->questiontext = $this->substitute_variables_and_eval(
fe6ce234 356 $numericalquestion->questiontext, $state->options->dataset);*/
2d279432
PP
357 $responses = $virtualqtype->get_all_responses($numericalquestion, $state);
358 $response = reset($responses->responses);
359 $correct = $response->answer.' : ';
360
361 $responses = $virtualqtype->get_actual_response($numericalquestion, $state);
362
363 foreach ($responses as $key=>$response){
364 $responses[$key] = $correct.$response;
365 }
366
367 return $responses;
368 }
369
370 function create_virtual_qtype() {
371 global $CFG;
fe6ce234
DC
372 require_once("$CFG->dirroot/question/type/multichoice/questiontype.php");
373 return new question_multichoice_qtype();
2d279432
PP
374 }
375
376
377 function comment_header($question) {
378 //$this->get_question_options($question);
379 $strheader = '';
380 $delimiter = '';
381
382 $answers = $question->options->answers;
383
384 foreach ($answers as $key => $answer) {
385 if (is_string($answer)) {
386 $strheader .= $delimiter.$answer;
387 } else {
388 $strheader .= $delimiter.$answer->answer;
389 }
fe6ce234 390 $delimiter = '<br/>';
2d279432
PP
391 }
392 return $strheader;
393 }
394
395 function comment_on_datasetitems($qtypeobj,$questionid,$questiontext, $answers,$data, $number) { //multichoice_
396 global $DB;
0ff4bd08 397 $comment = new stdClass();
2d279432
PP
398 $comment->stranswers = array();
399 $comment->outsidelimit = false ;
400 $comment->answers = array();
401 /// Find a default unit:
402 /* if (!empty($questionid) && $unit = $DB->get_record('question_numerical_units', array('question'=> $questionid, 'multiplier' => 1.0))) {
403 $unit = $unit->unit;
404 } else {
405 $unit = '';
fe6ce234 406 }*/
2d279432
PP
407
408 $answers = fullclone($answers);
409 $strmin = get_string('min', 'quiz');
410 $strmax = get_string('max', 'quiz');
411 $errors = '';
412 $delimiter = ': ';
413 foreach ($answers as $key => $answer) {
fe6ce234
DC
414 $answer->answer = $this->substitute_variables($answer->answer, $data);
415 //evaluate the equations i.e {=5+4)
416 $qtext = "";
417 $qtextremaining = $answer->answer ;
418 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
419 $qtextsplits = explode($regs1[0], $qtextremaining, 2);
420 $qtext =$qtext.$qtextsplits[0];
421 $qtextremaining = $qtextsplits[1];
422 if (empty($regs1[1])) {
423 $str = '';
424 } else {
425 if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
426 $str=$formulaerrors ;
427 }else {
428 eval('$str = '.$regs1[1].';');
429 }
2d279432 430 }
fe6ce234
DC
431 $qtext = $qtext.$str ;
432 }
433 $answer->answer = $qtext.$qtextremaining;
434 $comment->stranswers[$key] = $answer->answer;
435
436
2d279432
PP
437 /* $formula = $this->substitute_variables($answer->answer,$data);
438 $formattedanswer = qtype_calculated_calculate_answer(
439 $answer->answer, $data, $answer->tolerance,
440 $answer->tolerancetype, $answer->correctanswerlength,
441 $answer->correctanswerformat, $unit);
442 if ( $formula === '*'){
443 $answer->min = ' ';
444 $formattedanswer->answer = $answer->answer ;
445 }else {
446 eval('$answer->answer = '.$formula.';') ;
447 $virtualqtype->get_tolerance_interval($answer);
fe6ce234 448 }
2d279432
PP
449 if ($answer->min === '') {
450 // This should mean that something is wrong
451 $comment->stranswers[$key] = " $formattedanswer->answer".'<br/><br/>';
452 } else if ($formula === '*'){
453 $comment->stranswers[$key] = $formula.' = '.get_string('anyvalue','qtype_calculated').'<br/><br/><br/>';
454 }else{
455 $comment->stranswers[$key]= $formula.' = '.$formattedanswer->answer.'<br/>' ;
456 $comment->stranswers[$key] .= $strmin. $delimiter.$answer->min.'---';
457 $comment->stranswers[$key] .= $strmax.$delimiter.$answer->max;
458 $comment->stranswers[$key] .='<br/>';
459 $correcttrue->correct = $formattedanswer->answer ;
460 $correcttrue->true = $answer->answer ;
461 if ($formattedanswer->answer < $answer->min || $formattedanswer->answer > $answer->max){
462 $comment->outsidelimit = true ;
463 $comment->answers[$key] = $key;
464 $comment->stranswers[$key] .=get_string('trueansweroutsidelimits','qtype_calculated',$correcttrue);//<span class="error">ERROR True answer '..' outside limits</span>';
465 }else {
466 $comment->stranswers[$key] .=get_string('trueanswerinsidelimits','qtype_calculated',$correcttrue);//' True answer :'.$calculated->trueanswer.' inside limits';
467 }
468 $comment->stranswers[$key] .='';
fe6ce234 469 }*/
2d279432
PP
470 }
471 return fullclone($comment);
472 }
473
2d279432
PP
474 function get_correct_responses1(&$question, &$state) {
475 $virtualqtype = $this->get_virtual_qtype( $question);
476 /* if ($question->options->multichoice != 1 ) {
477 if($unit = $virtualqtype->get_default_numerical_unit($question)){
478 $unit = $unit->unit;
479 } else {
480 $unit = '';
481 }
482 foreach ($question->options->answers as $answer) {
483 if (((int) $answer->fraction) === 1) {
484 $answernumerical = qtype_calculated_calculate_answer(
485 $answer->answer, $state->options->dataset, $answer->tolerance,
486 $answer->tolerancetype, $answer->correctanswerlength,
487 $answer->correctanswerformat, ''); // remove unit
488 $correct = array('' => $answernumerical->answer);
489 $correct['answer']= $correct[''];
490 if (isset($correct['']) && $correct[''] != '*' && $unit ) {
491 $correct[''] .= ' '.$unit;
492 $correct['unit']= $unit;
493 }
494 return $correct;
495 }
496 }
fe6ce234
DC
497 }else{**/
498 return $virtualqtype->get_correct_responses($question, $state) ;
499 // }
2d279432
PP
500 return null;
501 }
502
2d279432
PP
503 function get_virtual_qtype() {
504 global $QTYPES;
fe6ce234
DC
505 // if ( isset($question->options->multichoice) && $question->options->multichoice == '1'){
506 $this->virtualqtype =& $QTYPES['multichoice'];
507 // }else {
508 // $this->virtualqtype =& $QTYPES['numerical'];
509 // }
2d279432
PP
510 return $this->virtualqtype;
511 }
512
513
fe6ce234
DC
514 /**
515 * Runs all the code required to set up and save an essay question for testing purposes.
516 * Alternate DB table prefix may be used to facilitate data deletion.
517 */
518 function generate_test($name, $courseid = null) {
519 global $DB;
520 list($form, $question) = parent::generate_test($name, $courseid);
521 $form->feedback = 1;
522 $form->multiplier = array(1, 1);
523 $form->shuffleanswers = 1;
524 $form->noanswers = 1;
525 $form->qtype ='calculatedmulti';
526 $question->qtype ='calculatedmulti';
527 $form->answers = array('{a} + {b}');
528 $form->fraction = array(1);
529 $form->tolerance = array(0.01);
530 $form->tolerancetype = array(1);
531 $form->correctanswerlength = array(2);
532 $form->correctanswerformat = array(1);
533 $form->questiontext = "What is {a} + {b}?";
534
535 if ($courseid) {
536 $course = $DB->get_record('course', array('id'=> $courseid));
537 }
538
94dbfb3a 539 $new_question = $this->save_question($question, $form);
fe6ce234
DC
540
541 $dataset_form = new stdClass();
542 $dataset_form->nextpageparam["forceregeneration"]= 1;
543 $dataset_form->calcmin = array(1 => 1.0, 2 => 1.0);
544 $dataset_form->calcmax = array(1 => 10.0, 2 => 10.0);
545 $dataset_form->calclength = array(1 => 1, 2 => 1);
546 $dataset_form->number = array(1 => 5.4 , 2 => 4.9);
547 $dataset_form->itemid = array(1 => '' , 2 => '');
548 $dataset_form->calcdistribution = array(1 => 'uniform', 2 => 'uniform');
549 $dataset_form->definition = array(1 => "1-0-a",
550 2 => "1-0-b");
551 $dataset_form->nextpageparam = array('forceregeneration' => false);
552 $dataset_form->addbutton = 1;
553 $dataset_form->selectadd = 1;
554 $dataset_form->courseid = $courseid;
555 $dataset_form->cmid = 0;
556 $dataset_form->id = $new_question->id;
557 $this->save_dataset_items($new_question, $dataset_form);
558
559 return $new_question;
560 }
561
5d548d3e 562 function move_files($questionid, $oldcontextid, $newcontextid) {
fe6ce234 563 $fs = get_file_storage();
fe6ce234 564
5d548d3e
TH
565 parent::move_files($questionid, $oldcontextid, $newcontextid);
566 $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true);
567
568 $fs->move_area_files_to_new_context($oldcontextid,
569 $newcontextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid);
570 $fs->move_area_files_to_new_context($oldcontextid,
571 $newcontextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid);
572 $fs->move_area_files_to_new_context($oldcontextid,
573 $newcontextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid);
fe6ce234
DC
574 }
575
9203b705
TH
576 protected function delete_files($questionid, $contextid) {
577 $fs = get_file_storage();
578
579 parent::delete_files($questionid, $contextid);
580 $this->delete_files_in_answers($questionid, $contextid, true);
581 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid);
582 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid);
583 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid);
584 }
585
fe6ce234
DC
586 function check_file_access($question, $state, $options, $contextid, $component,
587 $filearea, $args) {
588 $itemid = reset($args);
589
590 if (empty($question->maxgrade)) {
591 $question->maxgrade = $question->defaultgrade;
592 }
593
594 if (in_array($filearea, array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'))) {
595 $result = $options->feedback && ($itemid == $question->id);
596 if (!$result) {
597 return false;
598 }
599 if ($state->raw_grade >= $question->maxgrade/1.01) {
600 $feedbacktype = 'correctfeedback';
601 } else if ($state->raw_grade > 0) {
602 $feedbacktype = 'partiallycorrectfeedback';
603 } else {
604 $feedbacktype = 'incorrectfeedback';
605 }
606 if ($feedbacktype != $filearea) {
607 return false;
608 }
609 return true;
610 } else if ($component == 'question' && $filearea == 'answerfeedback') {
611 return $options->feedback && (array_key_exists($itemid, $question->options->answers));
612 } else {
613 return parent::check_file_access($question, $state, $options, $contextid, $component,
614 $filearea, $args);
615 }
616 }
2d279432 617}
fe6ce234 618
2d279432
PP
619//// END OF CLASS ////
620
621//////////////////////////////////////////////////////////////////////////
622//// INITIATION - Without this line the question type is not in use... ///
623//////////////////////////////////////////////////////////////////////////
624question_register_questiontype(new question_calculatedmulti_qtype());
34e24cd3
PP
625
626if ( ! defined ("CALCULATEDMULTI")) {
627 define("CALCULATEDMULTI", "calculatedmulti");
628}