MDL-27413 qtype_multianswer embedded inline multichoice now work.
[moodle.git] / question / type / multianswer / renderer.php
CommitLineData
12c6e008 1<?php
ab50232b
TH
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
ab50232b
TH
17/**
18 * Multianswer question renderer classes.
19 * Handle shortanswer, numerical and various multichoice subquestions
20 *
42a5b055
TH
21 * @package qtype
22 * @subpackage multianswer
23 * @copyright 2010 Pierre Pichet
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
ab50232b
TH
25 */
26
42a5b055
TH
27
28require_once($CFG->dirroot . '/question/type/shortanswer/renderer.php');
29
30
ab50232b
TH
31/**
32 * Base class for generating the bits of output common to multianswer
33 * (Cloze) questions.
34 * This render the main question text and transfer to the subquestions
12c6e008 35 * the task of display their input elements and status
ab50232b
TH
36 * feedback, grade, correct answer(s)
37 *
fa6c8620 38 * @copyright 2010 Pierre Pichet
ab50232b
TH
39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
40 */
12c6e008 41class qtype_multianswer_renderer extends qtype_renderer {
ab50232b
TH
42
43 public function formulation_and_controls(question_attempt $qa,
44 question_display_options $options) {
ab50232b
TH
45 $question = $qa->get_question();
46
42a5b055
TH
47 $output = '';
48 foreach ($question->textfragments as $i => $fragment) {
49 if ($i > 0) {
50 $index = $question->places[$i];
51 $output .= $this->subquestion($qa, $options, $index,
52 $question->subquestions[$index]);
53 }
54 $output .= $question->format_text($fragment, $question->questiontextformat,
55 $qa, 'question', 'questiontext', $question->id);
56 }
ab50232b 57
42a5b055
TH
58 $this->page->requires->js_init_call('M.qtype_multianswer.init',
59 array('#q' . $qa->get_slot()), false, array(
60 'name' => 'qtype_multianswer',
61 'fullpath' => '/question/type/multianswer/module.js',
62 'requires' => array('base', 'node', 'event', 'overlay'),
63 ));
ab50232b 64
42a5b055
TH
65 return $output;
66 }
ab50232b 67
42a5b055
TH
68 public function subquestion(question_attempt $qa,
69 question_display_options $options, $index, question_graded_automatically $subq) {
7ac7977c 70
42a5b055
TH
71 $subtype = $subq->qtype->name();
72 if ($subtype == 'numerical' || $subtype == 'shortanswer') {
73 $subrenderer = 'textfield';
74 } else if ($subtype == 'multichoice') {
75 if ($subq->layout == qtype_multichoice_base::LAYOUT_DROPDOWN) {
76 $subrenderer = 'multichoice_inline';
77 } else if ($subq->layout == qtype_multichoice_base::LAYOUT_HORIZONTAL) {
78 $subrenderer = 'multichoice_horizontal';
ab50232b 79 } else {
42a5b055
TH
80 $subrenderer = 'multichoice_vertical';
81 }
82 } else {
83 throw new coding_exception('Unexpected subquestion type.', $subq);
84 }
85 $renderer = $this->page->get_renderer('qtype_multianswer', $subrenderer);
86 return $renderer->subquestion($qa, $options, $index, $subq);
ab50232b
TH
87 }
88
ab50232b 89 public function correct_response(question_attempt $qa) {
fa6c8620 90 return '';
ab50232b 91 }
ab50232b
TH
92}
93
94
95/**
96 * Subclass for generating the bits of output specific to shortanswer
97 * subquestions.
98 *
42a5b055 99 * @copyright 2011 The Open University
ab50232b
TH
100 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
101 */
7ac7977c
TH
102abstract class qtype_multianswer_subq_renderer_base extends qtype_renderer {
103
104 abstract public function subquestion(question_attempt $qa,
105 question_display_options $options, $index,
106 question_graded_automatically $subq);
107
108 /**
109 * Render the feedback pop-up contents.
110 *
111 * @param question_graded_automatically $subq the subquestion.
112 * @param float $fraction the mark the student got. null if this subq was not answered.
113 * @param string $feedbacktext the feedback text, already processed with format_text etc.
114 * @param string $rightanswer the right answer, already processed with format_text etc.
115 * @param question_display_options $options the display options.
116 * @return string the HTML for the feedback popup.
117 */
118 protected function feedback_popup(question_graded_automatically $subq,
119 $fraction, $feedbacktext, $rightanswer, question_display_options $options) {
120
121 if (!$options->feedback) {
122 return '';
123 }
124
125 $feedback = array();
126 if ($options->correctness) {
127 if (is_null($fraction)) {
128 $state = question_state::$gaveup;
129 } else {
130 $state = question_state::graded_state_for_fraction($fraction);
131 }
132 $feedback[] = $state->default_string(true);
133 }
134
135 if ($options->rightanswer) {
136 $feedback[] = get_string('correctansweris', 'qtype_shortanswer', $rightanswer);
137 }
138
139 $subfraction = '';
140 if ($options->marks >= question_display_options::MARK_AND_MAX && $subq->maxmark > 0) {
141 $a = new stdClass();
142 $a->mark = format_float($fraction * $subq->maxmark, $options->markdp);
143 $a->max = format_float($subq->maxmark, $options->markdp);
144 $feedback[] = get_string('markoutofmax', 'question', $a);
145 }
146
147 return html_writer::tag('span', implode('<br />', $feedback),
148 array('class' => 'feedbackspan accesshide'));
149 }
150}
151
152
153/**
154 * Subclass for generating the bits of output specific to shortanswer
155 * subquestions.
156 *
157 * @copyright 2011 The Open University
158 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
159 */
160class qtype_multianswer_textfield_renderer extends qtype_multianswer_subq_renderer_base {
ab50232b 161
42a5b055
TH
162 public function subquestion(question_attempt $qa, question_display_options $options,
163 $index, question_graded_automatically $subq) {
164
165 $fieldprefix = 'sub' . $index . '_';
166 $fieldname = $fieldprefix . 'answer';
7ac7977c 167
42a5b055 168 $response = $qa->get_last_qt_var($fieldname);
7ac7977c
TH
169 if ($subq->qtype->name() == 'shortanswer') {
170 $matchinganswer = $subq->get_matching_answer(array('answer' => $response));
171 } else {
172 $matchinganswer = $subq->get_matching_answer($response);
173 }
174
42a5b055 175 if (!$matchinganswer) {
7ac7977c 176 $matchinganswer = new question_answer(0, '', null, '', FORMAT_HTML);
ab50232b 177 }
42a5b055
TH
178
179 // Work out a good input field size.
180 $size = max(1, strlen(trim($response)) + 1);
181 foreach ($subq->answers as $ans) {
182 $size = max($size, strlen(trim($ans->answer)));
ab50232b 183 }
42a5b055
TH
184 $size = min(60, round($size + rand(0, $size*0.15)));
185 // The rand bit is to make guessing harder
186
ab50232b
TH
187 $inputattributes = array(
188 'type' => 'text',
42a5b055 189 'name' => $qa->get_qt_field_name($fieldname),
ab50232b 190 'value' => $response,
42a5b055 191 'id' => $qa->get_qt_field_name($fieldname),
ab50232b
TH
192 'size' => $size,
193 );
ab50232b
TH
194 if ($options->readonly) {
195 $inputattributes['readonly'] = 'readonly';
ab50232b 196 }
ab50232b 197
42a5b055
TH
198 $feedbackimg = '';
199 if ($options->correctness) {
7ac7977c
TH
200 $inputattributes['class'] = $this->feedback_class($matchinganswer->fraction);
201 $feedbackimg = $this->feedback_image($matchinganswer->fraction);
ab50232b 202 }
42a5b055 203
7ac7977c
TH
204 if ($subq->qtype->name() == 'shortanswer') {
205 $correctanswer = $subq->get_matching_answer($subq->get_correct_response());
206 } else {
207 $correctanswer = $subq->get_correct_answer();
208 }
42a5b055 209
7ac7977c
TH
210 $feedbackpopup = $this->feedback_popup($subq, $matchinganswer->fraction,
211 $subq->format_text($matchinganswer->feedback, $matchinganswer->feedbackformat,
212 $qa, 'question', 'answerfeedback', $matchinganswer->id),
213 s($correctanswer->answer), $options);
214
215 $output = '';
216 $output .= html_writer::start_tag('label', array('class' => 'subq'));
217 $output .= html_writer::empty_tag('input', $inputattributes);
218 $output .= $feedbackimg;
219 $output .= $feedbackpopup;
220 $output .= html_writer::end_tag('label');
42a5b055 221
7ac7977c
TH
222 return $output;
223 }
224}
225
226
227/**
228 * Render an embedded multiple-choice question that is displayed as a select menu.
229 *
230 * @copyright 2010 Pierre Pichet
231 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
232 */
233class qtype_multianswer_multichoice_inline_renderer
234 extends qtype_multianswer_subq_renderer_base {
235
236 public function subquestion(question_attempt $qa, question_display_options $options,
237 $index, question_graded_automatically $subq) {
238
239 $fieldprefix = 'sub' . $index . '_';
240 $fieldname = $fieldprefix . 'answer';
241
242 $response = $qa->get_last_qt_var($fieldname);
243 $choices = array();
244 $matchinganswer = new question_answer(0, '', null, '', FORMAT_HTML);
245 $rightanswer = null;
246 foreach ($subq->get_order($qa) as $value => $ansid) {
247 $ans = $subq->answers[$ansid];
248 $choices[$value] = $subq->format_text($ans->answer, $ans->answerformat,
249 $qa, 'question', 'answer', $ansid);
250 if ($subq->is_choice_selected($response, $value)) {
251 $matchinganswer = $ans;
ab50232b 252 }
7ac7977c 253 }
42a5b055 254
7ac7977c
TH
255 $inputattributes = array(
256 'id' => $qa->get_qt_field_name($fieldname),
257 );
258 if ($options->readonly) {
259 $inputattributes['disabled'] = 'disabled';
ab50232b 260 }
ab50232b 261
7ac7977c
TH
262 $feedbackimg = '';
263 if ($options->correctness) {
264 $inputattributes['class'] = $this->feedback_class($matchinganswer->fraction);
265 $feedbackimg = $this->feedback_image($matchinganswer->fraction);
266 }
267
268 $select = html_writer::select($choices, $qa->get_qt_field_name($fieldname),
269 $response, array('' => ''), $inputattributes);
270
271 $order = $subq->get_order($qa);
272 $rightanswer = $subq->answers[$order[reset($subq->get_correct_response())]];
273 $feedbackpopup = $this->feedback_popup($subq, $matchinganswer->fraction,
274 $subq->format_text($matchinganswer->feedback, $matchinganswer->feedbackformat,
275 $qa, 'question', 'answerfeedback', $matchinganswer->id),
276 $subq->format_text($rightanswer->answer, $rightanswer->answerformat,
277 $qa, 'question', 'answer', $rightanswer->id), $options);
278
42a5b055
TH
279 $output = '';
280 $output .= html_writer::start_tag('label', array('class' => 'subq'));
7ac7977c 281 $output .= $select;
42a5b055
TH
282 $output .= $feedbackimg;
283 $output .= $feedbackpopup;
284 $output .= html_writer::end_tag('label');
ab50232b 285
42a5b055
TH
286 return $output;
287 }
7ac7977c
TH
288
289 public function formulation_and_controls(question_attempt $qa,
290 question_display_options $options) {
291 $questiontot = $qa->get_question();
292 $subquestion = $questiontot->subquestions[$qa->subquestionindex];
293 $answers = $subquestion->answers;
294 $correctanswers = $subquestion->get_correct_response();
295 foreach ($correctanswers as $key => $value) {
296 $correct = $value;
297 }
298 $order = $subquestion->get_order($qa);
299 $response = $this->get_response($qa);
300 $currentanswer = $response;
301 $answername = $subquestion->fieldid.'answer';
302 $inputname = $qa->get_qt_field_name($answername);
303 $inputattributes = array(
304 'type' => $this->get_input_type(),
305 'name' => $inputname,
306 );
307
308 if ($options->readonly) {
309 $inputattributes['disabled'] = 'disabled';
310 $readonly = 'disabled ="disabled"';
311 }
312 $choices = array();
313 $popup = '';
314 $feedback = '';
315 $answer = '';
316 $classes = 'control';
317 $feedbackimage = '';
318 $fraction = 0;
319 $chosen = 0;
320
321 foreach ($order as $value => $ansid) {
322 $mcanswer = $subquestion->answers[$ansid];
323 $choices[$value] = strip_tags($mcanswer->answer);
324 $selected = '';
325 $isselected = false;
326 if ( $response != '') {
327 $isselected = $this->is_choice_selected($response, $value);
328 }
329 if ($isselected) {
330 $chosen = $value;
331 $answer = $mcanswer;
332 $fraction = $mcanswer->fraction;
333 $selected = ' selected="selected"';
334 }
335 }
336 if ($options->feedback) {
337 if ($answer) {
338 $classes .= ' ' . question_get_feedback_class($fraction);
339 $feedbackimage = question_get_feedback_image($answer->fraction);
340 if ($answer->feedback) {
341 $feedback .= $subquestion->format_text($answer->feedback);
342 }
343 } else {
344 $classes .= ' ' . question_get_feedback_class(0);
345 $feedbackimage = question_get_feedback_image(0);
346 }
347 }
348 // determine popup
349 // answer feedback (specific)i.e if options->feedback already set
350 // subquestion status correctness or Finished validator if correctness
351 // Correct response
352 // marks
353 $strfeedbackwrapped = 'Response Status';
354 if ($options->feedback) {
355 $feedback = get_string('feedback', 'quiz').":".$feedback."<br />";
356
357 if ($options->correctness) {
358 if (!$answer) {
359 $state = $qa->get_state();
360 $state = question_state::$invalid;
361 $strfeedbackwrapped .= ":<font color=red >".$state->default_string()."</font>";
362 $feedback = "<font color=red >".get_string('singleanswer', 'quiz') ."</font><br />";
363 } else {
364 $state = $qa->get_state();
365 $state = question_state::graded_state_for_fraction($fraction);
366 $strfeedbackwrapped .= ":".$state->default_string();
367 }
368 }
369
370 if ($options->correctresponse) {
371 $feedback .= $this->correct_response($qa)."<br />";
372 }
373 if ($options->marks) {
374 $subgrade= $fraction * $subquestion->defaultmark;
375 $feedback .= $questiontot->mark_summary($options, $subquestion->defaultmark , $subgrade);
376 }
377
378 $feedback .= '</div>';
379 }
380
381 if ($options->feedback) {
382 // need to replace ' and " as they could break the popup string
383 // as the text comes from database, slashes have been removed
384 // addslashes will not work as it keeps the "
385 // HTML &#039; for ' does not work
386 $feedback = str_replace("'", "\'", $feedback);
387 $feedback = str_replace('"', "\'", $feedback);
388 $strfeedbackwrapped = str_replace("'", "\'", $strfeedbackwrapped);
389 $strfeedbackwrapped = str_replace('"', "\'", $strfeedbackwrapped);
390
391 $popup = " onmouseover=\"return overlib('$feedback', STICKY, MOUSEOFF, CAPTION, '$strfeedbackwrapped', FGCOLOR, '#FFFFFF');\" ".
392 " onmouseout=\"return nd();\" ";
393 }
394 $result = '';
395
396 $result .= "<span $popup >";
397 $result .= html_writer::start_tag('span', array('class' => $classes), '');
398
399 $result .= choose_from_menu($choices, $inputname, $chosen,
400 ' ', '', '', true, $options->readonly) . $feedbackimage;
401 $result .= html_writer::end_tag('span');
402 $result .= html_writer::end_tag('span');
403
404 return $result;
405 }
406
407 protected function format_choices($question) {
408 $choices = array();
409 foreach ($question->get_choice_order() as $key => $choiceid) {
410 $choices[$key] = strip_tags($question->format_text($question->choices[$choiceid]));
411 }
412 return $choices;
413 }
ab50232b
TH
414}
415
12c6e008 416
ab50232b
TH
417/**
418 * As multianswer have specific display requirements for multichoice display
419 * a new class was defined although largely following the multichoice one
12c6e008
TH
420 *
421 * @copyright 2010 Pierre Pichet
422 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
ab50232b 423 */
12c6e008 424abstract class qtype_multianswer_multichoice_renderer_base extends qtype_renderer {
ab50232b
TH
425 abstract protected function get_input_type();
426
427 abstract protected function get_input_name(question_attempt $qa, $value);
428
429 abstract protected function get_input_value($value);
430
431 abstract protected function get_input_id(question_attempt $qa, $value);
432
433 abstract protected function is_choice_selected($response, $value);
434
435 abstract protected function is_right(question_answer $ans);
436
437 abstract protected function get_response(question_attempt $qa);
ab50232b
TH
438
439 public function specific_feedback(question_attempt $qa) {
12c6e008 440 return '';
ab50232b 441 }
12c6e008 442
ab50232b
TH
443 public function formulation_and_controls(question_attempt $qa,
444 question_display_options $options) {
12c6e008 445
ab50232b
TH
446 $questiontot = $qa->get_question();
447 $subquestion = $questiontot->subquestions[$qa->subquestionindex];
12c6e008 448 $order = $subquestion->get_order($qa);
ab50232b
TH
449 $response = $this->get_response($qa);
450 $inputattributes = array(
451 'type' => $this->get_input_type(),
12c6e008 452 );
ab50232b
TH
453
454 if ($options->readonly) {
455 $inputattributes['disabled'] = 'disabled';
456 }
457 $radiobuttons = array();
458 $feedbackimg = array();
459 $feedback = array();
460 $classes = array();
12c6e008
TH
461 $totfraction = 0;
462 $nullresponse = true;
ab50232b
TH
463 foreach ($order as $value => $ansid) {
464 $ans = $subquestion->answers[$ansid];
465 $inputattributes['name'] = $this->get_input_name($qa, $value);
ab50232b
TH
466 $inputattributes['value'] = $this->get_input_value($value);
467 $inputattributes['id'] = $this->get_input_id($qa, $value);
468 if ($subquestion->single) {
469 $isselected = $this->is_choice_selected($response, $value);
12c6e008
TH
470 } else {
471 $isselected = $this->is_choice_selected($response, $value);
ab50232b
TH
472 }
473 if ($isselected) {
474 $inputattributes['checked'] = 'checked';
12c6e008
TH
475 $totfraction += $ans->fraction;
476 $nullresponse = false;
ab50232b
TH
477 } else {
478 unset($inputattributes['checked']);
479 }
480 $radiobuttons[] = html_writer::empty_tag('input', $inputattributes) .
481 html_writer::tag('label', $subquestion->format_text($ans->answer), array('for' => $inputattributes['id']));
482
483 if (($options->feedback || $options->correctresponse) && $response !== -1) {
484 $feedbackimg[] = question_get_feedback_image($this->is_right($ans), $isselected && $options->feedback);
485 } else {
486 $feedbackimg[] = '';
487 }
488 if (($options->feedback || $options->correctresponse) && $isselected) {
489 $feedback[] = $subquestion->format_text($ans->feedback);
490 } else {
491 $feedback[] = '';
492 }
493 $class = 'r' . ($value % 2);
494 if ($options->correctresponse && $ans->fraction > 0) {
495 $class .= ' ' . question_get_feedback_class($ans->fraction);
496 }
497 $classes[] = $class;
498 }
499
12c6e008
TH
500 $result = '';
501
502 $answername = 'answer';
503 if ($subquestion->layout == 1) {
ab50232b 504 $result .= html_writer::start_tag('div', array('class' => 'ablock'));
12c6e008 505
ab50232b
TH
506 $result .= html_writer::start_tag('table', array('class' => $answername));
507 foreach ($radiobuttons as $key => $radio) {
508 $result .= html_writer::start_tag('tr', array('class' => $answername));
509 $result .= html_writer::start_tag('td', array('class' => $answername));
12c6e008 510 $result .= html_writer::tag('span', $radio . $feedbackimg[$key] . $feedback[$key], array('class' => $classes[$key])) . "\n";
ab50232b
TH
511 $result .= html_writer::end_tag('td');
512 $result .= html_writer::end_tag('tr');
513 }
514 $result .= html_writer::end_tag('table'); // answer
12c6e008 515
ab50232b
TH
516 $result .= html_writer::end_tag('div'); // ablock
517 }
12c6e008
TH
518 if ($subquestion->layout == 2) {
519 $result .= html_writer::start_tag('div', array('class' => 'ablock'));
ab50232b
TH
520 $result .= html_writer::start_tag('table', array('class' => $answername));
521 $result .= html_writer::start_tag('tr', array('class' => $answername));
522 foreach ($radiobuttons as $key => $radio) {
523 $result .= html_writer::start_tag('td', array('class' => $answername));
12c6e008 524 $result .= html_writer::tag('span', $radio . $feedbackimg[$key] . $feedback[$key]
ab50232b
TH
525 , array('class' => $classes[$key])) . "\n";
526 $result .= html_writer::end_tag('td');
527 }
528 $result .= html_writer::end_tag('tr');
529 $result .= html_writer::end_tag('table'); // answer
12c6e008 530
ab50232b 531 $result .= html_writer::end_tag('div'); // ablock
12c6e008
TH
532 }
533
534 if ($options->feedback) {
ab50232b
TH
535 $result .= html_writer::start_tag('div', array('class' => 'outcome'));
536
12c6e008
TH
537 if ($options->correctness) {
538 if ( $nullresponse) {
ab50232b
TH
539 $state = $qa->get_state();
540 $state = question_state::$invalid;
541 $result1 = $state->default_string();
12c6e008 542 $result .= html_writer::nonempty_tag('div', $result1,
ab50232b 543 array('class' => 'validationerror'));
12c6e008 544 $result1 = ($subquestion->single) ? get_string('singleanswer', 'quiz') : get_string('multipleanswers', 'quiz');
ab50232b 545 $result .= html_writer::nonempty_tag('div', $result1,
12c6e008
TH
546 array('class' => 'validationerror'));
547 } else {
ab50232b
TH
548 $state = $qa->get_state();
549 $state = question_state::graded_state_for_fraction($totfraction);
550 $result1 = $state->default_string();
551 $result .= html_writer::nonempty_tag('div', $result1,
552 array('class' => 'outcome'));
553 }
554 }
ab50232b 555
12c6e008
TH
556 if ($options->correctresponse) {
557 $result1 = $this->correct_response($qa);
558 $result .= html_writer::nonempty_tag('div', $result1, array('class' => 'outcome'));
559 }
560 if ($options->marks) {
561 $subgrade= $totfraction * $subquestion->defaultmark;
562 $result .= $questiontot->mark_summary($options, $subquestion->defaultmark , $subgrade);
563 }
564
565 if ($qa->get_state() == question_state::$invalid) {
566 $result .= html_writer::nonempty_tag('div', array('class' => 'validationerror'),
567 $subquestion->get_validation_error($qa->get_last_qt_data()));
568 }
569 $result .= html_writer::end_tag('div');
ab50232b 570
12c6e008 571 }
ab50232b
TH
572 return $result;
573 }
574
575
576}
577
578
579class qtype_multianswer_multichoice_single_renderer extends qtype_multianswer_multichoice_renderer_base {
12c6e008 580 protected function get_input_type() {
ab50232b 581 return 'radio';
12c6e008
TH
582 }
583
584 protected function is_choice_selected($response, $value) {
585 return $response == $value;
586 }
587
588 protected function is_right(question_answer $ans) {
589 return $ans->fraction > 0.9999999;
590 }
591
592 protected function get_input_name(question_attempt $qa, $value) {
593 $questiontot = $qa->get_question();
594 $subquestion = $questiontot->subquestions[$qa->subquestionindex];
595 $answername = $subquestion->fieldid.'answer';
596 return $qa->get_qt_field_name($answername);
597 }
598
599 protected function get_input_value($value) {
600 return $value;
601 }
602
603 protected function get_input_id(question_attempt $qa, $value) {
ab50232b
TH
604 $questiontot = $qa->get_question();
605 $subquestion = $questiontot->subquestions[$qa->subquestionindex];
606 $answername = $subquestion->fieldid.'answer';
607 return $qa->get_qt_field_name($answername);
608 }
609
610 protected function get_response(question_attempt $qa) {
611 $questiontot = $qa->get_question();
612 $subquestion = $questiontot->subquestions[$qa->subquestionindex];
613 return $qa->get_last_qt_var($subquestion->fieldid.'answer', -1);
12c6e008 614
ab50232b 615 }
12c6e008 616
ab50232b
TH
617 public function correct_response(question_attempt $qa) {
618 $questiontot = $qa->get_question();
619 $subquestion = $questiontot->subquestions[$qa->subquestionindex];
12c6e008 620
ab50232b
TH
621 foreach ($subquestion->answers as $ans) {
622 if ($ans->fraction > 0.9999999) {
623 return get_string('correctansweris', 'qtype_multichoice',
624 $subquestion->format_text($ans->answer));
625 }
626 }
627
12c6e008 628 return '';
ab50232b 629 }
ab50232b 630}