public function controls(question_attempt $qa, question_display_options $options) { if ($options->readonly || $qa->get_state() != question_state::$todo) { return ''; } // Hidden input to move the question into the complete state. return html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $qa->get_behaviour_field_name('seen'), 'value' => 1)); }
public function subquestion(question_attempt $qa, question_display_options $options, qtype_combined_combinable_base $subq, $placeno) { $question = $subq->question; $place = $placeno + 1; $group = $question->places[$place]; $fieldname = $subq->step_data_name($question->field($place)); $value = $qa->get_last_qt_var($fieldname); $attributes = array('id' => str_replace(':', '_', $qa->get_qt_field_name($fieldname))); if ($options->readonly) { $attributes['disabled'] = 'disabled'; } $orderedchoices = $question->get_ordered_choices($group); $selectoptions = array(); foreach ($orderedchoices as $orderedchoicevalue => $orderedchoice) { $selectoptions[$orderedchoicevalue] = $orderedchoice->text; } $feedbackimage = ''; if ($options->correctness) { $response = $qa->get_last_qt_data(); if (array_key_exists($fieldname, $response)) { $fraction = (int) ($response[$fieldname] == $question->get_right_choice_for($place)); $attributes['class'] = $this->feedback_class($fraction); $feedbackimage = $this->feedback_image($fraction); } } $selecthtml = html_writer::select($selectoptions, $qa->get_qt_field_name($fieldname), $value, get_string('choosedots'), $attributes) . ' ' . $feedbackimage; return html_writer::tag('span', $selecthtml, array('class' => 'control')); }
protected function get_graded_step(question_attempt $qa) { foreach ($qa->get_reverse_step_iterator() as $step) { if ($step->has_behaviour_var('_try')) { return $step; } } }
public function feedback(question_attempt $qa, question_display_options $options) { if (!$options->feedback) { return ''; } if ($qa->get_state() == question_state::$gaveup || $qa->get_state() == question_state::$mangaveup) { return ''; } $feedback = ''; if (!$qa->get_last_behaviour_var('certainty') && $qa->get_last_behaviour_var('_assumedcertainty')) { $feedback .= html_writer::tag('p', get_string('assumingcertainty', 'qbehaviour_deferredcbm', question_cbm::get_string($qa->get_last_behaviour_var('_assumedcertainty')))); } if ($options->marks >= question_display_options::MARK_AND_MAX) { $a = new stdClass(); $a->rawmark = format_float($qa->get_last_behaviour_var('_rawfraction') * $qa->get_max_mark(), $options->markdp); $a->mark = $qa->format_mark($options->markdp); $feedback .= html_writer::tag('p', get_string('markadjustment', 'qbehaviour_deferredcbm', $a)); } return $feedback; }
/** * Generate the display of a question in a particular state, and with certain * display options. Normally you do not call this method directly. Intsead * you call {@link question_usage_by_activity::render_question()} which will * call this method with appropriate arguments. * * @param question_attempt $qa the question attempt to display. * @param qbehaviour_renderer $behaviouroutput the renderer to output the behaviour * specific parts. * @param qtype_renderer $qtoutput the renderer to output the question type * specific parts. * @param question_display_options $options controls what should and should not be displayed. * @param string|null $number The question number to display. 'i' is a special * value that gets displayed as Information. Null means no number is displayed. * @return string HTML representation of the question. */ public function question(question_attempt $qa, qbehaviour_renderer $behaviouroutput, qtype_renderer $qtoutput, question_display_options $options, $number) { //start a new output buffer $output = ''; //add the quesiton number (TODO: style?) //$output .= '<strong>' . $number .'.</strong> '; $output .= html_writer::start_tag('table', array('style' => 'width: 100%; padding-bottom: 4px;')); $output .= html_writer::start_tag('tr', array()); $output .= html_writer::tag('td', $number . '.', array('valign' => 'top', 'width' => '10%', 'style' => 'padding-right: 10px;')); $output .= html_writer::start_tag('td', array('width' => '90%')); //get the question from the attempt object $question = $qa->get_question(); $pragmas = self::extract_pragmas($question->format_questiontext($qa)); //add the question's formulation $output .= $this->formulation($qa, $behaviouroutput, $qtoutput, $options); //an indication of output, if appropriate $output .= $this->outcome($qa, $behaviouroutput, $qtoutput, $options); //any manual comments, if appropriate $output .= $this->manual_comment($qa, $behaviouroutput, $qtoutput, $options); //the user's response history, if appropriate $output .= $this->response_history($qa, $behaviouroutput, $qtoutput, $options); $output .= html_writer::end_tag('td'); $output .= html_writer::end_tag('tr'); $output .= html_writer::end_tag('table'); //if a pragma exists specifying the space after a given quesiton, use it; otherwise, assume 5px //$space_after = array_key_exists('space_after', $pragmas) ? $pragmas['space_after'] : '5px'; $space_after = array_key_exists('space_after', $pragmas) ? $pragmas['space_after'] : 0; //and add a spacer after the given question if ($space_after !== 0) { $output .= html_writer::tag('div', ' ', array('style' => 'height: ' . $space_after . ';')); } //return the contents of the output buffer return $output; }
protected function embedded_element(question_attempt $qa, $place, question_display_options $options) { $question = $qa->get_question(); $group = $question->places[$place]; $fieldname = $question->field($place); $value = $qa->get_last_qt_var($question->field($place)); $attributes = array('id' => $this->box_id($qa, 'p' . $place)); $groupclass = 'group' . $group; if ($options->readonly) { $attributes['disabled'] = 'disabled'; } $orderedchoices = $question->get_ordered_choices($group); $selectoptions = array(); foreach ($orderedchoices as $orderedchoicevalue => $orderedchoice) { $selectoptions[$orderedchoicevalue] = $orderedchoice->text; } $feedbackimage = ''; if ($options->correctness) { $response = $qa->get_last_qt_data(); if (array_key_exists($fieldname, $response)) { $fraction = (int) ($response[$fieldname] == $question->get_right_choice_for($place)); $attributes['class'] = $this->feedback_class($fraction); $feedbackimage = $this->feedback_image($fraction); } } $selecthtml = html_writer::select($selectoptions, $qa->get_qt_field_name($fieldname), $value, get_string('choosedots'), $attributes) . ' ' . $feedbackimage; return html_writer::tag('span', $selecthtml, array('class' => 'control ' . $groupclass)); }
public function feedback(question_attempt $qa, question_display_options $options) { if ($qa->get_last_behaviour_var('_precheck', 0)) { return ''; } else { return parent::feedback($qa, $options); } }
public function manual_comment(question_attempt $qa, question_display_options $options) { if ($options->manualcomment != question_display_options::EDITABLE) { return ''; } $question = $qa->get_question(); return html_writer::nonempty_tag('div', $question->format_text($question->graderinfo, $question->graderinfo, $qa, 'qtype_poodllrecording', 'graderinfo', $question->id), array('class' => 'graderinfo')); }
/** * Normally you should not call this constuctor directly. The appropriate * behaviour object is created automatically as part of * {@link question_attempt::start()}. * @param question_attempt $qa the question attempt we will be managing. * @param string $preferredbehaviour the type of behaviour that was actually * requested. This information is not needed in most cases, the type of * subclass is enough, but occasionally it is needed. */ public function __construct(question_attempt $qa, $preferredbehaviour) { $this->qa = $qa; $this->question = $qa->get_question(); if (!$this->is_compatible_question($this->question)) { throw new coding_exception('This behaviour (' . $this->get_name() . ') cannot work with this question (' . get_class($this->question) . ')'); } }
public function feedback(question_attempt $qa, question_display_options $options) { // If the latest answer was invalid, display an informative message. if ($qa->get_state() == question_state::$invalid) { return html_writer::nonempty_tag('div', $this->disregarded_info(), array('class' => 'gradingdetails')); } // Otherwise get the details. return $this->render_adaptive_marks($qa->get_behaviour()->get_adaptive_marks(), $options); }
/** * Normally you should not call this constuctor directly. The appropriate * behaviour object is created automatically as part of * {@link question_attempt::start()}. * @param question_attempt $qa the question attempt we will be managing. * @param string $preferredbehaviour the type of behaviour that was actually * requested. This information is not needed in most cases, the type of * subclass is enough, but occasionally it is needed. */ public function __construct(question_attempt $qa, $preferredbehaviour) { $this->qa = $qa; $this->question = $qa->get_question(); $requiredclass = $this->required_question_definition_type(); if (!$this->question instanceof $requiredclass) { throw new coding_exception('This behaviour (' . $this->get_name() . ') cannot work with this question (' . get_class($this->question) . ')'); } }
public function correct_response(question_attempt $qa) { $question = $qa->get_question(); $answer = $question->get_matching_answer($question->get_correct_response()); if (!$answer) { return ''; } return get_string('correctansweris', 'qtype_shortanswer', s($answer->answer)); }
public function specific_feedback(question_attempt $qa) { $question = $qa->get_question(); $response = array(); foreach ($question->get_parameters() as $param) { $response['answer_' . $param] = $qa->get_last_qt_var('answer_' . $param); } $question->compute_feedbackperconditions($response); return $question->computedfeedbackperconditions; }
/** * Generates the specific feedback from the database when the attempt is finished and the question is answered. */ public function specific_feedback(question_attempt $qa) { global $DB, $CFG; // get feedback from the database $record = $DB->get_record('qtype_javaunittest_feedback', array('questionattemptid' => $qa->get_database_id()), 'feedback'); if ($record === false) { return ''; } $feedback = $record->feedback; $question = $qa->get_question(); return $question->format_text($feedback, 0, $qa, 'question', 'answerfeedback', 1); }
public function correct_response(question_attempt $qa) { $question = $qa->get_question(); $answer = $question->get_correct_response(); if (!$answer) { return ''; } $response = $answer['answer']; if ($question->unitdisplay != qtype_numerical::UNITNONE && $question->unitdisplay != qtype_numerical::UNITINPUT) { $response = $question->ap->add_unit($response); } return get_string('correctansweris', 'qtype_shortanswer', $response); }
public function feedback(question_attempt $qa, question_display_options $options) { if (!$qa->get_state()->is_active() || !$options->readonly) { return ''; } $attributes = array('type' => 'submit', 'id' => $qa->get_behaviour_field_name('tryagain'), 'name' => $qa->get_behaviour_field_name('tryagain'), 'value' => get_string('tryagain', 'qbehaviour_interactive'), 'class' => 'submit btn'); if ($options->readonly !== qbehaviour_interactive::READONLY_EXCEPT_TRY_AGAIN) { $attributes['disabled'] = 'disabled'; } $output = html_writer::empty_tag('input', $attributes); if (empty($attributes['disabled'])) { $this->page->requires->js_init_call('M.core_question_engine.init_submit_button', array($attributes['id'], $qa->get_slot())); } return $output; }
public function correct_response(question_attempt $qa) { $question = $qa->get_question(); $correctanswer = ''; foreach ($question->textfragments as $i => $fragment) { if ($i > 0) { $group = $question->places[$i]; $choice = $question->choices[$group][$question->rightchoices[$i]]; $correctanswer .= '[' . str_replace('-', '‑', $choice->text) . ']'; } $correctanswer .= $fragment; } if (!empty($correctanswer)) { return get_string('correctansweris', 'qtype_gapselect', $question->format_text($correctanswer, $question->questiontextformat, $qa, 'question', 'questiontext', $question->id)); } }
public function test_render_missing() { $records = new question_test_recordset(array(array('questionattemptid', 'contextid', 'questionusageid', 'slot', 'behaviour', 'questionid', 'variant', 'maxmark', 'minfraction', 'maxfraction', 'flagged', 'questionsummary', 'rightanswer', 'responsesummary', 'timemodified', 'attemptstepid', 'sequencenumber', 'state', 'fraction', 'timecreated', 'userid', 'name', 'value'), array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0, 0.0, 1.0, 0, '', '', '', 1256233790, 1, 0, 'todo', null, 1256233700, 1, '_order', '1,2,3'), array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0, 0.0, 1.0, 0, '', '', '', 1256233790, 2, 1, 'complete', 0.5, 1256233705, 1, '-submit', '1'), array(1, 123, 1, 1, 'strangeunknown', -1, 1, 2.0, 0.0, 1.0, 0, '', '', '', 1256233790, 2, 1, 'complete', 0.5, 1256233705, 1, 'choice0', '1'))); $question = test_question_maker::make_question('truefalse', 'true'); $question->id = -1; question_bank::start_unit_test(); question_bank::load_test_question_data($question); $qa = question_attempt::load_from_records($records, 1, new question_usage_null_observer(), 'deferredfeedback'); question_bank::end_unit_test(); $this->assertEquals(2, $qa->get_num_steps()); $step = $qa->get_step(0); $this->assertEquals(question_state::$todo, $step->get_state()); $this->assertNull($step->get_fraction()); $this->assertEquals(1256233700, $step->get_timecreated()); $this->assertEquals(1, $step->get_user_id()); $this->assertEquals(array('_order' => '1,2,3'), $step->get_all_data()); $step = $qa->get_step(1); $this->assertEquals(question_state::$complete, $step->get_state()); $this->assertEquals(0.5, $step->get_fraction()); $this->assertEquals(1256233705, $step->get_timecreated()); $this->assertEquals(1, $step->get_user_id()); $this->assertEquals(array('-submit' => '1', 'choice0' => '1'), $step->get_all_data()); $output = $qa->render(new question_display_options(), '1'); $this->assertRegExp('/' . preg_quote($qa->get_question()->questiontext, '/') . '/', $output); $this->assertRegExp('/' . preg_quote(get_string('questionusedunknownmodel', 'qbehaviour_missing'), '/') . '/', $output); $this->assertTag(array('tag' => 'div', 'attributes' => array('class' => 'warning')), $output); }
/** * Display the information about the penalty calculations. * @param question_attempt $qa the question attempt. * @param object $mark contains information about the current mark. * @param question_display_options $options display options. */ protected function penalty_info(question_attempt $qa, $mark, question_display_options $options) { if (!$qa->get_question()->penalty) { return ''; } $output = ''; // print details of grade adjustment due to penalties if ($mark->raw != $mark->cur) { $output .= ' ' . get_string('gradingdetailsadjustment', 'qbehaviour_adaptive', $mark); } // print info about new penalty // penalty is relevant only if the answer is not correct and further attempts are possible if (!$qa->get_state()->is_finished()) { $output .= ' ' . get_string('gradingdetailspenalty', 'qbehaviour_adaptive', format_float($qa->get_question()->penalty, $options->markdp)); } return $output; }
/** * Generate the display of the formulation part of the question. This is the * area that contains the quetsion text, and the controls for students to * input their answers. Some question types also embed bits of feedback, for * example ticks and crosses, in this area. * * @param question_attempt $qa the question attempt to display. * @param question_display_options $options controls what should and should not be displayed. * @return string HTML fragment. */ public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); $table = new html_table(); $table->attributes['class'] = 'matrix'; $table->head = array(); $table->head[] = ''; foreach ($question->cols as $col) { $table->head[] = self::matrix_header($col); } if ($options->correctness) { $table->head[] = ''; } foreach ($question->rows as $row) { $row_data = array(); $row_data[] = self::matrix_header($row); foreach ($question->cols as $col) { $key = $question->key($row, $col); $cell_name = $qa->get_field_prefix() . $key; $is_readonly = $options->readonly; $is_checked = $question->is_answered($response, $row, $col); if ($question->multiple) { $cell = self::checkbox($cell_name, $is_checked, $is_readonly); } else { $cell = self::radio($cell_name, $col->id, $is_checked, $is_readonly); } if ($options->correctness) { $weight = $question->weight($row, $col); $cell .= $this->feedback_image($weight); } $row_data[] = $cell; } if ($options->correctness) { $row_grade = $question->grading()->grade_row($question, $row, $response); $feedback = $row->feedback; $feedback = strip_tags($feedback) ? $feedback : ''; $row_data[] = $this->feedback_image($row_grade) . $feedback; } $table->data[] = $row_data; //$row_index++; } $result = $question->questiontext; $result .= html_writer::table($table, true); return $result; }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $questiontext = $question->format_questiontext($qa); $placeholder = false; if (preg_match('/_____+/', $questiontext, $matches)) { $placeholder = $matches[0]; } $input = '**subq controls go in here**'; if ($placeholder) { $questiontext = substr_replace($questiontext, $input, strpos($questiontext, $placeholder), strlen($placeholder)); } $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); /* if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error(array('answer' => $currentanswer)), array('class' => 'validationerror')); }*/ return $result; }
public function feedback(question_attempt $qa, question_display_options $options) { // Try to find the last graded step. $isstateimprovable = $qa->get_behaviour()->is_state_improvable($qa->get_state()); $gradedstep = $this->get_graded_step($qa); if ($gradedstep) { if ($gradedstep->has_behaviour_var('_helps')) { return $this->extra_help($qa, $options); } } if (is_null($gradedstep) || $qa->get_max_mark() == 0 || $options->marks < question_display_options::MARK_AND_MAX) { return ''; } // Display the grading details from the last graded state $mark = new stdClass(); $mark->max = $qa->format_max_mark($options->markdp); $actualmark = $gradedstep->get_fraction() * $qa->get_max_mark(); $mark->cur = format_float($actualmark, $options->markdp); $rawmark = $gradedstep->get_behaviour_var('_rawfraction') * $qa->get_max_mark(); $mark->raw = format_float($rawmark, $options->markdp); // let student know wether the answer was correct if ($qa->get_state()->is_commented()) { $class = $qa->get_state()->get_feedback_class(); } else { $class = question_state::graded_state_for_fraction($gradedstep->get_behaviour_var('_rawfraction'))->get_feedback_class(); } $gradingdetails = get_string('gradingdetails', 'qbehaviour_adaptive', $mark); $penalty = $qa->get_question()->penalty; if ($penalty != 0) { $gradingdetails .= $this->penalty_info($qa, $mark, $options); } $output = ''; $output .= html_writer::tag('div', get_string($class, 'question'), array('class' => 'correctness ' . $class)); $output .= html_writer::tag('div', $gradingdetails, array('class' => 'gradingdetails')); $nbtries = $gradedstep->get_behaviour_var('_try'); if ($nbtries && $isstateimprovable) { $totalpenalties = $qa->get_behaviour()->get_help_penalty($nbtries * $penalty, $options->markdp, 'totalpenalties'); $output .= $totalpenalties; } return $output; }
/** * Display the information about the penalty calculations. * @param question_attempt $qa the question attempt. * @param object $mark contains information about the current mark. * @param question_display_options $options display options. */ protected function penalty_info(question_attempt $qa, $mark, question_display_options $options) { $currentpenalty = $qa->get_question()->penalty * $qa->get_max_mark(); $totalpenalty = $currentpenalty * $qa->get_last_behaviour_var('_try', 0); if ($currentpenalty == 0) { return ''; } $output = ''; // Print details of grade adjustment due to penalties if ($mark->raw != $mark->cur) { $output .= ' ' . get_string('gradingdetailsadjustment', 'qbehaviour_adaptive', $mark); } // Print information about any new penalty, only relevant if the answer can be improved. if ($qa->get_behaviour()->is_state_improvable($qa->get_state())) { $output .= ' ' . get_string('gradingdetailspenalty', 'qbehaviour_adaptive', format_float($currentpenalty, $options->markdp)); // Print information about total penalties so far, if larger than current penalty. if ($totalpenalty > $currentpenalty) { $output .= ' ' . get_string('gradingdetailspenaltytotal', 'qbehaviour_adaptive', format_float($totalpenalty, $options->markdp)); } } return $output; }
protected function num_parts_correct(question_attempt $qa) { if ($qa->get_question()->get_num_selected_choices($qa->get_last_qt_data()) > $qa->get_question()->get_num_correct_choices()) { return get_string('toomanyselected', 'qtype_multichoice'); } return parent::num_parts_correct($qa); }
protected function get_state_string(question_attempt $qa, $showcorrectness) { if ($qa->get_question()->length > 0) { return $qa->get_state_string($showcorrectness); } // Special case handling for 'information' items. if ($qa->get_state() == question_state::$todo) { return get_string('notyetviewed', 'quiz'); } else { return get_string('viewed', 'quiz'); } }
public function subquestion(question_attempt $qa, question_display_options $options, $index, question_graded_automatically $subq) { $fieldprefix = 'sub' . $index . '_'; $fieldname = $fieldprefix . 'answer'; $response = $qa->get_last_qt_var($fieldname); $inputattributes = array( 'type' => 'radio', 'name' => $qa->get_qt_field_name($fieldname), ); if ($options->readonly) { $inputattributes['disabled'] = 'disabled'; } $result = $this->all_choices_wrapper_start(); $fraction = null; foreach ($subq->get_order($qa) as $value => $ansid) { $ans = $subq->answers[$ansid]; $inputattributes['value'] = $value; $inputattributes['id'] = $inputattributes['name'] . $value; $isselected = $subq->is_choice_selected($response, $value); if ($isselected) { $inputattributes['checked'] = 'checked'; $fraction = $ans->fraction; } else { unset($inputattributes['checked']); } $class = 'r' . ($value % 2); if ($options->correctness && $isselected) { $feedbackimg = $this->feedback_image($ans->fraction); $class .= ' ' . $this->feedback_class($ans->fraction); } else { $feedbackimg = ''; } $result .= $this->choice_wrapper_start($class); $result .= html_writer::empty_tag('input', $inputattributes); $result .= html_writer::tag('label', $subq->format_text($ans->answer, $ans->answerformat, $qa, 'question', 'answer', $ansid), array('for' => $inputattributes['id'])); $result .= $feedbackimg; if ($options->feedback && $isselected && trim($ans->feedback)) { $result .= html_writer::tag('div', $subq->format_text($ans->feedback, $ans->feedbackformat, $qa, 'question', 'answerfeedback', $ansid), array('class' => 'specificfeedback')); } $result .= $this->choice_wrapper_end(); } $result .= $this->all_choices_wrapper_end(); $feedback = array(); if ($options->feedback && $options->marks >= question_display_options::MARK_AND_MAX && $subq->maxmark > 0) { $a = new stdClass(); $a->mark = format_float($fraction * $subq->maxmark, $options->markdp); $a->max = format_float($subq->maxmark, $options->markdp); $feedback[] = html_writer::tag('div', get_string('markoutofmax', 'question', $a)); } if ($options->rightanswer) { foreach ($subq->answers as $ans) { if (question_state::graded_state_for_fraction($ans->fraction) == question_state::$gradedright) { $feedback[] = get_string('correctansweris', 'qtype_multichoice', $subq->format_text($ans->answer, $ans->answerformat, $qa, 'question', 'answer', $ansid)); break; } } } $result .= html_writer::nonempty_tag('div', implode('<br />', $feedback), array('class' => 'outcome')); return $result; }
public function get_response(question_attempt $qa) { return $qa->get_last_qt_data(); }
public function test_maxmark_beats_default_mark() { $qa = new question_attempt($this->question, $this->usageid, null, 2); $this->assertEquals(2, $qa->get_max_mark()); }
/** * Generate the display of the response history part of the question. This * is the table showing all the steps the question has been through. * * @param question_attempt $qa the question attempt to display. * @param qbehaviour_renderer $behaviouroutput the renderer to output the behaviour * specific parts. * @param qtype_renderer $qtoutput the renderer to output the question type * specific parts. * @param question_display_options $options controls what should and should not be displayed. * @return HTML fragment. */ protected function response_history(question_attempt $qa, qbehaviour_renderer $behaviouroutput, qtype_renderer $qtoutput, question_display_options $options) { if (!$options->history) { return ''; } $table = new html_table(); $table->head = array(get_string('step', 'question'), get_string('time'), get_string('action', 'question'), get_string('state', 'question')); if ($options->marks >= question_display_options::MARK_AND_MAX) { $table->head[] = get_string('marks', 'question'); } foreach ($qa->get_full_step_iterator() as $i => $step) { $stepno = $i + 1; $rowclass = ''; if ($stepno == $qa->get_num_steps()) { $rowclass = 'current'; } else { if (!empty($options->questionreviewlink)) { $url = new moodle_url($options->questionreviewlink, array('slot' => $qa->get_slot(), 'step' => $i)); $stepno = $this->output->action_link($url, $stepno, new popup_action('click', $url, 'reviewquestion', array('width' => 450, 'height' => 650)), array('title' => get_string('reviewresponse', 'question'))); } } $restrictedqa = new question_attempt_with_restricted_history($qa, $i, null); $user = new stdClass(); $user->id = $step->get_user_id(); $row = array($stepno, userdate($step->get_timecreated(), get_string('strftimedatetimeshort')), s($qa->summarise_action($step)), $restrictedqa->get_state_string($options->correctness)); if ($options->marks >= question_display_options::MARK_AND_MAX) { $row[] = $qa->format_fraction_as_mark($step->get_fraction(), $options->markdp); } $table->rowclasses[] = $rowclass; $table->data[] = $row; } return html_writer::tag('h4', get_string('responsehistory', 'question'), array('class' => 'responsehistoryheader')) . $options->extrahistorycontent . html_writer::tag('div', html_writer::table($table, true), array('class' => 'responsehistoryheader')); }
protected function prepare_response($name, question_attempt $qa, question_attempt_step $step, $context) { if (!$step->has_qt_var($name)) { return ''; } $formatoptions = new stdClass(); $formatoptions->para = false; $text = $qa->rewrite_response_pluginfile_urls($step->get_qt_var($name), $context->id, 'answer', $step); return format_text($text, $step->get_qt_var($name . 'format'), $formatoptions); }