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