|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 00038 class qbehaviour_adaptive extends question_behaviour_with_save { 00039 const IS_ARCHETYPAL = true; 00040 00041 public function is_compatible_question(question_definition $question) { 00042 return $question instanceof question_automatically_gradable; 00043 } 00044 00045 public function get_expected_data() { 00046 if ($this->qa->get_state()->is_active()) { 00047 return array('submit' => PARAM_BOOL); 00048 } 00049 return parent::get_expected_data(); 00050 } 00051 00052 public function get_state_string($showcorrectness) { 00053 $laststep = $this->qa->get_last_step(); 00054 if ($laststep->has_behaviour_var('_try')) { 00055 $state = question_state::graded_state_for_fraction( 00056 $laststep->get_behaviour_var('_rawfraction')); 00057 return $state->default_string(true); 00058 } 00059 00060 $state = $this->qa->get_state(); 00061 if ($state == question_state::$todo) { 00062 return get_string('notcomplete', 'qbehaviour_adaptive'); 00063 } else { 00064 return parent::get_state_string($showcorrectness); 00065 } 00066 } 00067 00068 public function get_right_answer_summary() { 00069 return $this->question->get_right_answer_summary(); 00070 } 00071 00072 public function adjust_display_options(question_display_options $options) { 00073 parent::adjust_display_options($options); 00074 if (!$this->qa->get_state()->is_finished() && 00075 $this->qa->get_last_behaviour_var('_try')) { 00076 $options->feedback = true; 00077 } 00078 } 00079 00080 public function process_action(question_attempt_pending_step $pendingstep) { 00081 if ($pendingstep->has_behaviour_var('comment')) { 00082 return $this->process_comment($pendingstep); 00083 } else if ($pendingstep->has_behaviour_var('finish')) { 00084 return $this->process_finish($pendingstep); 00085 } else if ($pendingstep->has_behaviour_var('submit')) { 00086 return $this->process_submit($pendingstep); 00087 } else { 00088 return $this->process_save($pendingstep); 00089 } 00090 } 00091 00092 public function summarise_action(question_attempt_step $step) { 00093 if ($step->has_behaviour_var('comment')) { 00094 return $this->summarise_manual_comment($step); 00095 } else if ($step->has_behaviour_var('finish')) { 00096 return $this->summarise_finish($step); 00097 } else if ($step->has_behaviour_var('submit')) { 00098 return $this->summarise_submit($step); 00099 } else { 00100 return $this->summarise_save($step); 00101 } 00102 } 00103 00104 public function process_save(question_attempt_pending_step $pendingstep) { 00105 $status = parent::process_save($pendingstep); 00106 $prevgrade = $this->qa->get_fraction(); 00107 if (!is_null($prevgrade)) { 00108 $pendingstep->set_fraction($prevgrade); 00109 } 00110 $pendingstep->set_state(question_state::$todo); 00111 return $status; 00112 } 00113 00114 protected function adjusted_fraction($fraction, $prevtries) { 00115 return $fraction - $this->question->penalty * $prevtries; 00116 } 00117 00118 public function process_submit(question_attempt_pending_step $pendingstep) { 00119 $status = $this->process_save($pendingstep); 00120 00121 $response = $pendingstep->get_qt_data(); 00122 if (!$this->question->is_complete_response($response)) { 00123 $pendingstep->set_state(question_state::$invalid); 00124 if ($this->qa->get_state() != question_state::$invalid) { 00125 $status = question_attempt::KEEP; 00126 } 00127 return $status; 00128 } 00129 00130 $prevstep = $this->qa->get_last_step_with_behaviour_var('_try'); 00131 $prevresponse = $prevstep->get_qt_data(); 00132 $prevtries = $this->qa->get_last_behaviour_var('_try', 0); 00133 $prevbest = $pendingstep->get_fraction(); 00134 if (is_null($prevbest)) { 00135 $prevbest = 0; 00136 } 00137 00138 if ($this->question->is_same_response($response, $prevresponse)) { 00139 return question_attempt::DISCARD; 00140 } 00141 00142 list($fraction, $state) = $this->question->grade_response($response); 00143 00144 $pendingstep->set_fraction(max($prevbest, $this->adjusted_fraction($fraction, $prevtries))); 00145 if ($prevstep->get_state() == question_state::$complete) { 00146 $pendingstep->set_state(question_state::$complete); 00147 } else if ($state == question_state::$gradedright) { 00148 $pendingstep->set_state(question_state::$complete); 00149 } else { 00150 $pendingstep->set_state(question_state::$todo); 00151 } 00152 $pendingstep->set_behaviour_var('_try', $prevtries + 1); 00153 $pendingstep->set_behaviour_var('_rawfraction', $fraction); 00154 $pendingstep->set_new_response_summary($this->question->summarise_response($response)); 00155 00156 return question_attempt::KEEP; 00157 } 00158 00159 public function process_finish(question_attempt_pending_step $pendingstep) { 00160 if ($this->qa->get_state()->is_finished()) { 00161 return question_attempt::DISCARD; 00162 } 00163 00164 $prevtries = $this->qa->get_last_behaviour_var('_try', 0); 00165 $prevbest = $this->qa->get_fraction(); 00166 if (is_null($prevbest)) { 00167 $prevbest = 0; 00168 } 00169 00170 $laststep = $this->qa->get_last_step(); 00171 $response = $laststep->get_qt_data(); 00172 if (!$this->question->is_gradable_response($response)) { 00173 $state = question_state::$gaveup; 00174 $fraction = 0; 00175 } else { 00176 00177 if ($laststep->has_behaviour_var('_try')) { 00178 // Last answer was graded, we want to regrade it. Otherwise the answer 00179 // has changed, and we are grading a new try. 00180 $prevtries -= 1; 00181 } 00182 00183 list($fraction, $state) = $this->question->grade_response($response); 00184 00185 $pendingstep->set_behaviour_var('_try', $prevtries + 1); 00186 $pendingstep->set_behaviour_var('_rawfraction', $fraction); 00187 $pendingstep->set_new_response_summary($this->question->summarise_response($response)); 00188 } 00189 00190 $pendingstep->set_state($state); 00191 $pendingstep->set_fraction(max($prevbest, $this->adjusted_fraction($fraction, $prevtries))); 00192 return question_attempt::KEEP; 00193 } 00194 00200 public function get_graded_step() { 00201 $step = $this->qa->get_last_step_with_behaviour_var('_try'); 00202 if ($step->has_behaviour_var('_try')) { 00203 return $step; 00204 } else { 00205 return null; 00206 } 00207 } 00208 00216 public function is_state_improvable(question_state $state) { 00217 return $state == question_state::$todo; 00218 } 00219 }