|
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 00036 class qtype_calculatedmulti_edit_form extends question_edit_form { 00042 public $qtypeobj; 00043 public $questiondisplay; 00044 public $initialname = ''; 00045 public $reload = false; 00046 00047 public function __construct($submiturl, $question, $category, 00048 $contexts, $formeditable = true) { 00049 $this->question = $question; 00050 $this->qtypeobj = question_bank::get_qtype('calculatedmulti'); 00051 $this->reload = optional_param('reload', false, PARAM_BOOL); 00052 if (!$this->reload) { 00053 // use database data as this is first pass 00054 if (isset($this->question->id)) { 00055 // remove prefix #{..}# if exists 00056 $this->initialname = $question->name; 00057 $regs= array(); 00058 if (preg_match('~#\{([^[:space:]]*)#~', $question->name , $regs)) { 00059 $question->name = str_replace($regs[0], '', $question->name); 00060 }; 00061 } 00062 } 00063 parent::__construct($submiturl, $question, $category, $contexts, $formeditable); 00064 } 00065 00066 public function get_per_answer_fields($mform, $label, $gradeoptions, 00067 &$repeatedoptions, &$answersoption) { 00068 $repeated = array(); 00069 $repeated[] = $mform->createElement('header', 'answerhdr', $label); 00070 $repeated[] = $mform->createElement('text', 'answer', 00071 get_string('answer', 'question'), array('size' => 50)); 00072 $repeated[] = $mform->createElement('select', 'fraction', 00073 get_string('grade'), $gradeoptions); 00074 $repeated[] = $mform->createElement('editor', 'feedback', 00075 get_string('feedback', 'question'), null, $this->editoroptions); 00076 $repeatedoptions['answer']['type'] = PARAM_RAW; 00077 $repeatedoptions['fraction']['default'] = 0; 00078 $answersoption = 'answers'; 00079 00080 $mform->setType('answer', PARAM_NOTAGS); 00081 00082 $addrepeated = array(); 00083 $addrepeated[] = $mform->createElement('hidden', 'tolerance'); 00084 $addrepeated[] = $mform->createElement('hidden', 'tolerancetype', 1); 00085 $repeatedoptions['tolerance']['type'] = PARAM_NUMBER; 00086 $repeatedoptions['tolerance']['default'] = 0.01; 00087 00088 $addrepeated[] = $mform->createElement('select', 'correctanswerlength', 00089 get_string('correctanswershows', 'qtype_calculated'), range(0, 9)); 00090 $repeatedoptions['correctanswerlength']['default'] = 2; 00091 00092 $answerlengthformats = array( 00093 '1' => get_string('decimalformat', 'qtype_numerical'), 00094 '2' => get_string('significantfiguresformat', 'qtype_calculated') 00095 ); 00096 $addrepeated[] = $mform->createElement('select', 'correctanswerformat', 00097 get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats); 00098 array_splice($repeated, 3, 0, $addrepeated); 00099 $repeated[1]->setLabel('...<strong>{={x}+..}</strong>...'); 00100 00101 return $repeated; 00102 } 00103 00104 protected function definition_inner($mform) { 00105 00106 $label = get_string('sharedwildcards', 'qtype_calculated'); 00107 $mform->addElement('hidden', 'initialcategory', 1); 00108 $mform->addElement('hidden', 'reload', 1); 00109 $mform->setType('initialcategory', PARAM_INT); 00110 00111 $html2 = ''; 00112 $mform->insertElementBefore( 00113 $mform->createElement('static', 'listcategory', $label, $html2), 'name'); 00114 if (isset($this->question->id)) { 00115 $mform->insertElementBefore($mform->createElement('static', 'initialname', 00116 get_string('questionstoredname', 'qtype_calculated'), 00117 $this->initialname), 'name'); 00118 }; 00119 $addfieldsname = 'updatecategory'; 00120 $addstring = get_string('updatecategory', 'qtype_calculated'); 00121 $mform->registerNoSubmitButton($addfieldsname); 00122 $this->editasmultichoice = 1; 00123 00124 $mform->insertElementBefore( 00125 $mform->createElement('submit', $addfieldsname, $addstring), 'listcategory'); 00126 $mform->registerNoSubmitButton('createoptionbutton'); 00127 $mform->addElement('hidden', 'multichoice', $this->editasmultichoice); 00128 $mform->setType('multichoice', PARAM_INT); 00129 00130 $menu = array(get_string('answersingleno', 'qtype_multichoice'), 00131 get_string('answersingleyes', 'qtype_multichoice')); 00132 $mform->addElement('select', 'single', 00133 get_string('answerhowmany', 'qtype_multichoice'), $menu); 00134 $mform->setDefault('single', 1); 00135 00136 $mform->addElement('advcheckbox', 'shuffleanswers', 00137 get_string('shuffleanswers', 'qtype_multichoice'), null, null, array(0, 1)); 00138 $mform->addHelpButton('shuffleanswers', 'shuffleanswers', 'qtype_multichoice'); 00139 $mform->setDefault('shuffleanswers', 1); 00140 00141 $numberingoptions = question_bank::get_qtype('multichoice')->get_numbering_styles(); 00142 $mform->addElement('select', 'answernumbering', 00143 get_string('answernumbering', 'qtype_multichoice'), $numberingoptions); 00144 $mform->setDefault('answernumbering', 'abc'); 00145 00146 $this->add_per_answer_fields($mform, get_string('choiceno', 'qtype_multichoice', '{no}'), 00147 question_bank::fraction_options_full(), max(5, QUESTION_NUMANS_START)); 00148 00149 $repeated = array(); 00150 // if ($this->editasmultichoice == 1) { 00151 $nounits = optional_param('nounits', 1, PARAM_INT); 00152 $mform->addElement('hidden', 'nounits', $nounits); 00153 $mform->setType('nounits', PARAM_INT); 00154 $mform->setConstants(array('nounits'=>$nounits)); 00155 for ($i = 0; $i < $nounits; $i++) { 00156 $mform->addElement('hidden', 'unit'."[$i]", 00157 optional_param("unit[$i]", '', PARAM_NOTAGS)); 00158 $mform->setType('unit'."[$i]", PARAM_NOTAGS); 00159 $mform->addElement('hidden', 'multiplier'."[$i]", 00160 optional_param("multiplier[$i]", '', PARAM_NUMBER)); 00161 $mform->setType("multiplier[$i]", PARAM_NUMBER); 00162 } 00163 00164 $this->add_combined_feedback_fields(true); 00165 $mform->disabledIf('shownumcorrect', 'single', 'eq', 1); 00166 00167 $this->add_interactive_settings(true, true); 00168 00169 //hidden elements 00170 $mform->addElement('hidden', 'synchronize', ''); 00171 $mform->setType('synchronize', PARAM_INT); 00172 if (isset($this->question->options) && isset($this->question->options->synchronize)) { 00173 $mform->setDefault('synchronize', $this->question->options->synchronize); 00174 } else { 00175 $mform->setDefault('synchronize', 0); 00176 } 00177 $mform->addElement('hidden', 'wizard', 'datasetdefinitions'); 00178 $mform->setType('wizard', PARAM_ALPHA); 00179 } 00180 00181 public function data_preprocessing($question) { 00182 $question = parent::data_preprocessing($question); 00183 $question = $this->data_preprocessing_answers($question, true); 00184 $question = $this->data_preprocessing_combined_feedback($question, true); 00185 $question = $this->data_preprocessing_hints($question, true, true); 00186 00187 if (isset($question->options)) { 00188 $question->synchronize = $question->options->synchronize; 00189 $question->single = $question->options->single; 00190 $question->answernumbering = $question->options->answernumbering; 00191 $question->shuffleanswers = $question->options->shuffleanswers; 00192 } 00193 00194 return $question; 00195 } 00196 00197 protected function data_preprocessing_answers($question) { 00198 $question = parent::data_preprocessing_answers($question); 00199 if (empty($question->options->answers)) { 00200 return $question; 00201 } 00202 00203 $key = 0; 00204 foreach ($question->options->answers as $answer) { 00205 // See comment in the parent method about this hack. 00206 unset($this->_form->_defaultValues["tolerance[$key]"]); 00207 unset($this->_form->_defaultValues["tolerancetype[$key]"]); 00208 unset($this->_form->_defaultValues["correctanswerlength[$key]"]); 00209 unset($this->_form->_defaultValues["correctanswerformat[$key]"]); 00210 00211 $question->tolerance[$key] = $answer->tolerance; 00212 $question->tolerancetype[$key] = $answer->tolerancetype; 00213 $question->correctanswerlength[$key] = $answer->correctanswerlength; 00214 $question->correctanswerformat[$key] = $answer->correctanswerformat; 00215 $key++; 00216 } 00217 00218 return $question; 00219 } 00220 00221 public function validation($data, $files) { 00222 $errors = parent::validation($data, $files); 00223 00224 //verifying for errors in {=...} in question text; 00225 $qtext = ''; 00226 $qtextremaining = $data['questiontext']['text']; 00227 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']); 00228 foreach ($possibledatasets as $name => $value) { 00229 $qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining); 00230 } 00231 00232 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) { 00233 $qtextsplits = explode($regs1[0], $qtextremaining, 2); 00234 $qtext = $qtext.$qtextsplits[0]; 00235 $qtextremaining = $qtextsplits[1]; 00236 if (!empty($regs1[1]) && $formulaerrors = 00237 qtype_calculated_find_formula_errors($regs1[1])) { 00238 if (!isset($errors['questiontext'])) { 00239 $errors['questiontext'] = $formulaerrors.':'.$regs1[1]; 00240 } else { 00241 $errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1]; 00242 } 00243 } 00244 } 00245 $answers = $data['answer']; 00246 $answercount = 0; 00247 $maxgrade = false; 00248 $possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']); 00249 $mandatorydatasets = array(); 00250 foreach ($answers as $key => $answer) { 00251 $mandatorydatasets += $this->qtypeobj->find_dataset_names($answer); 00252 } 00253 if (count($mandatorydatasets) == 0) { 00254 foreach ($answers as $key => $answer) { 00255 $errors['answer['.$key.']'] = 00256 get_string('atleastonewildcard', 'qtype_calculated'); 00257 } 00258 } 00259 if ($data['multichoice'] == 1) { 00260 foreach ($answers as $key => $answer) { 00261 $trimmedanswer = trim($answer); 00262 if ($trimmedanswer != '' || $answercount == 0) { 00263 //verifying for errors in {=...} in answer text; 00264 $qanswer = ''; 00265 $qanswerremaining = $trimmedanswer; 00266 $possibledatasets = $this->qtypeobj->find_dataset_names($trimmedanswer); 00267 foreach ($possibledatasets as $name => $value) { 00268 $qanswerremaining = str_replace('{'.$name.'}', '1', $qanswerremaining); 00269 } 00270 00271 while (preg_match('~\{=([^[:space:]}]*)}~', $qanswerremaining, $regs1)) { 00272 $qanswersplits = explode($regs1[0], $qanswerremaining, 2); 00273 $qanswer = $qanswer . $qanswersplits[0]; 00274 $qanswerremaining = $qanswersplits[1]; 00275 if (!empty($regs1[1]) && $formulaerrors = 00276 qtype_calculated_find_formula_errors($regs1[1])) { 00277 if (!isset($errors['answer['.$key.']'])) { 00278 $errors['answer['.$key.']'] = $formulaerrors.':'.$regs1[1]; 00279 } else { 00280 $errors['answer['.$key.']'] .= '<br/>'.$formulaerrors.':'.$regs1[1]; 00281 } 00282 } 00283 } 00284 } 00285 if ($trimmedanswer != '') { 00286 if ('2' == $data['correctanswerformat'][$key] && 00287 '0' == $data['correctanswerlength'][$key]) { 00288 $errors['correctanswerlength['.$key.']'] = 00289 get_string('zerosignificantfiguresnotallowed', 'qtype_calculated'); 00290 } 00291 if (!is_numeric($data['tolerance'][$key])) { 00292 $errors['tolerance['.$key.']'] = 00293 get_string('mustbenumeric', 'qtype_calculated'); 00294 } 00295 if ($data['fraction'][$key] == 1) { 00296 $maxgrade = true; 00297 } 00298 00299 $answercount++; 00300 } 00301 //check grades 00302 $totalfraction = 0; 00303 $maxfraction = 0; 00304 if ($answer != '') { 00305 if ($data['fraction'][$key] > 0) { 00306 $totalfraction += $data['fraction'][$key]; 00307 } 00308 if ($data['fraction'][$key] > $maxfraction) { 00309 $maxfraction = $data['fraction'][$key]; 00310 } 00311 } 00312 } 00313 if ($answercount == 0) { 00314 $errors['answer[0]'] = get_string('notenoughanswers', 'qtype_multichoice', 2); 00315 $errors['answer[1]'] = get_string('notenoughanswers', 'qtype_multichoice', 2); 00316 } else if ($answercount == 1) { 00317 $errors['answer[1]'] = get_string('notenoughanswers', 'qtype_multichoice', 2); 00318 00319 } 00320 00322 if ($data['single']) { 00323 if ($maxfraction > 0.999) { 00324 $maxfraction = $maxfraction * 100; 00325 $errors['fraction[0]'] = 00326 get_string('errfractionsnomax', 'qtype_multichoice', $maxfraction); 00327 } 00328 } else { 00329 $totalfraction = round($totalfraction, 2); 00330 if ($totalfraction != 1) { 00331 $totalfraction = $totalfraction * 100; 00332 $errors['fraction[0]'] = 00333 get_string('errfractionsaddwrong', 'qtype_multichoice', $totalfraction); 00334 } 00335 } 00336 00337 if ($answercount == 0) { 00338 $errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated'); 00339 } 00340 if ($maxgrade == false) { 00341 $errors['fraction[0]'] = get_string('fractionsnomax', 'question'); 00342 } 00343 00344 } 00345 return $errors; 00346 } 00347 00348 public function qtype() { 00349 return 'calculatedmulti'; 00350 } 00351 }