/** * Renders hint button. Could be used by behaviour or question renderer to avoid code duplication while rendering it. * @param hintobj object an object of a child of qtype_specific_hint class */ public function render_hint_button(question_attempt $qa, question_display_options $options, $hintobj) { $question = $qa->get_question(); $hintkey = $hintobj->hint_key(); // Render button. $attributes = array('type' => 'submit', 'id' => $qa->get_behaviour_field_name($hintkey . 'btn'), 'name' => $qa->get_behaviour_field_name($hintkey . 'btn'), 'value' => get_string('hintbtn', 'qbehaviour_adaptivehints', $hintobj->hint_description()), 'class' => 'submit btn'); if ($options->readonly) { $attributes['disabled'] = 'disabled'; } $output = html_writer::empty_tag('input', $attributes); // Cost message. if ($hintobj->penalty_response_based()) { // If penalty is response-based. // Try to get last response. $response = $qa->get_last_qt_data(); if (empty($response)) { $response = null; } $penalty = $hintobj->penalty_for_specific_hint($response); if ($penalty != 0) { $output .= $this->button_cost('withpenaltyapprox', $penalty, $options); // Note that reported penalty is approximation since user could change response in adaptive. } } else { $penalty = $hintobj->penalty_for_specific_hint(null); if ($penalty != 0) { $output .= $this->button_cost('withpenalty', $penalty, $options); } } if (!$options->readonly) { $this->page->requires->js_init_call('M.core_question_engine.init_submit_button', array($attributes['id'], $qa->get_slot())); } return $output; }
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')); }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { global $PAGE; $question = $qa->get_question(); $response = $qa->get_last_qt_data(); $questiontext = $question->format_questiontext($qa); $output = html_writer::tag('div', $questiontext, array('class' => 'qtext')); $bgimage = self::get_url_for_image($qa, 'bgimage'); $img = html_writer::empty_tag('img', array('src' => $bgimage, 'class' => 'dropbackground', 'alt' => get_string('dropbackground', 'qtype_ddimageortext'))); $droparea = html_writer::tag('div', $img, array('class' => 'droparea')); $dragimagehomes = ''; foreach ($question->choices as $groupno => $group) { $dragimagehomesgroup = ''; $orderedgroup = $question->get_ordered_choices($groupno); foreach ($orderedgroup as $choiceno => $dragimage) { $dragimageurl = self::get_url_for_image($qa, 'dragimage', $dragimage->id); $classes = array("group{$groupno}", 'draghome', "dragitemhomes{$dragimage->no}", "choice{$choiceno}"); if ($dragimage->infinite) { $classes[] = 'infinite'; } if ($dragimageurl === null) { $classes[] = 'yui3-cssfonts'; $dragimagehomesgroup .= html_writer::tag('div', $dragimage->text, array('src' => $dragimageurl, 'class' => join(' ', $classes))); } else { $dragimagehomesgroup .= html_writer::empty_tag('img', array('src' => $dragimageurl, 'alt' => $dragimage->text, 'class' => join(' ', $classes))); } } $dragimagehomes .= html_writer::tag('div', $dragimagehomesgroup, array('class' => 'dragitemgroup' . $groupno)); } $dragitemsclass = 'dragitems'; if ($options->readonly) { $dragitemsclass .= ' readonly'; } $dragitems = html_writer::tag('div', $dragimagehomes, array('class' => $dragitemsclass)); $dropzones = html_writer::tag('div', '', array('class' => 'dropzones')); $hiddens = ''; foreach ($question->places as $placeno => $place) { $varname = $question->field($placeno); list($fieldname, $html) = $this->hidden_field_for_qt_var($qa, $varname); $hiddens .= $html; $question->places[$placeno]->fieldname = $fieldname; } $output .= html_writer::tag('div', $droparea . $dragitems . $dropzones . $hiddens, array('class' => 'ddarea')); $topnode = 'div#q' . $qa->get_slot() . ' div.ddarea'; $params = array('drops' => $question->places, 'topnode' => $topnode, 'readonly' => $options->readonly); $PAGE->requires->string_for_js('blank', 'qtype_ddimageortext'); $PAGE->requires->yui_module('moodle-qtype_ddimageortext-dd', 'M.qtype_ddimageortext.init_question', array($params)); if ($qa->get_state() == question_state::$invalid) { $output .= html_writer::nonempty_tag('div', $question->get_validation_error($qa->get_last_qt_data()), array('class' => 'validationerror')); } 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(); $stemorder = $question->get_stem_order(); $response = $qa->get_last_qt_data(); $choices = $this->format_choices($question); $result = ''; $result .= html_writer::tag('div', $question->format_questiontext($qa), array('class' => 'qtext')); $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= html_writer::start_tag('table', array('class' => 'answer')); $result .= html_writer::start_tag('tbody'); $parity = 0; $i = 1; foreach ($stemorder as $key => $stemid) { $result .= html_writer::start_tag('tr', array('class' => 'r' . $parity)); $fieldname = 'sub' . $key; $result .= html_writer::tag('td', $this->format_stem_text($qa, $stemid), array('class' => 'text')); $classes = 'control'; $feedbackimage = ''; if (array_key_exists($fieldname, $response)) { $selected = $response[$fieldname]; } else { $selected = 0; } $fraction = (int) ($selected && $selected == $question->get_right_choice_for($stemid)); if ($options->correctness && $selected) { $classes .= ' ' . $this->feedback_class($fraction); $feedbackimage = $this->feedback_image($fraction); } $result .= html_writer::tag('td', html_writer::label(get_string('answer', 'qtype_match', $i), 'menu' . $qa->get_qt_field_name('sub' . $key), false, array('class' => 'accesshide')) . html_writer::select($choices, $qa->get_qt_field_name('sub' . $key), $selected, array('0' => 'choose'), array('disabled' => $options->readonly)) . ' ' . $feedbackimage, array('class' => $classes)); $result .= html_writer::end_tag('tr'); $parity = 1 - $parity; $i++; } $result .= html_writer::end_tag('tbody'); $result .= html_writer::end_tag('table'); $result .= html_writer::end_tag('div'); // Closes <div class="ablock">. if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error($response), array('class' => 'validationerror')); } return $result; }
/** * Check a request for access to a file belonging to a combined feedback field. * @param question_attempt $qa the question attempt being displayed. * @param question_display_options $options the options that control display of the question. * @param string $filearea the name of the file area. * @return bool whether access to the file should be allowed. */ protected function check_combined_feedback_file_access($qa, $options, $filearea) { $state = $qa->get_state(); if (!$state->is_finished()) { $response = $qa->get_last_qt_data(); if (!$this->is_gradable_response($response)) { return false; } list($notused, $state) = $this->grade_response($response); } return $options->feedback && $state->get_feedback_class() . 'feedback' == $filearea; }
protected function hint(question_attempt $qa, question_hint $hint) { $output = ''; $question = $qa->get_question(); $response = $qa->get_last_qt_data(); if ($hint->statewhichincorrect) { $wrongdrags = $question->get_wrong_drags($response); $wrongparts = array(); foreach ($wrongdrags as $wrongdrag) { $wrongparts[] = html_writer::nonempty_tag('span', $wrongdrag, array('class' => 'wrongpart')); } $output .= html_writer::nonempty_tag('div', get_string('followingarewrong', 'qtype_ddmarker', join(', ', $wrongparts)), array('class' => 'wrongparts')); } $output .= parent::hint($qa, $hint); return $output; }
/** * Actually, this question type abuses this method to always ouptut the * hidden fields it needs. */ public function clear_wrong(question_attempt $qa, $reallyclear = true) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); if (!empty($response) && $reallyclear) { $cleanresponse = $question->clear_wrong_from_response($response); } else { $cleanresponse = $response; } $output = ''; foreach ($question->places as $place => $group) { $fieldname = $question->field($place); if (array_key_exists($fieldname, $response)) { $value = $response[$fieldname]; } else { $value = '0'; } if (array_key_exists($fieldname, $cleanresponse)) { $cleanvalue = $cleanresponse[$fieldname]; } else { $cleanvalue = '0'; } if ($cleanvalue != $value) { $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'id' => $this->box_id($qa, 'p' . $place), 'value' => s($value))) . html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $qa->get_qt_field_name($fieldname), 'value' => s($cleanvalue))); } else { $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'id' => $this->box_id($qa, 'p' . $place), 'name' => $qa->get_qt_field_name($fieldname), 'value' => s($value))); } } return $output; }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { global $CFG, $DB; $question = $qa->get_question(); $response = $qa->get_last_qt_data(); $question->update_current_response($response); $currentresponse = $question->currentresponse; $correctresponse = $question->correctresponse; // generate fieldnames and ids // response_fieldname : 1_response_319 // response_name : q27:1_response_319 // response_id : id_q27_1_response_319 // sortable_id : id_sortable_q27_1_response_319 $response_fieldname = $question->get_response_fieldname(); $response_name = $qa->get_qt_field_name($response_fieldname); $response_id = 'id_' . preg_replace('/[^a-zA-Z0-9]+/', '_', $response_name); $sortable_id = 'id_sortable_' . $question->id; $result = ''; if ($options->readonly || $options->correctness) { // don't allow items to be dragged and dropped } else { $script = "\n"; $script .= "//<![CDATA[\n"; $script .= "if (window.\$) {\n"; // $ is an alias for jQuery $script .= " \$(function() {\n"; $script .= " \$('#{$sortable_id}').sortable({\n"; $script .= " update: function(event, ui) {\n"; $script .= " var ItemsOrder = \$(this).sortable('toArray').toString();\n"; $script .= " \$('#{$response_id}').attr('value', ItemsOrder);\n"; $script .= " },\n"; $script .= " opacity: 0.6\n"; $script .= " });\n"; $script .= " \$('#{$sortable_id}').disableSelection();\n"; $script .= " });\n"; $script .= " \$(document).ready(function() {\n"; $script .= " var ItemsOrder = \$('#{$sortable_id}').sortable('toArray').toString();\n"; $script .= " \$('#{$response_id}').attr('value', ItemsOrder);\n"; $script .= " });\n"; $script .= "}\n"; $script .= "//]]>\n"; $result .= html_writer::tag('script', $script, array('type' => 'text/javascript')); } $result .= html_writer::tag('div', $question->format_questiontext($qa), array('class' => 'qtext')); $printeditems = false; if (count($currentresponse)) { // generate ordering items foreach ($currentresponse as $position => $answerid) { if (!array_key_exists($answerid, $question->answers)) { continue; // shouldn't happen !! } if (!array_key_exists($position, $correctresponse)) { continue; // shouldn't happen !! } if ($printeditems == false) { $printeditems = true; $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= html_writer::start_tag('div', array('class' => 'answer')); $result .= html_writer::start_tag('ul', array('class' => 'sortablelist', 'id' => $sortable_id)); } if ($options->correctness) { if ($correctresponse[$position] == $answerid) { $class = 'correctposition'; $img = $this->feedback_image(1); } else { $class = 'wrongposition'; $img = $this->feedback_image(0); } $img = "{$img} "; } else { $class = 'sortableitem'; $img = ''; } // the original "id" revealed the correct order of the answers // because $answer->fraction holds the correct order number // $id = 'ordering_item_'.$answerid.'_'.intval($question->answers[$answerid]->fraction); $answer = $question->answers[$answerid]; $params = array('class' => $class, 'id' => $answer->md5key); $result .= html_writer::tag('li', $img . $answer->answer, $params); } } if ($printeditems) { $result .= html_writer::end_tag('ul'); $result .= html_writer::end_tag('div'); // answer $result .= html_writer::end_tag('div'); // ablock $result .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $response_name, 'id' => $response_id, 'value' => '')); $result .= html_writer::tag('div', '', array('style' => 'clear:both;')); } return $result; }
public function get_response(question_attempt $qa) { return $qa->get_last_qt_data(); }
/** * Output the content of the subquestion. * * @param question_attempt $qa * @param question_display_options $options * @param int $index * @param question_graded_automatically $subq * @return string */ public function subquestion(question_attempt $qa, question_display_options $options, $index, question_graded_automatically $subq) { if (!$subq instanceof qtype_multichoice_multi_question) { throw new coding_exception('Expecting subquestion of type qtype_multichoice_multi_question'); } $fieldprefix = 'sub' . $index . '_'; $fieldname = $fieldprefix . 'choice'; // Extract the responses that related to this question + strip off the prefix. $fieldprefixlen = strlen($fieldprefix); $response = []; foreach ($qa->get_last_qt_data() as $name => $val) { if (substr($name, 0, $fieldprefixlen) == $fieldprefix) { $name = substr($name, $fieldprefixlen); $response[$name] = $val; } } $basename = $qa->get_qt_field_name($fieldname); $inputattributes = array( 'type' => 'checkbox', 'value' => 1, ); if ($options->readonly) { $inputattributes['disabled'] = 'disabled'; } $result = $this->all_choices_wrapper_start(); // Calculate the total score (as we need to know if choices should be marked as 'correct' or 'partial'). $fraction = 0; foreach ($subq->get_order($qa) as $value => $ansid) { $ans = $subq->answers[$ansid]; if ($subq->is_choice_selected($response, $value)) { $fraction += $ans->fraction; } } // Display 'correct' answers as correct, if we are at 100%, otherwise mark them as 'partial'. $answerfraction = ($fraction > 0.999) ? 1.0 : 0.5; foreach ($subq->get_order($qa) as $value => $ansid) { $ans = $subq->answers[$ansid]; $name = $basename.$value; $inputattributes['name'] = $name; $inputattributes['id'] = $name; $isselected = $subq->is_choice_selected($response, $value); if ($isselected) { $inputattributes['checked'] = 'checked'; } else { unset($inputattributes['checked']); } $class = 'r' . ($value % 2); if ($options->correctness && $isselected) { $thisfrac = ($ans->fraction > 0) ? $answerfraction : 0; $feedbackimg = $this->feedback_image($thisfrac); $class .= ' ' . $this->feedback_class($thisfrac); } 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) { $correct = []; foreach ($subq->answers as $ans) { if (question_state::graded_state_for_fraction($ans->fraction) != question_state::$gradedwrong) { $correct[] = $subq->format_text($ans->answer, $ans->answerformat, $qa, 'question', 'answer', $ans->id); } } $correct = '<ul><li>'.implode('</li><li>', $correct).'</li></ul>'; $feedback[] = get_string('correctansweris', 'qtype_multichoice', $correct); } $result .= html_writer::nonempty_tag('div', implode('<br />', $feedback), array('class' => 'outcome')); return $result; }
/** * Construct the answer block area * * @param question_attempt $qa */ public function construct_answerblock($qa, $question, $options) { $stemorder = $question->get_stem_order(); $response = $qa->get_last_qt_data(); $choices = $this->format_choices($qa); $o = html_writer::start_tag('div', array('class' => 'ablock')); $o .= html_writer::start_tag('table', array('class' => 'answer')); $o .= html_writer::start_tag('tbody'); $parity = 0; $curfieldname = null; foreach ($stemorder as $key => $stemid) { $o .= html_writer::start_tag('tr', array('class' => 'r' . $parity)); $o .= html_writer::tag('td', $this->construct_stem_cell($qa, $question, $stemid), array('class' => 'text')); $classes = array('control'); $feedbackimage = ''; $curfieldname = $question->get_field_name($key); if (array_key_exists($curfieldname, $response)) { $selected = (int) $response[$curfieldname]; } else { $selected = 0; } $fraction = (int) ($selected && $selected == $question->get_right_choice_for($stemid)); if ($options->correctness && $selected) { $classes[] = $this->feedback_class($fraction); $feedbackimage = $this->feedback_image($fraction); } $dragdropclasses = $classes; $classes[] = 'hiddenifjs'; $dragdropclasses[] = 'visibleifjs'; $o .= html_writer::tag('td', $this->construct_choice_cell_select($qa, $options, $choices, $stemid, $curfieldname, $selected) . ' ' . $feedbackimage, array('class' => implode(' ', $classes))); $o .= html_writer::tag('td', $this->construct_choice_cell_dragdrop($qa, $options, $choices, $stemid, $curfieldname, $selected) . ' ' . $feedbackimage, array('class' => implode(' ', $dragdropclasses))); $o .= html_writer::end_tag('tr'); $parity = 1 - $parity; } $o .= html_writer::end_tag('tbody'); $o .= html_writer::end_tag('table'); $o .= $this->construct_available_dragdrop_choices($qa, $question); $o .= html_writer::end_tag('div'); $o .= html_writer::tag('div', '', array('class' => 'clearer')); return $o; }
public function num_parts_correct(question_attempt $qa) { $a = new stdClass(); list($a->num, $a->outof) = $qa->get_question()->get_num_parts_right($qa->get_last_qt_data()); if (is_null($a->outof)) { return ''; } else { return get_string('correctanswersno', 'qtype_omeromultichoice') . '<span class="font-weight: bold">' . $a->num . '</span>'; } }
private function get_feedback_class_image(question_attempt $qa, question_display_options $options, $key) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); $stemorder = $question->get_stem_order(); $stemid = $stemorder[$key]; $ret = new stdClass(); $ret->class = null; $ret->image = ''; $selected = $this->get_selected($question, $response, $key); $fraction = (int) ($selected && $selected == $question->get_right_choice_for($stemid)); if ($options->correctness && $selected) { $ret->class = $this->feedback_class($fraction); $ret->image = $this->feedback_image($fraction); } return $ret; }
/** * Generate the specific feedback. This has to be a stack-specific method * since the standard specific_feedback method does not get given $options. * @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. */ protected function stack_specific_feedback(question_attempt $qa, question_display_options $options) { $question = $qa->get_question(); $response = $qa->get_last_qt_data(); $feedbacktext = $question->specificfeedbackinstantiated; if (!$feedbacktext) { return ''; } $feedbacktext = stack_maths::process_display_castext($feedbacktext, $this); $feedbacktext = $question->format_text($feedbacktext, $question->specificfeedbackformat, $qa, 'qtype_stack', 'specificfeedback', $question->id); $individualfeedback = count($question->prts) == 1; if ($individualfeedback) { $overallfeedback = ''; } else { $overallfeedback = $this->overall_standard_prt_feedback($qa, $question, $response); } // Replace any PRT feedback. $allempty = true; foreach ($question->prts as $index => $prt) { $feedback = $this->prt_feedback($index, $response, $qa, $options, $individualfeedback); $allempty = $allempty && !$feedback; $feedbacktext = str_replace("[[feedback:{$index}]]", stack_maths::process_display_castext($feedback, $this), $feedbacktext); } if ($allempty && !$overallfeedback) { return ''; } return $overallfeedback . $feedbacktext; }
protected function num_parts_correct(question_attempt $qa) { $a = new stdClass(); list($a->num, $a->outof) = $qa->get_question()->get_num_parts_right($qa->get_last_qt_data()); if (is_null($a->outof)) { return ''; } else { return get_string('yougotnrightcount', 'qtype_gapfill', $a); } }
public function get_marked_gaps(question_attempt $qa, question_display_options $options) { $marked_gaps = array(); $question = $qa->get_question(); $correct_gaps = array(); foreach ($question->textfragments as $place => $fragment) { if ($place < 1) { continue; } $fieldname = $question->field($place); $rightanswer = $question->get_right_choice_for($place); if ($options->correctness or $options->numpartscorrect) { $response = $qa->get_last_qt_data(); if (array_key_exists($fieldname, $response)) { if ($question->is_correct_response($response[$fieldname], $rightanswer)) { $marked_gaps[$fieldname]['value'] = $response[$fieldname]; $marked_gaps[$fieldname]['fraction'] = 1; $correct_gaps[] = $response[$fieldname]; } else { $marked_gaps[$fieldname]['value'] = $response[$fieldname]; $marked_gaps[$fieldname]['fraction'] = 0; } } } } $arr_unique = array_unique($correct_gaps); $arr_duplicates = array_diff_assoc($correct_gaps, $arr_unique); foreach ($marked_gaps as $fieldname => $gap) { if (in_array($gap['value'], $arr_duplicates)) { $marked_gaps[$fieldname]['duplicate'] = 'true'; } else { $marked_gaps[$fieldname]['duplicate'] = 'false'; } } return $marked_gaps; }
protected function combined_feedback(question_attempt $qa) { $question = $qa->get_question(); $state = $qa->get_state(); if (!$state->is_finished()) { $response = $qa->get_last_qt_data(); if (!$qa->get_question()->is_gradable_response($response)) { return ''; } list($notused, $state) = $qa->get_question()->grade_response($response); } $feedback = ''; $field = $state->get_feedback_class() . 'feedback'; $format = $state->get_feedback_class() . 'feedbackformat'; if ($question->{$field}) { $feedback .= $question->format_text($question->{$field}, $question->{$format}, $qa, 'question', $field, $question->id); } return $feedback; }
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); }
public function formulation_and_controls(question_attempt $qa, question_display_options $options) { global $CFG, $currentanswerwithhint; require_once $CFG->dirroot . '/question/type/regexp/locallib.php'; $question = $qa->get_question(); $inputname = $qa->get_qt_field_name('answer'); $ispreview = !isset($options->attempt); $currentanswer = remove_blanks($qa->get_last_qt_var('answer')); $response = $qa->get_last_qt_data(); $laststep = $qa->get_reverse_step_iterator(); $hintadded = false; foreach ($qa->get_reverse_step_iterator() as $step) { $hintadded = $step->has_behaviour_var('_helps') === true; break; } $closest = find_closest($question, $currentanswer, $correct_response = false, $hintadded); $question->closest = $closest; $currentanswer = $closest[0]; //js script for showing / hiding regexp generated alternative sentences (for teacher only) if ($ispreview) { $alternateanswers = get_alternateanswers($question); $response = $question->get_correct_response(); $correctanswer = $response['answer']; $id = "showhidebutton"; echo html_writer::start_tag('div'); echo html_writer::empty_tag('input', array('type' => 'button', 'value' => get_string("showalternate", "qtype_regexp"), 'id' => $id, 'name' => $id)); echo html_writer::end_tag('div'); $this->page->requires->js_init_call('M.qtype_regexp.showhidealternate', array('#' . $id, '#alternateanswers'), false, array('name' => 'qtype_regexp', 'fullpath' => '/question/type/regexp/module.js', 'requires' => array('base', 'node', 'event'), 'strings' => array(array('showalternate', 'qtype_regexp'), array('hidealternate', 'qtype_regexp')))); echo html_writer::start_tag('div', array('id' => 'alternateanswers', 'style' => 'display:none;')); echo '<hr />'; if ($question->usecase) { $case = get_string('caseyes', 'qtype_regexp'); } else { $case = get_string('caseno', 'qtype_regexp'); } echo get_string('casesensitive', 'qtype_regexp') . ' : <b>' . $case . '</b><hr />'; foreach ($alternateanswers as $key => $alternateanswer) { echo get_string('answer') . ' ' . $key . ' (' . $alternateanswer['fraction'] . ') ', '<span class="regexp">' . $alternateanswer['regexp'] . '</span>'; $list = ''; foreach ($alternateanswer['answers'] as $alternate) { $list .= '<li>' . $alternate . '</li>'; } echo '<ul class="square">' . $list . '</ul>'; } echo "<hr />"; echo html_writer::end_tag('div'); } $inputattributes = array('type' => 'text', 'name' => $inputname, 'value' => $currentanswer, 'id' => $inputname, 'size' => 80); if ($options->readonly) { $inputattributes['readonly'] = 'readonly'; } $feedbackimg = ''; if ($options->correctness) { $answer = $question->get_matching_answer(array('answer' => $currentanswer)); if ($answer) { $fraction = $answer->fraction; } else { $fraction = 0; } $inputattributes['class'] = $this->feedback_class($fraction); $feedbackimg = $this->feedback_image($fraction); } $questiontext = $question->format_questiontext($qa); $placeholder = false; if (preg_match('/_____+/', $questiontext, $matches)) { $placeholder = $matches[0]; $inputattributes['size'] = round(strlen($placeholder) * 1.1); } $input = html_writer::empty_tag('input', $inputattributes) . $feedbackimg; if ($placeholder) { $questiontext = substr_replace($questiontext, $input, strpos($questiontext, $placeholder), strlen($placeholder)); } $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); if (!$placeholder) { $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= get_string('answer', 'qtype_shortanswer', html_writer::tag('div', $input, array('class' => 'answer'))); $result .= html_writer::end_tag('div'); } 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; }