Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/question/type/match/question.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 
00027 defined('MOODLE_INTERNAL') || die();
00028 
00029 
00036 class qtype_match_question extends question_graded_automatically_with_countback {
00038     public $shufflestems;
00039 
00040     public $correctfeedback;
00041     public $correctfeedbackformat;
00042     public $partiallycorrectfeedback;
00043     public $partiallycorrectfeedbackformat;
00044     public $incorrectfeedback;
00045     public $incorrectfeedbackformat;
00046 
00048     public $stems;
00050     public $choices;
00052     public $right;
00053 
00055     protected $stemorder;
00057     protected $choiceorder;
00058 
00059     public function start_attempt(question_attempt_step $step, $variant) {
00060         $this->stemorder = array_keys($this->stems);
00061         if ($this->shufflestems) {
00062             shuffle($this->stemorder);
00063         }
00064         $step->set_qt_var('_stemorder', implode(',', $this->stemorder));
00065 
00066         $choiceorder = array_keys($this->choices);
00067         shuffle($choiceorder);
00068         $step->set_qt_var('_choiceorder', implode(',', $choiceorder));
00069         $this->set_choiceorder($choiceorder);
00070     }
00071 
00072     public function apply_attempt_state(question_attempt_step $step) {
00073         $this->stemorder = explode(',', $step->get_qt_var('_stemorder'));
00074         $this->set_choiceorder(explode(',', $step->get_qt_var('_choiceorder')));
00075     }
00076 
00082     protected function set_choiceorder($choiceorder) {
00083         $this->choiceorder = array();
00084         foreach ($choiceorder as $key => $value) {
00085             $this->choiceorder[$key + 1] = $value;
00086         }
00087     }
00088 
00089     public function get_question_summary() {
00090         $question = $this->html_to_text($this->questiontext, $this->questiontextformat);
00091         $stems = array();
00092         foreach ($this->stemorder as $stemid) {
00093             $stems[] = $this->html_to_text($this->stems[$stemid], $this->stemformat[$stemid]);
00094         }
00095         $choices = array();
00096         foreach ($this->choiceorder as $choiceid) {
00097             $choices[] = $this->choices[$choiceid];
00098         }
00099         return $question . ' {' . implode('; ', $stems) . '} -> {' .
00100                 implode('; ', $choices) . '}';
00101     }
00102 
00103     public function summarise_response(array $response) {
00104         $matches = array();
00105         foreach ($this->stemorder as $key => $stemid) {
00106             if (array_key_exists($this->field($key), $response) && $response[$this->field($key)]) {
00107                 $matches[] = $this->html_to_text($this->stems[$stemid],
00108                         $this->stemformat[$stemid]) . ' -> ' .
00109                         $this->choices[$this->choiceorder[$response[$this->field($key)]]];
00110             }
00111         }
00112         if (empty($matches)) {
00113             return null;
00114         }
00115         return implode('; ', $matches);
00116     }
00117 
00118     public function classify_response(array $response) {
00119         $selectedchoices = array();
00120         foreach ($this->stemorder as $key => $stemid) {
00121             if (array_key_exists($this->field($key), $response) && $response[$this->field($key)]) {
00122                 $selectedchoices[$stemid] = $this->choiceorder[$response[$this->field($key)]];
00123             } else {
00124                 $selectedchoices[$stemid] = 0;
00125             }
00126         }
00127 
00128         $parts = array();
00129         foreach ($this->stems as $stemid => $stem) {
00130             if (empty($selectedchoices[$stemid])) {
00131                 $parts[$stemid] = question_classified_response::no_response();
00132                 continue;
00133             }
00134             $choice = $this->choices[$selectedchoices[$stemid]];
00135             $parts[$stemid] = new question_classified_response(
00136                     $selectedchoices[$stemid], $choice,
00137                     ($selectedchoices[$stemid] == $this->right[$stemid]) / count($this->stems));
00138         }
00139         return $parts;
00140     }
00141 
00142     public function clear_wrong_from_response(array $response) {
00143         foreach ($this->stemorder as $key => $stemid) {
00144             if (!array_key_exists($this->field($key), $response) ||
00145                     $response[$this->field($key)] != $this->get_right_choice_for($stemid)) {
00146                 $response[$this->field($key)] = 0;
00147             }
00148         }
00149         return $response;
00150     }
00151 
00152     public function get_num_parts_right(array $response) {
00153         $numright = 0;
00154         foreach ($this->stemorder as $key => $stemid) {
00155             $fieldname = $this->field($key);
00156             if (!array_key_exists($fieldname, $response)) {
00157                 continue;
00158             }
00159 
00160             $choice = $response[$fieldname];
00161             if ($choice && $this->choiceorder[$choice] == $this->right[$stemid]) {
00162                 $numright += 1;
00163             }
00164         }
00165         return array($numright, count($this->stemorder));
00166     }
00167 
00172     protected function field($key) {
00173         return 'sub' . $key;
00174     }
00175 
00176     public function get_expected_data() {
00177         $vars = array();
00178         foreach ($this->stemorder as $key => $notused) {
00179             $vars[$this->field($key)] = PARAM_INTEGER;
00180         }
00181         return $vars;
00182     }
00183 
00184     public function get_correct_response() {
00185         $response = array();
00186         foreach ($this->stemorder as $key => $stemid) {
00187             $response[$this->field($key)] = $this->get_right_choice_for($stemid);
00188         }
00189         return $response;
00190     }
00191 
00192     public function get_right_choice_for($stemid) {
00193         foreach ($this->choiceorder as $choicekey => $choiceid) {
00194             if ($this->right[$stemid] == $choiceid) {
00195                 return $choicekey;
00196             }
00197         }
00198     }
00199 
00200     public function is_complete_response(array $response) {
00201         $complete = true;
00202         foreach ($this->stemorder as $key => $stemid) {
00203             $complete = $complete && !empty($response[$this->field($key)]);
00204         }
00205         return $complete;
00206     }
00207 
00208     public function is_gradable_response(array $response) {
00209         foreach ($this->stemorder as $key => $stemid) {
00210             if (!empty($response[$this->field($key)])) {
00211                 return true;
00212             }
00213         }
00214         return false;
00215     }
00216 
00217     public function get_validation_error(array $response) {
00218         if ($this->is_complete_response($response)) {
00219             return '';
00220         }
00221         return get_string('pleaseananswerallparts', 'qtype_match');
00222     }
00223 
00224     public function is_same_response(array $prevresponse, array $newresponse) {
00225         foreach ($this->stemorder as $key => $notused) {
00226             $fieldname = $this->field($key);
00227             if (!question_utils::arrays_same_at_key_integer(
00228                     $prevresponse, $newresponse, $fieldname)) {
00229                 return false;
00230             }
00231         }
00232         return true;
00233     }
00234 
00235     public function grade_response(array $response) {
00236         list($right, $total) = $this->get_num_parts_right($response);
00237         $fraction = $right / $total;
00238         return array($fraction, question_state::graded_state_for_fraction($fraction));
00239     }
00240 
00241     public function compute_final_grade($responses, $totaltries) {
00242         $totalstemscore = 0;
00243         foreach ($this->stemorder as $key => $stemid) {
00244             $fieldname = $this->field($key);
00245 
00246             $lastwrongindex = -1;
00247             $finallyright = false;
00248             foreach ($responses as $i => $response) {
00249                 if (!array_key_exists($fieldname, $response) || !$response[$fieldname] ||
00250                         $this->choiceorder[$response[$fieldname]] != $this->right[$stemid]) {
00251                     $lastwrongindex = $i;
00252                     $finallyright = false;
00253                 } else {
00254                     $finallyright = true;
00255                 }
00256             }
00257 
00258             if ($finallyright) {
00259                 $totalstemscore += max(0, 1 - ($lastwrongindex + 1) * $this->penalty);
00260             }
00261         }
00262 
00263         return $totalstemscore / count($this->stemorder);
00264     }
00265 
00266     public function get_stem_order() {
00267         return $this->stemorder;
00268     }
00269 
00270     public function get_choice_order() {
00271         return $this->choiceorder;
00272     }
00273 
00274     public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) {
00275         if ($component == 'qtype_match' && $filearea == 'subquestion') {
00276             $subqid = reset($args); // itemid is sub question id
00277             return array_key_exists($subqid, $this->stems);
00278 
00279         } else if ($component == 'question' && in_array($filearea,
00280                 array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'))) {
00281             return $this->check_combined_feedback_file_access($qa, $options, $filearea);
00282 
00283         } else if ($component == 'question' && $filearea == 'hint') {
00284             return $this->check_hint_file_access($qa, $options, $args);
00285 
00286         } else {
00287             return parent::check_file_access($qa, $options, $component, $filearea,
00288                     $args, $forcedownload);
00289         }
00290     }
00291 }
 All Data Structures Namespaces Files Functions Variables Enumerations