/**
  * 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;
 }
Esempio n. 2
0
 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;
 }
 /**
  * Construct the HTML for the optional 'precheck' button, which triggers
  * a partial submit in which no penalties are imposed but only the
  * 'Use as example' test cases are run.
  * This code is identical to the 'submit_button' code in
  * qbehaviour_renderer::submit_button except for the id and name of the
  * button.
  */
 protected function precheck_button(question_attempt $qa, question_display_options $options)
 {
     if (!$qa->get_state()->is_active()) {
         return '';
         // Not sure if this can happen, but the submit button does it.
     }
     $attributes = array('type' => 'submit', 'id' => $qa->get_behaviour_field_name('precheck'), 'name' => $qa->get_behaviour_field_name('precheck'), 'value' => get_string('precheck', 'qbehaviour_adaptive_adapted_for_coderunner'), 'class' => 'submit btn');
     if ($options->readonly) {
         $attributes['disabled'] = 'disabled';
     }
     $output = html_writer::empty_tag('input', $attributes);
     if (!$options->readonly) {
         $this->page->requires->js_init_call('M.core_question_engine.init_submit_button', array($attributes['id'], $qa->get_slot()));
     }
     return $output;
 }
 protected function require_js($toreplaceid, question_attempt $qa, $readonly, $correctness)
 {
     global $PAGE;
     $jsmodule = array('name' => 'qtype_jme', 'fullpath' => '/question/type/jme/module.js', 'requires' => array(), 'strings' => array(array('enablejavascript', 'qtype_jme')));
     $topnode = 'div.que.jme#q' . $qa->get_slot();
     $appleturl = new moodle_url('/question/type/jme/jme/JME.jar');
     $question = $qa->get_question();
     // They will be converted to strings later.
     $width = $question->width;
     $height = $question->height;
     $appletoptions = $question->jmeoptions;
     if ($correctness) {
         $feedbackimage = $this->feedback_image($this->fraction_for_last_response($qa));
     } else {
         $feedbackimage = '';
     }
     $name = 'JME' . $qa->get_slot();
     $appletid = 'jme' . $qa->get_slot();
     $PAGE->requires->js_init_call('M.qtype_jme.insert_applet', array($toreplaceid, $name, $appletid, $topnode, $appleturl->out(), $feedbackimage, $readonly, "{$width}", "{$height}", $appletoptions), false, $jsmodule);
 }
Esempio n. 5
0
 /**
  * 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 require_js($toreplaceid, question_attempt $qa, $readonly, $correctness, $uniqid)
 {
     global $PAGE, $CFG;
     $marvinjsconfig = get_config('qtype_easyonamejs_options');
     $protocol = (empty($_SERVER['HTTPS']) or $_SERVER['HTTPS'] == 'off') ? 'http://' : 'https://';
     $marvinjspath = $protocol . $_SERVER['HTTP_HOST'] . $marvinjsconfig->path;
     $topnode = 'div.que.easyonamejs#q' . $qa->get_slot();
     $feedbackimage = '';
     if ($correctness) {
         $feedbackimage = $this->feedback_image($this->fraction_for_last_response($qa));
     }
     $name = 'EASYONAMEJS' . $uniqid;
     $appletid = 'easyonamejs' . $uniqid;
     $strippedanswerid = "stripped_answer" . $uniqid;
     $PAGE->requires->js_init_call('M.qtype_easyonamejs.insert_easyonamejs_applet', array($toreplaceid, $name, $appletid, $topnode, $feedbackimage, $readonly, $strippedanswerid, $CFG->wwwroot, $marvinjspath), false);
 }
Esempio n. 7
0
 public function notify_step_deleted(question_attempt_step $step, question_attempt $qa)
 {
     if (array_key_exists($qa->get_slot(), $this->attemptsadded)) {
         return;
     }
     if (($key = $this->is_step_added($step)) !== false) {
         unset($this->stepsadded[$key]);
         return;
     }
     if (($key = $this->is_step_modified($step)) !== false) {
         unset($this->stepsmodified[$key]);
     }
     $stepid = $step->get_id();
     if (empty($stepid)) {
         return;
         // Was never in the database.
     }
     $this->stepsdeleted[$stepid] = $step;
 }
Esempio n. 8
0
 /**
  * Get the postdata that needs to be sent to question/toggleflag.php to change the flag state.
  * You need to append &newstate=0/1 to this.
  * @return the post data to send.
  */
 public static function get_postdata(question_attempt $qa)
 {
     $qaid = $qa->get_database_id();
     $qubaid = $qa->get_usage_id();
     $qid = $qa->get_question()->id;
     $slot = $qa->get_slot();
     $checksum = self::get_toggle_checksum($qubaid, $qid, $qaid, $slot);
     return "qaid={$qaid}&qubaid={$qubaid}&qid={$qid}&slot={$slot}&checksum={$checksum}&sesskey=" . sesskey() . '&newstate=';
 }
 public function notify_step_added(question_attempt_step $step, question_attempt $qa, $seq)
 {
     if (array_key_exists($qa->get_slot(), $this->attemptsadded)) {
         return;
     }
     $this->stepsadded[] = array($step, $qa->get_database_id(), $seq);
 }
Esempio n. 10
0
 public function notify_metadata_modified(question_attempt $qa, $name)
 {
     if (array_key_exists($qa->get_slot(), $this->attemptsadded)) {
         return;
     }
     if ($this->is_step_added($qa->get_step(0)) !== false) {
         return;
     }
     if (isset($this->metadataadded[$qa->get_slot()][$name])) {
         return;
     }
     if (isset($this->metadatamodified[$qa->get_slot()][$name])) {
         return;
     }
     $this->metadatamodified[$qa->get_slot()][$name] = $qa;
 }
Esempio n. 11
0
 /**
  * Several behaviours need a submit button, so put the common code here.
  * The button is disabled if the question is displayed read-only.
  * @param question_display_options $options controls what should and should not be displayed.
  * @return string HTML fragment.
  */
 protected function submit_button(question_attempt $qa, question_display_options $options)
 {
     $attributes = array('type' => 'submit', 'id' => $qa->get_behaviour_field_name('submit'), 'name' => $qa->get_behaviour_field_name('submit'), 'value' => get_string('check', 'question'), 'class' => 'submit btn');
     if ($options->readonly) {
         $attributes['disabled'] = 'disabled';
     }
     $output = html_writer::empty_tag('input', $attributes);
     if (!$options->readonly) {
         $this->page->requires->js_init_call('M.core_question_engine.init_submit_button', array($attributes['id'], $qa->get_slot()));
     }
     return $output;
 }
Esempio n. 12
0
 /**
  * Returns the URL for an image
  *
  * @param object $qa Question attempt object
  * @param string $filearea File area descriptor
  * @param int $itemid Item id to get
  * @return string Output url, or null if not found
  */
 protected static function get_url_for_image(question_attempt $qa, $filearea, $itemid = 0)
 {
     $question = $qa->get_question();
     $qubaid = $qa->get_usage_id();
     $slot = $qa->get_slot();
     $fs = get_file_storage();
     if ($filearea == 'bgimage') {
         $itemid = $question->id;
     }
     $componentname = $question->qtype->plugin_name();
     $draftfiles = $fs->get_area_files($question->contextid, $componentname, $filearea, $itemid, 'id');
     if ($draftfiles) {
         foreach ($draftfiles as $file) {
             if ($file->is_directory()) {
                 continue;
             }
             $url = moodle_url::make_pluginfile_url($question->contextid, $componentname, $filearea, "{$qubaid}/{$slot}/{$itemid}", '/', $file->get_filename());
             return $url->out();
         }
     }
     return null;
 }