Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/question/behaviour/interactive/behaviour.php
Go to the documentation of this file.
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 
00028 defined('MOODLE_INTERNAL') || die();
00029 
00030 
00042 class qbehaviour_interactive extends question_behaviour_with_save {
00043     const IS_ARCHETYPAL = true;
00044 
00053     const READONLY_EXCEPT_TRY_AGAIN = 23485299;
00054 
00055     public function is_compatible_question(question_definition $question) {
00056         return $question instanceof question_automatically_gradable;
00057     }
00058 
00059     public function get_right_answer_summary() {
00060         return $this->question->get_right_answer_summary();
00061     }
00062 
00066     protected function is_try_again_state() {
00067         $laststep = $this->qa->get_last_step();
00068         return $this->qa->get_state()->is_active() && $laststep->has_behaviour_var('submit') &&
00069                 $laststep->has_behaviour_var('_triesleft');
00070     }
00071 
00072     public function adjust_display_options(question_display_options $options) {
00073         // We only need different behaviour in try again states.
00074         if (!$this->is_try_again_state()) {
00075             parent::adjust_display_options($options);
00076             return;
00077         }
00078 
00079         // Let the hint adjust the options.
00080         $hint = $this->get_applicable_hint();
00081         if (!is_null($hint)) {
00082             $hint->adjust_display_options($options);
00083         }
00084 
00085         // Now call the base class method, but protect some fields from being overwritten.
00086         $save = clone($options);
00087         parent::adjust_display_options($options);
00088         $options->feedback = $save->feedback;
00089         $options->numpartscorrect = $save->numpartscorrect;
00090 
00091         // In a try-again state, everything except the try again button
00092         // Should be read-only. This is a mild hack to achieve this.
00093         if (!$options->readonly) {
00094             $options->readonly = self::READONLY_EXCEPT_TRY_AGAIN;
00095         }
00096     }
00097 
00098     public function get_applicable_hint() {
00099         if (!$this->is_try_again_state()) {
00100             return null;
00101         }
00102         return $this->question->get_hint(count($this->question->hints) -
00103                 $this->qa->get_last_behaviour_var('_triesleft'), $this->qa);
00104     }
00105 
00106     public function get_expected_data() {
00107         if ($this->is_try_again_state()) {
00108             return array(
00109                 'tryagain' => PARAM_BOOL,
00110             );
00111         } else if ($this->qa->get_state()->is_active()) {
00112             return array(
00113                 'submit' => PARAM_BOOL,
00114             );
00115         }
00116         return parent::get_expected_data();
00117     }
00118 
00119     public function get_expected_qt_data() {
00120         $hint = $this->get_applicable_hint();
00121         if (!empty($hint->clearwrong)) {
00122             return $this->question->get_expected_data();
00123         }
00124         return parent::get_expected_qt_data();
00125     }
00126 
00127     public function get_state_string($showcorrectness) {
00128         $state = $this->qa->get_state();
00129         if (!$state->is_active() || $state == question_state::$invalid) {
00130             return parent::get_state_string($showcorrectness);
00131         }
00132 
00133         if ($this->is_try_again_state()) {
00134             return get_string('notcomplete', 'qbehaviour_interactive');
00135         } else {
00136             return get_string('triesremaining', 'qbehaviour_interactive',
00137                     $this->qa->get_last_behaviour_var('_triesleft'));
00138         }
00139     }
00140 
00141     public function init_first_step(question_attempt_step $step, $variant) {
00142         parent::init_first_step($step, $variant);
00143         $step->set_behaviour_var('_triesleft', count($this->question->hints) + 1);
00144     }
00145 
00146     public function process_action(question_attempt_pending_step $pendingstep) {
00147         if ($pendingstep->has_behaviour_var('finish')) {
00148             return $this->process_finish($pendingstep);
00149         }
00150         if ($this->is_try_again_state()) {
00151             if ($pendingstep->has_behaviour_var('tryagain')) {
00152                 return $this->process_try_again($pendingstep);
00153             } else {
00154                 return question_attempt::DISCARD;
00155             }
00156         } else {
00157             if ($pendingstep->has_behaviour_var('comment')) {
00158                 return $this->process_comment($pendingstep);
00159             } else if ($pendingstep->has_behaviour_var('submit')) {
00160                 return $this->process_submit($pendingstep);
00161             } else {
00162                 return $this->process_save($pendingstep);
00163             }
00164         }
00165     }
00166 
00167     public function summarise_action(question_attempt_step $step) {
00168         if ($step->has_behaviour_var('comment')) {
00169             return $this->summarise_manual_comment($step);
00170         } else if ($step->has_behaviour_var('finish')) {
00171             return $this->summarise_finish($step);
00172         } else if ($step->has_behaviour_var('tryagain')) {
00173             return get_string('tryagain', 'qbehaviour_interactive');
00174         } else if ($step->has_behaviour_var('submit')) {
00175             return $this->summarise_submit($step);
00176         } else {
00177             return $this->summarise_save($step);
00178         }
00179     }
00180 
00181     public function process_try_again(question_attempt_pending_step $pendingstep) {
00182         $pendingstep->set_state(question_state::$todo);
00183         return question_attempt::KEEP;
00184     }
00185 
00186     public function process_submit(question_attempt_pending_step $pendingstep) {
00187         if ($this->qa->get_state()->is_finished()) {
00188             return question_attempt::DISCARD;
00189         }
00190 
00191         if (!$this->is_complete_response($pendingstep)) {
00192             $pendingstep->set_state(question_state::$invalid);
00193 
00194         } else {
00195             $triesleft = $this->qa->get_last_behaviour_var('_triesleft');
00196             $response = $pendingstep->get_qt_data();
00197             list($fraction, $state) = $this->question->grade_response($response);
00198             if ($state == question_state::$gradedright || $triesleft == 1) {
00199                 $pendingstep->set_state($state);
00200                 $pendingstep->set_fraction($this->adjust_fraction($fraction, $pendingstep));
00201 
00202             } else {
00203                 $pendingstep->set_behaviour_var('_triesleft', $triesleft - 1);
00204                 $pendingstep->set_state(question_state::$todo);
00205             }
00206             $pendingstep->set_new_response_summary($this->question->summarise_response($response));
00207         }
00208         return question_attempt::KEEP;
00209     }
00210 
00211     protected function adjust_fraction($fraction, question_attempt_pending_step $pendingstep) {
00212         $totaltries = $this->qa->get_step(0)->get_behaviour_var('_triesleft');
00213         $triesleft = $this->qa->get_last_behaviour_var('_triesleft');
00214 
00215         $fraction -= ($totaltries - $triesleft) * $this->question->penalty;
00216         $fraction = max($fraction, 0);
00217         return $fraction;
00218     }
00219 
00220     public function process_finish(question_attempt_pending_step $pendingstep) {
00221         if ($this->qa->get_state()->is_finished()) {
00222             return question_attempt::DISCARD;
00223         }
00224 
00225         $response = $this->qa->get_last_qt_data();
00226         if (!$this->question->is_gradable_response($response)) {
00227             $pendingstep->set_state(question_state::$gaveup);
00228 
00229         } else {
00230             list($fraction, $state) = $this->question->grade_response($response);
00231             $pendingstep->set_fraction($this->adjust_fraction($fraction, $pendingstep));
00232             $pendingstep->set_state($state);
00233         }
00234         $pendingstep->set_new_response_summary($this->question->summarise_response($response));
00235         return question_attempt::KEEP;
00236     }
00237 
00238     public function process_save(question_attempt_pending_step $pendingstep) {
00239         $status = parent::process_save($pendingstep);
00240         if ($status == question_attempt::KEEP &&
00241                 $pendingstep->get_state() == question_state::$complete) {
00242             $pendingstep->set_state(question_state::$todo);
00243         }
00244         return $status;
00245     }
00246 }
 All Data Structures Namespaces Files Functions Variables Enumerations