|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 00003 // This file is part of Moodle - http://moodle.org/ 00004 // 00005 // Moodle is free software: you can redistribute it and/or modify 00006 // it under the terms of the GNU General Public License as published by 00007 // the Free Software Foundation, either version 3 of the License, or 00008 // (at your option) any later version. 00009 // 00010 // Moodle is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00017 00027 defined('MOODLE_INTERNAL') || die(); 00028 00030 define("LESSON_PAGE_MATCHING", "5"); 00031 00032 class lesson_page_type_matching extends lesson_page { 00033 00034 protected $type = lesson_page::TYPE_QUESTION; 00035 protected $typeid = LESSON_PAGE_MATCHING; 00036 protected $typeidstring = 'matching'; 00037 protected $string = null; 00038 00039 public function get_typeid() { 00040 return $this->typeid; 00041 } 00042 public function get_typestring() { 00043 if ($this->string===null) { 00044 $this->string = get_string($this->typeidstring, 'lesson'); 00045 } 00046 return $this->string; 00047 } 00048 public function get_idstring() { 00049 return $this->typeidstring; 00050 } 00051 public function display($renderer, $attempt) { 00052 global $USER, $CFG, $PAGE; 00053 $mform = $this->make_answer_form($attempt); 00054 $data = new stdClass; 00055 $data->id = $PAGE->cm->id; 00056 $data->pageid = $this->properties->id; 00057 $mform->set_data($data); 00058 return $mform->display(); 00059 } 00060 00061 protected function make_answer_form($attempt=null) { 00062 global $USER, $CFG; 00063 // don't shuffle answers (could be an option??) 00064 $getanswers = array_slice($this->get_answers(), 2); 00065 00066 $answers = array(); 00067 foreach ($getanswers as $getanswer) { 00068 $answers[$getanswer->id] = $getanswer; 00069 } 00070 00071 $responses = array(); 00072 foreach ($answers as $answer) { 00073 // get all the response 00074 if ($answer->response != NULL) { 00075 $responses[] = trim($answer->response); 00076 } 00077 } 00078 00079 $responseoptions = array(''=>get_string('choosedots')); 00080 if (!empty($responses)) { 00081 shuffle($responses); 00082 $responses = array_unique($responses); 00083 foreach ($responses as $response) { 00084 $responseoptions[htmlspecialchars(trim($response))] = $response; 00085 } 00086 } 00087 if (isset($USER->modattempts[$this->lesson->id]) && !empty($attempt->useranswer)) { 00088 $useranswers = explode(',', $attempt->useranswer); 00089 $t = 0; 00090 } else { 00091 $useranswers = array(); 00092 } 00093 00094 $action = $CFG->wwwroot.'/mod/lesson/continue.php'; 00095 $params = array('answers'=>$answers, 'useranswers'=>$useranswers, 'responseoptions'=>$responseoptions, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); 00096 $mform = new lesson_display_answer_form_matching($action, $params); 00097 return $mform; 00098 } 00099 00100 public function create_answers($properties) { 00101 global $DB; 00102 // now add the answers 00103 $newanswer = new stdClass; 00104 $newanswer->lessonid = $this->lesson->id; 00105 $newanswer->pageid = $this->properties->id; 00106 $newanswer->timecreated = $this->properties->timecreated; 00107 00108 $answers = array(); 00109 00110 // need to add two to offset correct response and wrong response 00111 $this->lesson->maxanswers = $this->lesson->maxanswers + 2; 00112 for ($i = 0; $i < $this->lesson->maxanswers; $i++) { 00113 $answer = clone($newanswer); 00114 if (!empty($properties->answer_editor[$i]) && is_array($properties->answer_editor[$i])) { 00115 $answer->answer = $properties->answer_editor[$i]['text']; 00116 $answer->answerformat = $properties->answer_editor[$i]['format']; 00117 } 00118 if (!empty($properties->response_editor[$i]) && is_array($properties->response_editor[$i])) { 00119 $answer->response = $properties->response_editor[$i]['text']; 00120 $answer->responseformat = $properties->response_editor[$i]['format']; 00121 } 00122 00123 if (isset($properties->jumpto[$i])) { 00124 $answer->jumpto = $properties->jumpto[$i]; 00125 } 00126 if ($this->lesson->custom && isset($properties->score[$i])) { 00127 $answer->score = $properties->score[$i]; 00128 } 00129 00130 if (isset($answer->answer) && $answer->answer != '') { 00131 $answer->id = $DB->insert_record("lesson_answers", $answer); 00132 $answers[$answer->id] = new lesson_page_answer($answer); 00133 } else if ($i < 2) { 00134 $answer->id = $DB->insert_record("lesson_answers", $answer); 00135 $answers[$answer->id] = new lesson_page_answer($answer); 00136 } else { 00137 break; 00138 } 00139 } 00140 $this->answers = $answers; 00141 return $answers; 00142 } 00143 00144 public function check_answer() { 00145 global $CFG, $PAGE; 00146 00147 $formattextdefoptions = new stdClass(); 00148 $formattextdefoptions->noclean = true; 00149 $formattextdefoptions->para = false; 00150 00151 $result = parent::check_answer(); 00152 00153 $mform = $this->make_answer_form(); 00154 00155 $data = $mform->get_data(); 00156 require_sesskey(); 00157 00158 if (!$data) { 00159 redirect(new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$this->properties->id))); 00160 } 00161 00162 $response = $data->response; 00163 if (!is_array($response)) { 00164 $result->noanswer = true; 00165 return $result; 00166 } 00167 00168 $answers = $this->get_answers(); 00169 00170 $correct = array_shift($answers); 00171 $wrong = array_shift($answers); 00172 00173 foreach ($answers as $key=>$answer) { 00174 if ($answer->answer === '' or $answer->response === '') { 00175 // incomplete option! 00176 unset($answers[$key]); 00177 } 00178 } 00179 // get he users exact responses for record keeping 00180 $hits = 0; 00181 $userresponse = array(); 00182 foreach ($response as $key => $value) { 00183 foreach($answers as $answer) { 00184 if ($value === $answer->response) { 00185 $userresponse[] = $answer->id; 00186 } 00187 if ((int)$answer->id === (int)$key) { 00188 $result->studentanswer .= '<br />'.format_text($answer->answer, $answer->answerformat, $formattextdefoptions).' = '.$value; 00189 } 00190 if ((int)$answer->id === (int)$key and $value === $answer->response) { 00191 $hits++; 00192 } 00193 } 00194 } 00195 $result->userresponse = implode(",", $userresponse); 00196 00197 if ($hits == count($answers)) { 00198 $result->correctanswer = true; 00199 $result->response = format_text($correct->answer, $correct->answerformat, $formattextdefoptions); 00200 $result->answerid = $correct->id; 00201 $result->newpageid = $correct->jumpto; 00202 } else { 00203 $result->correctanswer = false; 00204 $result->response = format_text($wrong->answer, $wrong->answerformat, $formattextdefoptions); 00205 $result->answerid = $wrong->id; 00206 $result->newpageid = $wrong->jumpto; 00207 } 00208 00209 return $result; 00210 } 00211 00212 public function option_description_string() { 00213 return get_string("firstanswershould", "lesson"); 00214 } 00215 00216 public function display_answers(html_table $table) { 00217 $answers = $this->get_answers(); 00218 $options = new stdClass; 00219 $options->noclean = true; 00220 $options->para = false; 00221 $i = 1; 00222 $n = 0; 00223 00224 foreach ($answers as $answer) { 00225 if ($n < 2) { 00226 if ($answer->answer != NULL) { 00227 $cells = array(); 00228 if ($n == 0) { 00229 $cells[] = "<span class=\"label\">".get_string("correctresponse", "lesson").'</span>'; 00230 } else { 00231 $cells[] = "<span class=\"label\">".get_string("wrongresponse", "lesson").'</span>'; 00232 } 00233 $cells[] = format_text($answer->answer, $answer->answerformat, $options); 00234 $table->data[] = new html_table_row($cells); 00235 } 00236 00237 if ($n == 0) { 00238 $cells = array(); 00239 $cells[] = '<span class="label">'.get_string("correctanswerscore", "lesson")."</span>: "; 00240 $cells[] = $answer->score; 00241 $table->data[] = new html_table_row($cells); 00242 00243 $cells = array(); 00244 $cells[] = '<span class="label">'.get_string("correctanswerjump", "lesson")."</span>: "; 00245 $cells[] = $this->get_jump_name($answer->jumpto); 00246 $table->data[] = new html_table_row($cells); 00247 } elseif ($n == 1) { 00248 $cells = array(); 00249 $cells[] = '<span class="label">'.get_string("wronganswerscore", "lesson")."</span>: "; 00250 $cells[] = $answer->score; 00251 $table->data[] = new html_table_row($cells); 00252 00253 $cells = array(); 00254 $cells[] = '<span class="label">'.get_string("wronganswerjump", "lesson")."</span>: "; 00255 $cells[] = $this->get_jump_name($answer->jumpto); 00256 $table->data[] = new html_table_row($cells); 00257 } 00258 00259 if ($n === 0){ 00260 $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; 00261 } 00262 $n++; 00263 $i--; 00264 } else { 00265 $cells = array(); 00266 if ($this->lesson->custom && $answer->score > 0) { 00267 // if the score is > 0, then it is correct 00268 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n"; 00269 } else if ($this->lesson->custom) { 00270 $cells[] = '<span class="label">'.get_string("answer", "lesson")." $i</span>: \n"; 00271 } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 00272 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n"; 00273 } else { 00274 $cells[] = '<span class="label">'.get_string("answer", "lesson")." $i</span>: \n"; 00275 } 00276 $cells[] = format_text($answer->answer, $answer->answerformat, $options); 00277 $table->data[] = new html_table_row($cells); 00278 00279 $cells = array(); 00280 $cells[] = '<span class="label">'.get_string("matchesanswer", "lesson")." $i</span>: "; 00281 $cells[] = format_text($answer->response, $answer->responseformat, $options); 00282 $table->data[] = new html_table_row($cells); 00283 } 00284 $i++; 00285 } 00286 return $table; 00287 } 00296 public function update($properties) { 00297 global $DB, $PAGE; 00298 $answers = $this->get_answers(); 00299 $properties->id = $this->properties->id; 00300 $properties->lessonid = $this->lesson->id; 00301 $properties = file_postupdate_standard_editor($properties, 'contents', array('noclean'=>true, 'maxfiles'=>EDITOR_UNLIMITED_FILES, 'maxbytes'=>$PAGE->course->maxbytes), get_context_instance(CONTEXT_MODULE, $PAGE->cm->id), 'mod_lesson', 'page_contents', $properties->id); 00302 $DB->update_record("lesson_pages", $properties); 00303 00304 // need to add two to offset correct response and wrong response 00305 $this->lesson->maxanswers += 2; 00306 for ($i = 0; $i < $this->lesson->maxanswers; $i++) { 00307 if (!array_key_exists($i, $this->answers)) { 00308 $this->answers[$i] = new stdClass; 00309 $this->answers[$i]->lessonid = $this->lesson->id; 00310 $this->answers[$i]->pageid = $this->id; 00311 $this->answers[$i]->timecreated = $this->timecreated; 00312 } 00313 00314 if (!empty($properties->answer_editor[$i]) && is_array($properties->answer_editor[$i])) { 00315 $this->answers[$i]->answer = $properties->answer_editor[$i]['text']; 00316 $this->answers[$i]->answerformat = $properties->answer_editor[$i]['format']; 00317 } 00318 if (!empty($properties->response_editor[$i]) && is_array($properties->response_editor[$i])) { 00319 $this->answers[$i]->response = $properties->response_editor[$i]['text']; 00320 $this->answers[$i]->responseformat = $properties->response_editor[$i]['format']; 00321 } 00322 00323 if (isset($properties->jumpto[$i])) { 00324 $this->answers[$i]->jumpto = $properties->jumpto[$i]; 00325 } 00326 if ($this->lesson->custom && isset($properties->score[$i])) { 00327 $this->answers[$i]->score = $properties->score[$i]; 00328 } 00329 00330 // we don't need to check for isset here because properties called it's own isset method. 00331 if ($this->answers[$i]->answer != '') { 00332 if (!isset($this->answers[$i]->id)) { 00333 $this->answers[$i]->id = $DB->insert_record("lesson_answers", $this->answers[$i]); 00334 } else { 00335 $DB->update_record("lesson_answers", $this->answers[$i]->properties()); 00336 } 00337 } else if ($i < 2) { 00338 if (!isset($this->answers[$i]->id)) { 00339 $this->answers[$i]->id = $DB->insert_record("lesson_answers", $this->answers[$i]); 00340 } else { 00341 $DB->update_record("lesson_answers", $this->answers[$i]->properties()); 00342 } 00343 00344 } else if (isset($this->answers[$i]->id)) { 00345 $DB->delete_records('lesson_answers', array('id'=>$this->answers[$i]->id)); 00346 unset($this->answers[$i]); 00347 } 00348 } 00349 return true; 00350 } 00351 public function stats(array &$pagestats, $tries) { 00352 if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt 00353 $temp = $tries[$this->lesson->maxattempts - 1]; 00354 } else { 00355 // else, user attempted the question less than the max, so grab the last one 00356 $temp = end($tries); 00357 } 00358 if ($temp->correct) { 00359 if (isset($pagestats[$temp->pageid]["correct"])) { 00360 $pagestats[$temp->pageid]["correct"]++; 00361 } else { 00362 $pagestats[$temp->pageid]["correct"] = 1; 00363 } 00364 } 00365 if (isset($pagestats[$temp->pageid]["total"])) { 00366 $pagestats[$temp->pageid]["total"]++; 00367 } else { 00368 $pagestats[$temp->pageid]["total"] = 1; 00369 } 00370 return true; 00371 } 00372 public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { 00373 $answers = array(); 00374 foreach ($this->get_answers() as $answer) { 00375 $answers[$answer->id] = $answer; 00376 } 00377 $formattextdefoptions = new stdClass; 00378 $formattextdefoptions->para = false; //I'll use it widely in this page 00379 foreach ($answers as $answer) { 00380 if ($n == 0 && $useranswer != NULL && $useranswer->correct) { 00381 if ($answer->response == NULL && $useranswer != NULL) { 00382 $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); 00383 } else { 00384 $answerdata->response = $answer->response; 00385 } 00386 if ($this->lesson->custom) { 00387 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 00388 } else { 00389 $answerdata->score = get_string("receivedcredit", "lesson"); 00390 } 00391 } elseif ($n == 1 && $useranswer != NULL && !$useranswer->correct) { 00392 if ($answer->response == NULL && $useranswer != NULL) { 00393 $answerdata->response = get_string("thatsthewronganswer", "lesson"); 00394 } else { 00395 $answerdata->response = $answer->response; 00396 } 00397 if ($this->lesson->custom) { 00398 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 00399 } else { 00400 $answerdata->score = get_string("didnotreceivecredit", "lesson"); 00401 } 00402 } elseif ($n > 1) { 00403 $data = "<select disabled=\"disabled\"><option selected=\"selected\">".strip_tags(format_string($answer->answer))."</option></select>"; 00404 if ($useranswer != NULL) { 00405 $userresponse = explode(",", $useranswer->useranswer); 00406 $data .= "<select disabled=\"disabled\"><option selected=\"selected\">"; 00407 if (array_key_exists($i, $userresponse)) { 00408 $data .= strip_tags(format_string($answers[$userresponse[$i]]->response)); 00409 } 00410 $data .= "</option></select>"; 00411 } else { 00412 $data .= "<select disabled=\"disabled\"><option selected=\"selected\">".strip_tags(format_string($answer->response))."</option></select>"; 00413 } 00414 00415 if ($n == 2) { 00416 if (isset($pagestats[$this->properties->id])) { 00417 if (!array_key_exists('correct', $pagestats[$this->properties->id])) { 00418 $pagestats[$this->properties->id]["correct"] = 0; 00419 } 00420 $percent = $pagestats[$this->properties->id]["correct"] / $pagestats[$this->properties->id]["total"] * 100; 00421 $percent = round($percent, 2); 00422 $percent .= "% ".get_string("answeredcorrectly", "lesson"); 00423 } else { 00424 $percent = get_string("nooneansweredthisquestion", "lesson"); 00425 } 00426 } else { 00427 $percent = ''; 00428 } 00429 00430 $answerdata->answers[] = array($data, $percent); 00431 $i++; 00432 } 00433 $n++; 00434 $answerpage->answerdata = $answerdata; 00435 } 00436 return $answerpage; 00437 } 00438 public function get_jumps() { 00439 global $DB; 00440 // The jumps for matching question type are stored in the 1st and 2nd answer record. 00441 $jumps = array(); 00442 if ($answers = $DB->get_records("lesson_answers", array("lessonid" => $this->lesson->id, "pageid" => $this->properties->id), 'id', '*', 0, 2)) { 00443 foreach ($answers as $answer) { 00444 $jumps[] = $this->get_jump_name($answer->jumpto); 00445 } 00446 } else { 00447 $jumps[] = $this->get_jump_name($this->properties->nextpageid); 00448 } 00449 return $jumps; 00450 } 00451 } 00452 00453 class lesson_add_page_form_matching extends lesson_add_page_form_base { 00454 00455 public $qtype = 'matching'; 00456 public $qtypestring = 'matching'; 00457 00458 public function custom_definition() { 00459 00460 $this->_form->addElement('header', 'correctresponse', get_string('correctresponse', 'lesson')); 00461 $this->_form->addElement('editor', 'answer_editor[0]', get_string('correctresponse', 'lesson'), array('rows'=>'4', 'columns'=>'80'), array('noclean'=>true)); 00462 $this->add_jumpto(0, get_string('correctanswerjump','lesson'), LESSON_NEXTPAGE); 00463 $this->add_score(0, get_string("correctanswerscore", "lesson"), 1); 00464 00465 $this->_form->addElement('header', 'wrongresponse', get_string('wrongresponse', 'lesson')); 00466 $this->_form->addElement('editor', 'answer_editor[1]', get_string('wrongresponse', 'lesson'), array('rows'=>'4', 'columns'=>'80'), array('noclean'=>true)); 00467 $this->add_jumpto(1, get_string('wronganswerjump','lesson'), LESSON_THISPAGE); 00468 $this->add_score(1, get_string("wronganswerscore", "lesson"), 0); 00469 00470 for ($i = 2; $i < $this->_customdata['lesson']->maxanswers+2; $i++) { 00471 $this->_form->addElement('header', 'matchingpair'.($i-1), get_string('matchingpair', 'lesson', $i-1)); 00472 $this->add_answer($i, NULL, ($i < 4)); 00473 $this->add_response($i, get_string('matchesanswer','lesson'), ($i < 4)); 00474 } 00475 } 00476 } 00477 00478 00479 class lesson_display_answer_form_matching extends moodleform { 00480 00481 public function definition() { 00482 global $USER, $OUTPUT; 00483 $mform = $this->_form; 00484 $answers = $this->_customdata['answers']; 00485 $useranswers = $this->_customdata['useranswers']; 00486 $responseoptions = $this->_customdata['responseoptions']; 00487 $lessonid = $this->_customdata['lessonid']; 00488 $contents = $this->_customdata['contents']; 00489 00490 $mform->addElement('header', 'pageheader'); 00491 00492 $mform->addElement('html', $OUTPUT->container($contents, 'contents')); 00493 00494 $hasattempt = false; 00495 $disabled = ''; 00496 if (isset($useranswers) && !empty($useranswers)) { 00497 $hasattempt = true; 00498 $disabled = array('disabled' => 'disabled'); 00499 } 00500 00501 $options = new stdClass; 00502 $options->para = false; 00503 $options->noclean = true; 00504 00505 $mform->addElement('hidden', 'id'); 00506 $mform->setType('id', PARAM_INT); 00507 00508 $mform->addElement('hidden', 'pageid'); 00509 $mform->setType('pageid', PARAM_INT); 00510 00511 $i = 0; 00512 foreach ($answers as $answer) { 00513 $mform->addElement('html', '<div class="answeroption">'); 00514 if ($answer->response != NULL) { 00515 $responseid = 'response['.$answer->id.']'; 00516 if ($hasattempt) { 00517 $responseid = 'response_'.$answer->id; 00518 $mform->addElement('hidden', 'response['.$answer->id.']', htmlspecialchars(trim($answers[$useranswers[$i]]->response))); 00519 $mform->setType('response['.$answer->id.']', PARAM_TEXT); 00520 } 00521 $mform->addElement('select', $responseid, format_text($answer->answer,$answer->answerformat,$options), $responseoptions, $disabled); 00522 $mform->setType($responseid, PARAM_TEXT); 00523 if ($hasattempt) { 00524 $mform->setDefault($responseid, htmlspecialchars(trim($answers[$useranswers[$i]]->response))); //TODO: this is suspicious 00525 } else { 00526 $mform->setDefault($responseid, 'answeroption'); 00527 } 00528 } 00529 $mform->addElement('html', '</div>'); 00530 $i++; 00531 } 00532 if ($hasattempt) { 00533 $this->add_action_buttons(null, get_string("nextpage", "lesson")); 00534 } else { 00535 $this->add_action_buttons(null, get_string("submit", "lesson")); 00536 } 00537 } 00538 00539 }