[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 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 17 /** 18 * Question behaviour where the student can submit questions one at a 19 * time for immediate feedback. 20 * 21 * @package qbehaviour 22 * @subpackage interactive 23 * @copyright 2009 The Open University 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 27 28 defined('MOODLE_INTERNAL') || die(); 29 30 31 /** 32 * Question behaviour for the interactive model. 33 * 34 * Each question has a submit button next to it which the student can use to 35 * submit it. Once the qustion is submitted, it is not possible for the 36 * student to change their answer any more, but the student gets full feedback 37 * straight away. 38 * 39 * @copyright 2009 The Open University 40 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 41 */ 42 class qbehaviour_interactive extends question_behaviour_with_multiple_tries { 43 /** 44 * Special value used for {@link question_display_options::$readonly when 45 * we are showing the try again button to the student during an attempt. 46 * The particular number was chosen randomly. PHP will treat it the same 47 * as true, but in the renderer we reconginse it display the try again 48 * button enabled even though the rest of the question is disabled. 49 * @var integer 50 */ 51 const READONLY_EXCEPT_TRY_AGAIN = 23485299; 52 53 public function is_compatible_question(question_definition $question) { 54 return $question instanceof question_automatically_gradable; 55 } 56 57 public function get_right_answer_summary() { 58 return $this->question->get_right_answer_summary(); 59 } 60 61 /** 62 * @return bool are we are currently in the try_again state. 63 */ 64 protected function is_try_again_state() { 65 $laststep = $this->qa->get_last_step(); 66 return $this->qa->get_state()->is_active() && $laststep->has_behaviour_var('submit') && 67 $laststep->has_behaviour_var('_triesleft'); 68 } 69 70 public function adjust_display_options(question_display_options $options) { 71 // We only need different behaviour in try again states. 72 if (!$this->is_try_again_state()) { 73 parent::adjust_display_options($options); 74 return; 75 } 76 77 // Let the hint adjust the options. 78 $hint = $this->get_applicable_hint(); 79 if (!is_null($hint)) { 80 $hint->adjust_display_options($options); 81 } 82 83 // Now call the base class method, but protect some fields from being overwritten. 84 $save = clone($options); 85 parent::adjust_display_options($options); 86 $options->feedback = $save->feedback; 87 $options->numpartscorrect = $save->numpartscorrect; 88 89 // In a try-again state, everything except the try again button 90 // Should be read-only. This is a mild hack to achieve this. 91 if (!$options->readonly) { 92 $options->readonly = self::READONLY_EXCEPT_TRY_AGAIN; 93 } 94 } 95 96 public function get_applicable_hint() { 97 if (!$this->is_try_again_state()) { 98 return null; 99 } 100 return $this->question->get_hint(count($this->question->hints) - 101 $this->qa->get_last_behaviour_var('_triesleft'), $this->qa); 102 } 103 104 public function get_expected_data() { 105 if ($this->is_try_again_state()) { 106 return array( 107 'tryagain' => PARAM_BOOL, 108 ); 109 } else if ($this->qa->get_state()->is_active()) { 110 return array( 111 'submit' => PARAM_BOOL, 112 ); 113 } 114 return parent::get_expected_data(); 115 } 116 117 public function get_expected_qt_data() { 118 $hint = $this->get_applicable_hint(); 119 if (!empty($hint->clearwrong)) { 120 return $this->question->get_expected_data(); 121 } 122 return parent::get_expected_qt_data(); 123 } 124 125 public function get_state_string($showcorrectness) { 126 $state = $this->qa->get_state(); 127 if (!$state->is_active() || $state == question_state::$invalid) { 128 return parent::get_state_string($showcorrectness); 129 } 130 131 if ($this->is_try_again_state()) { 132 return get_string('notcomplete', 'qbehaviour_interactive'); 133 } else { 134 return get_string('triesremaining', 'qbehaviour_interactive', 135 $this->qa->get_last_behaviour_var('_triesleft')); 136 } 137 } 138 139 public function init_first_step(question_attempt_step $step, $variant) { 140 parent::init_first_step($step, $variant); 141 $step->set_behaviour_var('_triesleft', count($this->question->hints) + 1); 142 } 143 144 public function process_action(question_attempt_pending_step $pendingstep) { 145 if ($pendingstep->has_behaviour_var('finish')) { 146 return $this->process_finish($pendingstep); 147 } 148 if ($this->is_try_again_state()) { 149 if ($pendingstep->has_behaviour_var('tryagain')) { 150 return $this->process_try_again($pendingstep); 151 } else { 152 return question_attempt::DISCARD; 153 } 154 } else { 155 if ($pendingstep->has_behaviour_var('comment')) { 156 return $this->process_comment($pendingstep); 157 } else if ($pendingstep->has_behaviour_var('submit')) { 158 return $this->process_submit($pendingstep); 159 } else { 160 return $this->process_save($pendingstep); 161 } 162 } 163 } 164 165 public function summarise_action(question_attempt_step $step) { 166 if ($step->has_behaviour_var('comment')) { 167 return $this->summarise_manual_comment($step); 168 } else if ($step->has_behaviour_var('finish')) { 169 return $this->summarise_finish($step); 170 } else if ($step->has_behaviour_var('tryagain')) { 171 return get_string('tryagain', 'qbehaviour_interactive'); 172 } else if ($step->has_behaviour_var('submit')) { 173 return $this->summarise_submit($step); 174 } else { 175 return $this->summarise_save($step); 176 } 177 } 178 179 public function process_try_again(question_attempt_pending_step $pendingstep) { 180 $pendingstep->set_state(question_state::$todo); 181 return question_attempt::KEEP; 182 } 183 184 public function process_submit(question_attempt_pending_step $pendingstep) { 185 if ($this->qa->get_state()->is_finished()) { 186 return question_attempt::DISCARD; 187 } 188 189 if (!$this->is_complete_response($pendingstep)) { 190 $pendingstep->set_state(question_state::$invalid); 191 192 } else { 193 $triesleft = $this->qa->get_last_behaviour_var('_triesleft'); 194 $response = $pendingstep->get_qt_data(); 195 list($fraction, $state) = $this->question->grade_response($response); 196 if ($state == question_state::$gradedright || $triesleft == 1) { 197 $pendingstep->set_state($state); 198 $pendingstep->set_fraction($this->adjust_fraction($fraction, $pendingstep)); 199 200 } else { 201 $pendingstep->set_behaviour_var('_triesleft', $triesleft - 1); 202 $pendingstep->set_state(question_state::$todo); 203 } 204 $pendingstep->set_new_response_summary($this->question->summarise_response($response)); 205 } 206 return question_attempt::KEEP; 207 } 208 209 protected function adjust_fraction($fraction, question_attempt_pending_step $pendingstep) { 210 $totaltries = $this->qa->get_step(0)->get_behaviour_var('_triesleft'); 211 $triesleft = $this->qa->get_last_behaviour_var('_triesleft'); 212 213 $fraction -= ($totaltries - $triesleft) * $this->question->penalty; 214 $fraction = max($fraction, 0); 215 return $fraction; 216 } 217 218 public function process_finish(question_attempt_pending_step $pendingstep) { 219 if ($this->qa->get_state()->is_finished()) { 220 return question_attempt::DISCARD; 221 } 222 223 $response = $this->qa->get_last_qt_data(); 224 if (!$this->question->is_gradable_response($response)) { 225 $pendingstep->set_state(question_state::$gaveup); 226 227 } else { 228 list($fraction, $state) = $this->question->grade_response($response); 229 $pendingstep->set_fraction($this->adjust_fraction($fraction, $pendingstep)); 230 $pendingstep->set_state($state); 231 } 232 $pendingstep->set_new_response_summary($this->question->summarise_response($response)); 233 return question_attempt::KEEP; 234 } 235 236 public function process_save(question_attempt_pending_step $pendingstep) { 237 $status = parent::process_save($pendingstep); 238 if ($status == question_attempt::KEEP && 239 $pendingstep->get_state() == question_state::$complete) { 240 $pendingstep->set_state(question_state::$todo); 241 } 242 return $status; 243 } 244 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |