[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 3 // This file is part of Moodle - http://moodle.org/ 4 // 5 // Moodle is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // Moodle is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 17 18 /** 19 * Multichoice 20 * 21 * @package mod_lesson 22 * @copyright 2009 Sam Hemelryk 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 **/ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 /** Multichoice question type */ 29 define("LESSON_PAGE_MULTICHOICE", "3"); 30 31 class lesson_page_type_multichoice extends lesson_page { 32 33 protected $type = lesson_page::TYPE_QUESTION; 34 protected $typeidstring = 'multichoice'; 35 protected $typeid = LESSON_PAGE_MULTICHOICE; 36 protected $string = null; 37 38 public function get_typeid() { 39 return $this->typeid; 40 } 41 public function get_typestring() { 42 if ($this->string===null) { 43 $this->string = get_string($this->typeidstring, 'lesson'); 44 } 45 return $this->string; 46 } 47 public function get_idstring() { 48 return $this->typeidstring; 49 } 50 51 /** 52 * Gets an array of the jumps used by the answers of this page 53 * 54 * @return array 55 */ 56 public function get_jumps() { 57 global $DB; 58 $jumps = array(); 59 if ($answers = $this->get_answers()) { 60 foreach ($answers as $answer) { 61 if ($answer->answer === '') { 62 // show only jumps for real branches (==have description) 63 continue; 64 } 65 $jumps[] = $this->get_jump_name($answer->jumpto); 66 } 67 } else { 68 // We get here is the lesson was created on a Moodle 1.9 site and 69 // the lesson contains question pages without any answers. 70 $jumps[] = $this->get_jump_name($this->properties->nextpageid); 71 } 72 return $jumps; 73 } 74 75 public function get_used_answers() { 76 $answers = $this->get_answers(); 77 foreach ($answers as $key=>$answer) { 78 if ($answer->answer === '') { 79 unset($answers[$key]); 80 } else { 81 $answers[$key] = parent::rewrite_answers_urls($answer); 82 } 83 } 84 return $answers; 85 } 86 87 public function display($renderer, $attempt) { 88 global $CFG, $PAGE; 89 $answers = $this->get_used_answers(); 90 shuffle($answers); 91 $action = $CFG->wwwroot.'/mod/lesson/continue.php'; 92 $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents(), 'attempt'=>$attempt); 93 if ($this->properties->qoption) { 94 $mform = new lesson_display_answer_form_multichoice_multianswer($action, $params); 95 } else { 96 $mform = new lesson_display_answer_form_multichoice_singleanswer($action, $params); 97 } 98 $data = new stdClass; 99 $data->id = $PAGE->cm->id; 100 $data->pageid = $this->properties->id; 101 $mform->set_data($data); 102 return $mform->display(); 103 } 104 105 public function check_answer() { 106 global $DB, $CFG, $PAGE; 107 $result = parent::check_answer(); 108 109 $formattextdefoptions = new stdClass(); 110 $formattextdefoptions->noclean = true; 111 $formattextdefoptions->para = false; 112 113 $answers = $this->get_used_answers(); 114 shuffle($answers); 115 $action = $CFG->wwwroot.'/mod/lesson/continue.php'; 116 $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); 117 if ($this->properties->qoption) { 118 $mform = new lesson_display_answer_form_multichoice_multianswer($action, $params); 119 } else { 120 $mform = new lesson_display_answer_form_multichoice_singleanswer($action, $params); 121 } 122 $data = $mform->get_data(); 123 require_sesskey(); 124 125 if (!$data) { 126 redirect(new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$this->properties->id))); 127 } 128 129 if ($this->properties->qoption) { 130 // Multianswer allowed, user's answer is an array 131 132 if (empty($data->answer) || !is_array($data->answer)) { 133 $result->noanswer = true; 134 return $result; 135 } 136 137 $studentanswers = array(); 138 foreach ($data->answer as $key=>$value) { 139 $studentanswers[] = (int)$key; 140 } 141 142 // get what the user answered 143 $result->userresponse = implode(",", $studentanswers); 144 145 // get the answers in a set order, the id order 146 $answers = $this->get_used_answers(); 147 $ncorrect = 0; 148 $nhits = 0; 149 $responses = array(); 150 $correctanswerid = 0; 151 $wronganswerid = 0; 152 // store student's answers for displaying on feedback page 153 $result->studentanswer = ''; 154 foreach ($answers as $answer) { 155 foreach ($studentanswers as $answerid) { 156 if ($answerid == $answer->id) { 157 $result->studentanswer .= '<br />'.format_text($answer->answer, $answer->answerformat, $formattextdefoptions); 158 if (trim(strip_tags($answer->response))) { 159 $responses[$answerid] = format_text($answer->response, $answer->responseformat, $formattextdefoptions); 160 } 161 } 162 } 163 } 164 $correctpageid = null; 165 $wrongpageid = null; 166 // this is for custom scores. If score on answer is positive, it is correct 167 if ($this->lesson->custom) { 168 $ncorrect = 0; 169 $nhits = 0; 170 foreach ($answers as $answer) { 171 if ($answer->score > 0) { 172 $ncorrect++; 173 174 foreach ($studentanswers as $answerid) { 175 if ($answerid == $answer->id) { 176 $nhits++; 177 } 178 } 179 // save the first jumpto page id, may be needed!... 180 if (!isset($correctpageid)) { 181 // leave in its "raw" state - will converted into a proper page id later 182 $correctpageid = $answer->jumpto; 183 } 184 // save the answer id for scoring 185 if ($correctanswerid == 0) { 186 $correctanswerid = $answer->id; 187 } 188 } else { 189 // save the first jumpto page id, may be needed!... 190 if (!isset($wrongpageid)) { 191 // leave in its "raw" state - will converted into a proper page id later 192 $wrongpageid = $answer->jumpto; 193 } 194 // save the answer id for scoring 195 if ($wronganswerid == 0) { 196 $wronganswerid = $answer->id; 197 } 198 } 199 } 200 } else { 201 foreach ($answers as $answer) { 202 if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 203 $ncorrect++; 204 foreach ($studentanswers as $answerid) { 205 if ($answerid == $answer->id) { 206 $nhits++; 207 } 208 } 209 // save the first jumpto page id, may be needed!... 210 if (!isset($correctpageid)) { 211 // leave in its "raw" state - will converted into a proper page id later 212 $correctpageid = $answer->jumpto; 213 } 214 // save the answer id for scoring 215 if ($correctanswerid == 0) { 216 $correctanswerid = $answer->id; 217 } 218 } else { 219 // save the first jumpto page id, may be needed!... 220 if (!isset($wrongpageid)) { 221 // leave in its "raw" state - will converted into a proper page id later 222 $wrongpageid = $answer->jumpto; 223 } 224 // save the answer id for scoring 225 if ($wronganswerid == 0) { 226 $wronganswerid = $answer->id; 227 } 228 } 229 } 230 } 231 if ((count($studentanswers) == $ncorrect) and ($nhits == $ncorrect)) { 232 $result->correctanswer = true; 233 $result->response = implode('<br />', $responses); 234 $result->newpageid = $correctpageid; 235 $result->answerid = $correctanswerid; 236 } else { 237 $result->response = implode('<br />', $responses); 238 $result->newpageid = $wrongpageid; 239 $result->answerid = $wronganswerid; 240 } 241 } else { 242 // only one answer allowed 243 if (!isset($data->answerid) || (empty($data->answerid) && !is_int($data->answerid))) { 244 $result->noanswer = true; 245 return $result; 246 } 247 $result->answerid = $data->answerid; 248 if (!$answer = $DB->get_record("lesson_answers", array("id" => $result->answerid))) { 249 print_error("Continue: answer record not found"); 250 } 251 $answer = parent::rewrite_answers_urls($answer); 252 if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 253 $result->correctanswer = true; 254 } 255 if ($this->lesson->custom) { 256 if ($answer->score > 0) { 257 $result->correctanswer = true; 258 } else { 259 $result->correctanswer = false; 260 } 261 } 262 $result->newpageid = $answer->jumpto; 263 $result->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); 264 $result->userresponse = format_text($answer->answer, $answer->answerformat, $formattextdefoptions); 265 $result->studentanswer = $result->userresponse; 266 } 267 return $result; 268 } 269 270 public function option_description_string() { 271 if ($this->properties->qoption) { 272 return " - ".get_string("multianswer", "lesson"); 273 } 274 return parent::option_description_string(); 275 } 276 277 public function display_answers(html_table $table) { 278 $answers = $this->get_used_answers(); 279 $options = new stdClass; 280 $options->noclean = true; 281 $options->para = false; 282 $i = 1; 283 foreach ($answers as $answer) { 284 $answer = parent::rewrite_answers_urls($answer); 285 $cells = array(); 286 if ($this->lesson->custom && $answer->score > 0) { 287 // if the score is > 0, then it is correct 288 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n"; 289 } else if ($this->lesson->custom) { 290 $cells[] = '<span class="label">'.get_string("answer", "lesson")." $i</span>: \n"; 291 } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 292 // underline correct answers 293 $cells[] = '<span class="correct">'.get_string("answer", "lesson")." $i</span>: \n"; 294 } else { 295 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n"; 296 } 297 $cells[] = format_text($answer->answer, $answer->answerformat, $options); 298 $table->data[] = new html_table_row($cells); 299 300 $cells = array(); 301 $cells[] = "<span class=\"label\">".get_string("response", "lesson")." $i</span>"; 302 $cells[] = format_text($answer->response, $answer->responseformat, $options); 303 $table->data[] = new html_table_row($cells); 304 305 $cells = array(); 306 $cells[] = "<span class=\"label\">".get_string("score", "lesson").'</span>'; 307 $cells[] = $answer->score; 308 $table->data[] = new html_table_row($cells); 309 310 $cells = array(); 311 $cells[] = "<span class=\"label\">".get_string("jump", "lesson").'</span>'; 312 $cells[] = $this->get_jump_name($answer->jumpto); 313 $table->data[] = new html_table_row($cells); 314 if ($i === 1){ 315 $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; 316 } 317 $i++; 318 } 319 return $table; 320 } 321 public function stats(array &$pagestats, $tries) { 322 if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt 323 $temp = $tries[$this->lesson->maxattempts - 1]; 324 } else { 325 // else, user attempted the question less than the max, so grab the last one 326 $temp = end($tries); 327 } 328 if ($this->properties->qoption) { 329 $userresponse = explode(",", $temp->useranswer); 330 foreach ($userresponse as $response) { 331 if (isset($pagestats[$temp->pageid][$response])) { 332 $pagestats[$temp->pageid][$response]++; 333 } else { 334 $pagestats[$temp->pageid][$response] = 1; 335 } 336 } 337 } else { 338 if (isset($pagestats[$temp->pageid][$temp->answerid])) { 339 $pagestats[$temp->pageid][$temp->answerid]++; 340 } else { 341 $pagestats[$temp->pageid][$temp->answerid] = 1; 342 } 343 } 344 if (isset($pagestats[$temp->pageid]["total"])) { 345 $pagestats[$temp->pageid]["total"]++; 346 } else { 347 $pagestats[$temp->pageid]["total"] = 1; 348 } 349 return true; 350 } 351 352 public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { 353 $answers = $this->get_used_answers(); 354 $formattextdefoptions = new stdClass; 355 $formattextdefoptions->para = false; //I'll use it widely in this page 356 357 foreach ($answers as $answer) { 358 if ($this->properties->qoption) { 359 if ($useranswer == null) { 360 $userresponse = array(); 361 } else { 362 $userresponse = explode(",", $useranswer->useranswer); 363 } 364 if (in_array($answer->id, $userresponse)) { 365 // make checked 366 $data = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />"; 367 if (!isset($answerdata->response)) { 368 if ($answer->response == null) { 369 if ($useranswer->correct) { 370 $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); 371 } else { 372 $answerdata->response = get_string("thatsthewronganswer", "lesson"); 373 } 374 } else { 375 $answerdata->response = $answer->response; 376 } 377 } 378 if (!isset($answerdata->score)) { 379 if ($this->lesson->custom) { 380 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 381 } elseif ($useranswer->correct) { 382 $answerdata->score = get_string("receivedcredit", "lesson"); 383 } else { 384 $answerdata->score = get_string("didnotreceivecredit", "lesson"); 385 } 386 } 387 } else { 388 // unchecked 389 $data = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />"; 390 } 391 if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { 392 $data = "<div class=highlight>".$data.' '.format_text($answer->answer,$answer->answerformat,$formattextdefoptions)."</div>"; 393 } else { 394 $data .= format_text($answer->answer,$answer->answerformat,$formattextdefoptions); 395 } 396 } else { 397 if ($useranswer != null and $answer->id == $useranswer->answerid) { 398 // make checked 399 $data = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />"; 400 if ($answer->response == null) { 401 if ($useranswer->correct) { 402 $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); 403 } else { 404 $answerdata->response = get_string("thatsthewronganswer", "lesson"); 405 } 406 } else { 407 $answerdata->response = $answer->response; 408 } 409 if ($this->lesson->custom) { 410 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 411 } elseif ($useranswer->correct) { 412 $answerdata->score = get_string("receivedcredit", "lesson"); 413 } else { 414 $answerdata->score = get_string("didnotreceivecredit", "lesson"); 415 } 416 } else { 417 // unchecked 418 $data = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />"; 419 } 420 if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { 421 $data = "<div class=\"highlight\">".$data.' '.format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."</div>"; 422 } else { 423 $data .= format_text($answer->answer,$answer->answerformat,$formattextdefoptions); 424 } 425 } 426 if (isset($pagestats[$this->properties->id][$answer->id])) { 427 $percent = $pagestats[$this->properties->id][$answer->id] / $pagestats[$this->properties->id]["total"] * 100; 428 $percent = round($percent, 2); 429 $percent .= "% ".get_string("checkedthisone", "lesson"); 430 } else { 431 $percent = get_string("noonecheckedthis", "lesson"); 432 } 433 434 $answerdata->answers[] = array($data, $percent); 435 $answerpage->answerdata = $answerdata; 436 } 437 return $answerpage; 438 } 439 } 440 441 442 class lesson_add_page_form_multichoice extends lesson_add_page_form_base { 443 444 public $qtype = 'multichoice'; 445 public $qtypestring = 'multichoice'; 446 447 public function custom_definition() { 448 449 $this->_form->addElement('checkbox', 'qoption', get_string('options', 'lesson'), get_string('multianswer', 'lesson')); 450 $this->_form->setDefault('qoption', 0); 451 $this->_form->addHelpButton('qoption', 'multianswer', 'lesson'); 452 453 for ($i = 0; $i < $this->_customdata['lesson']->maxanswers; $i++) { 454 $this->_form->addElement('header', 'answertitle'.$i, get_string('answer').' '.($i+1)); 455 $this->add_answer($i, null, ($i<2)); 456 $this->add_response($i); 457 $this->add_jumpto($i, null, ($i == 0 ? LESSON_NEXTPAGE : LESSON_THISPAGE)); 458 $this->add_score($i, null, ($i===0)?1:0); 459 } 460 } 461 } 462 463 class lesson_display_answer_form_multichoice_singleanswer extends moodleform { 464 465 public function definition() { 466 global $USER, $OUTPUT; 467 $mform = $this->_form; 468 $answers = $this->_customdata['answers']; 469 $lessonid = $this->_customdata['lessonid']; 470 $contents = $this->_customdata['contents']; 471 if (array_key_exists('attempt', $this->_customdata)) { 472 $attempt = $this->_customdata['attempt']; 473 } else { 474 $attempt = new stdClass(); 475 $attempt->answerid = null; 476 } 477 478 $mform->addElement('header', 'pageheader'); 479 480 $mform->addElement('html', $OUTPUT->container($contents, 'contents')); 481 482 $hasattempt = false; 483 $disabled = ''; 484 if (isset($USER->modattempts[$lessonid]) && !empty($USER->modattempts[$lessonid])) { 485 $hasattempt = true; 486 $disabled = array('disabled' => 'disabled'); 487 } 488 489 $options = new stdClass; 490 $options->para = false; 491 $options->noclean = true; 492 493 $mform->addElement('hidden', 'id'); 494 $mform->setType('id', PARAM_INT); 495 496 $mform->addElement('hidden', 'pageid'); 497 $mform->setType('pageid', PARAM_INT); 498 499 $i = 0; 500 foreach ($answers as $answer) { 501 $mform->addElement('html', '<div class="answeroption">'); 502 $answer->answer = preg_replace('#>$#', '> ', $answer->answer); 503 $mform->addElement('radio','answerid',null,format_text($answer->answer, $answer->answerformat, $options),$answer->id, $disabled); 504 $mform->setType('answer'.$i, PARAM_INT); 505 if ($hasattempt && $answer->id == $USER->modattempts[$lessonid]->answerid) { 506 $mform->setDefault('answerid', $USER->modattempts[$lessonid]->answerid); 507 } 508 $mform->addElement('html', '</div>'); 509 $i++; 510 } 511 512 if ($hasattempt) { 513 $this->add_action_buttons(null, get_string("nextpage", "lesson")); 514 } else { 515 $this->add_action_buttons(null, get_string("submit", "lesson")); 516 } 517 } 518 519 } 520 521 class lesson_display_answer_form_multichoice_multianswer extends moodleform { 522 523 public function definition() { 524 global $USER, $OUTPUT; 525 $mform = $this->_form; 526 $answers = $this->_customdata['answers']; 527 528 $lessonid = $this->_customdata['lessonid']; 529 $contents = $this->_customdata['contents']; 530 531 $mform->addElement('header', 'pageheader'); 532 533 $mform->addElement('html', $OUTPUT->container($contents, 'contents')); 534 535 $hasattempt = false; 536 $disabled = ''; 537 $useranswers = array(); 538 if (isset($USER->modattempts[$lessonid]) && !empty($USER->modattempts[$lessonid])) { 539 $hasattempt = true; 540 $disabled = array('disabled' => 'disabled'); 541 $useranswers = explode(',', $USER->modattempts[$lessonid]->useranswer); 542 } 543 544 $options = new stdClass; 545 $options->para = false; 546 $options->noclean = true; 547 548 $mform->addElement('hidden', 'id'); 549 $mform->setType('id', PARAM_INT); 550 551 $mform->addElement('hidden', 'pageid'); 552 $mform->setType('pageid', PARAM_INT); 553 554 foreach ($answers as $answer) { 555 $mform->addElement('html', '<div class="answeroption">'); 556 $answerid = 'answer['.$answer->id.']'; 557 if ($hasattempt && in_array($answer->id, $useranswers)) { 558 $answerid = 'answer_'.$answer->id; 559 $mform->addElement('hidden', 'answer['.$answer->id.']', $answer->answer); 560 $mform->setType('answer['.$answer->id.']', PARAM_NOTAGS); 561 $mform->setDefault($answerid, true); 562 $mform->setDefault('answer['.$answer->id.']', true); 563 } 564 // NOTE: our silly checkbox supports only value '1' - we can not use it like the radiobox above!!!!!! 565 $answer->answer = preg_replace('#>$#', '> ', $answer->answer); 566 $mform->addElement('checkbox', $answerid, null, format_text($answer->answer, $answer->answerformat, $options), $disabled); 567 $mform->setType($answerid, PARAM_INT); 568 569 $mform->addElement('html', '</div>'); 570 } 571 572 if ($hasattempt) { 573 $this->add_action_buttons(null, get_string("nextpage", "lesson")); 574 } else { 575 $this->add_action_buttons(null, get_string("submit", "lesson")); 576 } 577 } 578 579 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |