[ Index ] |
PHP Cross Reference of Unnamed Project |
[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 103 // Trigger an event question viewed. 104 $eventparams = array( 105 'context' => context_module::instance($PAGE->cm->id), 106 'objectid' => $this->properties->id, 107 'other' => array( 108 'pagetype' => $this->get_typestring() 109 ) 110 ); 111 112 $event = \mod_lesson\event\question_viewed::create($eventparams); 113 $event->trigger(); 114 return $mform->display(); 115 } 116 117 public function check_answer() { 118 global $DB, $CFG, $PAGE; 119 $result = parent::check_answer(); 120 121 $formattextdefoptions = new stdClass(); 122 $formattextdefoptions->noclean = true; 123 $formattextdefoptions->para = false; 124 125 $answers = $this->get_used_answers(); 126 shuffle($answers); 127 $action = $CFG->wwwroot.'/mod/lesson/continue.php'; 128 $params = array('answers'=>$answers, 'lessonid'=>$this->lesson->id, 'contents'=>$this->get_contents()); 129 if ($this->properties->qoption) { 130 $mform = new lesson_display_answer_form_multichoice_multianswer($action, $params); 131 } else { 132 $mform = new lesson_display_answer_form_multichoice_singleanswer($action, $params); 133 } 134 $data = $mform->get_data(); 135 require_sesskey(); 136 137 if (!$data) { 138 redirect(new moodle_url('/mod/lesson/view.php', array('id'=>$PAGE->cm->id, 'pageid'=>$this->properties->id))); 139 } 140 141 if ($this->properties->qoption) { 142 // Multianswer allowed, user's answer is an array 143 144 if (empty($data->answer) || !is_array($data->answer)) { 145 $result->noanswer = true; 146 return $result; 147 } 148 149 $studentanswers = array(); 150 foreach ($data->answer as $key=>$value) { 151 $studentanswers[] = (int)$key; 152 } 153 154 // get what the user answered 155 $result->userresponse = implode(",", $studentanswers); 156 157 // get the answers in a set order, the id order 158 $answers = $this->get_used_answers(); 159 $ncorrect = 0; 160 $nhits = 0; 161 $responses = array(); 162 $correctanswerid = 0; 163 $wronganswerid = 0; 164 // store student's answers for displaying on feedback page 165 $result->studentanswer = ''; 166 $result->studentanswerformat = FORMAT_HTML; 167 foreach ($answers as $answer) { 168 foreach ($studentanswers as $answerid) { 169 if ($answerid == $answer->id) { 170 $result->studentanswer .= '<br />'.format_text($answer->answer, $answer->answerformat, $formattextdefoptions); 171 if (trim(strip_tags($answer->response))) { 172 $responses[$answerid] = format_text($answer->response, $answer->responseformat, $formattextdefoptions); 173 } 174 } 175 } 176 } 177 $correctpageid = null; 178 $wrongpageid = null; 179 // this is for custom scores. If score on answer is positive, it is correct 180 if ($this->lesson->custom) { 181 $ncorrect = 0; 182 $nhits = 0; 183 foreach ($answers as $answer) { 184 if ($answer->score > 0) { 185 $ncorrect++; 186 187 foreach ($studentanswers as $answerid) { 188 if ($answerid == $answer->id) { 189 $nhits++; 190 } 191 } 192 // save the first jumpto page id, may be needed!... 193 if (!isset($correctpageid)) { 194 // leave in its "raw" state - will converted into a proper page id later 195 $correctpageid = $answer->jumpto; 196 } 197 // save the answer id for scoring 198 if ($correctanswerid == 0) { 199 $correctanswerid = $answer->id; 200 } 201 } else { 202 // save the first jumpto page id, may be needed!... 203 if (!isset($wrongpageid)) { 204 // leave in its "raw" state - will converted into a proper page id later 205 $wrongpageid = $answer->jumpto; 206 } 207 // save the answer id for scoring 208 if ($wronganswerid == 0) { 209 $wronganswerid = $answer->id; 210 } 211 } 212 } 213 } else { 214 foreach ($answers as $answer) { 215 if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 216 $ncorrect++; 217 foreach ($studentanswers as $answerid) { 218 if ($answerid == $answer->id) { 219 $nhits++; 220 } 221 } 222 // save the first jumpto page id, may be needed!... 223 if (!isset($correctpageid)) { 224 // leave in its "raw" state - will converted into a proper page id later 225 $correctpageid = $answer->jumpto; 226 } 227 // save the answer id for scoring 228 if ($correctanswerid == 0) { 229 $correctanswerid = $answer->id; 230 } 231 } else { 232 // save the first jumpto page id, may be needed!... 233 if (!isset($wrongpageid)) { 234 // leave in its "raw" state - will converted into a proper page id later 235 $wrongpageid = $answer->jumpto; 236 } 237 // save the answer id for scoring 238 if ($wronganswerid == 0) { 239 $wronganswerid = $answer->id; 240 } 241 } 242 } 243 } 244 if ((count($studentanswers) == $ncorrect) and ($nhits == $ncorrect)) { 245 $result->correctanswer = true; 246 $result->response = implode('<br />', $responses); 247 $result->newpageid = $correctpageid; 248 $result->answerid = $correctanswerid; 249 } else { 250 $result->response = implode('<br />', $responses); 251 $result->newpageid = $wrongpageid; 252 $result->answerid = $wronganswerid; 253 } 254 } else { 255 // only one answer allowed 256 if (!isset($data->answerid) || (empty($data->answerid) && !is_int($data->answerid))) { 257 $result->noanswer = true; 258 return $result; 259 } 260 $result->answerid = $data->answerid; 261 if (!$answer = $DB->get_record("lesson_answers", array("id" => $result->answerid))) { 262 print_error("Continue: answer record not found"); 263 } 264 $answer = parent::rewrite_answers_urls($answer); 265 if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 266 $result->correctanswer = true; 267 } 268 if ($this->lesson->custom) { 269 if ($answer->score > 0) { 270 $result->correctanswer = true; 271 } else { 272 $result->correctanswer = false; 273 } 274 } 275 $result->newpageid = $answer->jumpto; 276 $result->response = format_text($answer->response, $answer->responseformat, $formattextdefoptions); 277 $result->userresponse = format_text($answer->answer, $answer->answerformat, $formattextdefoptions); 278 $result->studentanswer = $result->userresponse; 279 } 280 return $result; 281 } 282 283 public function option_description_string() { 284 if ($this->properties->qoption) { 285 return " - ".get_string("multianswer", "lesson"); 286 } 287 return parent::option_description_string(); 288 } 289 290 public function display_answers(html_table $table) { 291 $answers = $this->get_used_answers(); 292 $options = new stdClass; 293 $options->noclean = true; 294 $options->para = false; 295 $i = 1; 296 foreach ($answers as $answer) { 297 $answer = parent::rewrite_answers_urls($answer); 298 $cells = array(); 299 if ($this->lesson->custom && $answer->score > 0) { 300 // if the score is > 0, then it is correct 301 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n"; 302 } else if ($this->lesson->custom) { 303 $cells[] = '<span class="label">'.get_string("answer", "lesson")." $i</span>: \n"; 304 } else if ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto)) { 305 // underline correct answers 306 $cells[] = '<span class="correct">'.get_string("answer", "lesson")." $i</span>: \n"; 307 } else { 308 $cells[] = '<span class="labelcorrect">'.get_string("answer", "lesson")." $i</span>: \n"; 309 } 310 $cells[] = format_text($answer->answer, $answer->answerformat, $options); 311 $table->data[] = new html_table_row($cells); 312 313 $cells = array(); 314 $cells[] = "<span class=\"label\">".get_string("response", "lesson")." $i</span>"; 315 $cells[] = format_text($answer->response, $answer->responseformat, $options); 316 $table->data[] = new html_table_row($cells); 317 318 $cells = array(); 319 $cells[] = "<span class=\"label\">".get_string("score", "lesson").'</span>'; 320 $cells[] = $answer->score; 321 $table->data[] = new html_table_row($cells); 322 323 $cells = array(); 324 $cells[] = "<span class=\"label\">".get_string("jump", "lesson").'</span>'; 325 $cells[] = $this->get_jump_name($answer->jumpto); 326 $table->data[] = new html_table_row($cells); 327 if ($i === 1){ 328 $table->data[count($table->data)-1]->cells[0]->style = 'width:20%;'; 329 } 330 $i++; 331 } 332 return $table; 333 } 334 public function stats(array &$pagestats, $tries) { 335 if(count($tries) > $this->lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt 336 $temp = $tries[$this->lesson->maxattempts - 1]; 337 } else { 338 // else, user attempted the question less than the max, so grab the last one 339 $temp = end($tries); 340 } 341 if ($this->properties->qoption) { 342 $userresponse = explode(",", $temp->useranswer); 343 foreach ($userresponse as $response) { 344 if (isset($pagestats[$temp->pageid][$response])) { 345 $pagestats[$temp->pageid][$response]++; 346 } else { 347 $pagestats[$temp->pageid][$response] = 1; 348 } 349 } 350 } else { 351 if (isset($pagestats[$temp->pageid][$temp->answerid])) { 352 $pagestats[$temp->pageid][$temp->answerid]++; 353 } else { 354 $pagestats[$temp->pageid][$temp->answerid] = 1; 355 } 356 } 357 if (isset($pagestats[$temp->pageid]["total"])) { 358 $pagestats[$temp->pageid]["total"]++; 359 } else { 360 $pagestats[$temp->pageid]["total"] = 1; 361 } 362 return true; 363 } 364 365 public function report_answers($answerpage, $answerdata, $useranswer, $pagestats, &$i, &$n) { 366 $answers = $this->get_used_answers(); 367 $formattextdefoptions = new stdClass; 368 $formattextdefoptions->para = false; //I'll use it widely in this page 369 $formattextdefoptions->context = $answerpage->context; 370 371 foreach ($answers as $answer) { 372 if ($this->properties->qoption) { 373 if ($useranswer == null) { 374 $userresponse = array(); 375 } else { 376 $userresponse = explode(",", $useranswer->useranswer); 377 } 378 if (in_array($answer->id, $userresponse)) { 379 // make checked 380 $data = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />"; 381 if (!isset($answerdata->response)) { 382 if ($answer->response == null) { 383 if ($useranswer->correct) { 384 $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); 385 } else { 386 $answerdata->response = get_string("thatsthewronganswer", "lesson"); 387 } 388 } else { 389 $answerdata->response = $answer->response; 390 } 391 } 392 if (!isset($answerdata->score)) { 393 if ($this->lesson->custom) { 394 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 395 } elseif ($useranswer->correct) { 396 $answerdata->score = get_string("receivedcredit", "lesson"); 397 } else { 398 $answerdata->score = get_string("didnotreceivecredit", "lesson"); 399 } 400 } 401 } else { 402 // unchecked 403 $data = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />"; 404 } 405 if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { 406 $data = "<div class=highlight>".$data.' '.format_text($answer->answer,$answer->answerformat,$formattextdefoptions)."</div>"; 407 } else { 408 $data .= format_text($answer->answer,$answer->answerformat,$formattextdefoptions); 409 } 410 } else { 411 if ($useranswer != null and $answer->id == $useranswer->answerid) { 412 // make checked 413 $data = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />"; 414 if ($answer->response == null) { 415 if ($useranswer->correct) { 416 $answerdata->response = get_string("thatsthecorrectanswer", "lesson"); 417 } else { 418 $answerdata->response = get_string("thatsthewronganswer", "lesson"); 419 } 420 } else { 421 $answerdata->response = $answer->response; 422 } 423 if ($this->lesson->custom) { 424 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score; 425 } elseif ($useranswer->correct) { 426 $answerdata->score = get_string("receivedcredit", "lesson"); 427 } else { 428 $answerdata->score = get_string("didnotreceivecredit", "lesson"); 429 } 430 } else { 431 // unchecked 432 $data = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />"; 433 } 434 if (($answer->score > 0 && $this->lesson->custom) || ($this->lesson->jumpto_is_correct($this->properties->id, $answer->jumpto) && !$this->lesson->custom)) { 435 $data = "<div class=\"highlight\">".$data.' '.format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."</div>"; 436 } else { 437 $data .= format_text($answer->answer,$answer->answerformat,$formattextdefoptions); 438 } 439 } 440 if (isset($pagestats[$this->properties->id][$answer->id])) { 441 $percent = $pagestats[$this->properties->id][$answer->id] / $pagestats[$this->properties->id]["total"] * 100; 442 $percent = round($percent, 2); 443 $percent .= "% ".get_string("checkedthisone", "lesson"); 444 } else { 445 $percent = get_string("noonecheckedthis", "lesson"); 446 } 447 448 $answerdata->answers[] = array($data, $percent); 449 $answerpage->answerdata = $answerdata; 450 } 451 return $answerpage; 452 } 453 } 454 455 456 class lesson_add_page_form_multichoice extends lesson_add_page_form_base { 457 458 public $qtype = 'multichoice'; 459 public $qtypestring = 'multichoice'; 460 protected $answerformat = LESSON_ANSWER_HTML; 461 protected $responseformat = LESSON_ANSWER_HTML; 462 463 public function custom_definition() { 464 465 $this->_form->addElement('checkbox', 'qoption', get_string('options', 'lesson'), get_string('multianswer', 'lesson')); 466 $this->_form->setDefault('qoption', 0); 467 $this->_form->addHelpButton('qoption', 'multianswer', 'lesson'); 468 469 for ($i = 0; $i < $this->_customdata['lesson']->maxanswers; $i++) { 470 $this->_form->addElement('header', 'answertitle'.$i, get_string('answer').' '.($i+1)); 471 $this->add_answer($i, null, ($i<2), $this->get_answer_format()); 472 $this->add_response($i); 473 $this->add_jumpto($i, null, ($i == 0 ? LESSON_NEXTPAGE : LESSON_THISPAGE)); 474 $this->add_score($i, null, ($i===0)?1:0); 475 } 476 } 477 } 478 479 class lesson_display_answer_form_multichoice_singleanswer extends moodleform { 480 481 public function definition() { 482 global $USER, $OUTPUT; 483 $mform = $this->_form; 484 $answers = $this->_customdata['answers']; 485 $lessonid = $this->_customdata['lessonid']; 486 $contents = $this->_customdata['contents']; 487 if (array_key_exists('attempt', $this->_customdata)) { 488 $attempt = $this->_customdata['attempt']; 489 } else { 490 $attempt = new stdClass(); 491 $attempt->answerid = null; 492 } 493 494 // Disable shortforms. 495 $mform->setDisableShortforms(); 496 497 $mform->addElement('header', 'pageheader'); 498 499 $mform->addElement('html', $OUTPUT->container($contents, 'contents')); 500 501 $hasattempt = false; 502 $disabled = ''; 503 if (isset($USER->modattempts[$lessonid]) && !empty($USER->modattempts[$lessonid])) { 504 $hasattempt = true; 505 $disabled = array('disabled' => 'disabled'); 506 } 507 508 $options = new stdClass; 509 $options->para = false; 510 $options->noclean = true; 511 512 $mform->addElement('hidden', 'id'); 513 $mform->setType('id', PARAM_INT); 514 515 $mform->addElement('hidden', 'pageid'); 516 $mform->setType('pageid', PARAM_INT); 517 518 $i = 0; 519 foreach ($answers as $answer) { 520 $mform->addElement('html', '<div class="answeroption">'); 521 $answer->answer = preg_replace('#>$#', '> ', $answer->answer); 522 $mform->addElement('radio','answerid',null,format_text($answer->answer, $answer->answerformat, $options),$answer->id, $disabled); 523 $mform->setType('answer'.$i, PARAM_INT); 524 if ($hasattempt && $answer->id == $USER->modattempts[$lessonid]->answerid) { 525 $mform->setDefault('answerid', $USER->modattempts[$lessonid]->answerid); 526 } 527 $mform->addElement('html', '</div>'); 528 $i++; 529 } 530 531 if ($hasattempt) { 532 $this->add_action_buttons(null, get_string("nextpage", "lesson")); 533 } else { 534 $this->add_action_buttons(null, get_string("submit", "lesson")); 535 } 536 } 537 538 } 539 540 class lesson_display_answer_form_multichoice_multianswer extends moodleform { 541 542 public function definition() { 543 global $USER, $OUTPUT; 544 $mform = $this->_form; 545 $answers = $this->_customdata['answers']; 546 547 $lessonid = $this->_customdata['lessonid']; 548 $contents = $this->_customdata['contents']; 549 550 // Disable shortforms. 551 $mform->setDisableShortforms(); 552 553 $mform->addElement('header', 'pageheader'); 554 555 $mform->addElement('html', $OUTPUT->container($contents, 'contents')); 556 557 $hasattempt = false; 558 $disabled = ''; 559 $useranswers = array(); 560 if (isset($USER->modattempts[$lessonid]) && !empty($USER->modattempts[$lessonid])) { 561 $hasattempt = true; 562 $disabled = array('disabled' => 'disabled'); 563 $useranswers = explode(',', $USER->modattempts[$lessonid]->useranswer); 564 } 565 566 $options = new stdClass; 567 $options->para = false; 568 $options->noclean = true; 569 570 $mform->addElement('hidden', 'id'); 571 $mform->setType('id', PARAM_INT); 572 573 $mform->addElement('hidden', 'pageid'); 574 $mform->setType('pageid', PARAM_INT); 575 576 foreach ($answers as $answer) { 577 $mform->addElement('html', '<div class="answeroption">'); 578 $answerid = 'answer['.$answer->id.']'; 579 if ($hasattempt && in_array($answer->id, $useranswers)) { 580 $answerid = 'answer_'.$answer->id; 581 $mform->addElement('hidden', 'answer['.$answer->id.']', $answer->answer); 582 $mform->setType('answer['.$answer->id.']', PARAM_NOTAGS); 583 $mform->setDefault($answerid, true); 584 $mform->setDefault('answer['.$answer->id.']', true); 585 } 586 // NOTE: our silly checkbox supports only value '1' - we can not use it like the radiobox above!!!!!! 587 $answer->answer = preg_replace('#>$#', '> ', $answer->answer); 588 $mform->addElement('checkbox', $answerid, null, format_text($answer->answer, $answer->answerformat, $options), $disabled); 589 $mform->setType($answerid, PARAM_INT); 590 591 $mform->addElement('html', '</div>'); 592 } 593 594 if ($hasattempt) { 595 $this->add_action_buttons(null, get_string("nextpage", "lesson")); 596 } else { 597 $this->add_action_buttons(null, get_string("submit", "lesson")); 598 } 599 } 600 601 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |