/** * Test the question answered event. * * There is no external API for answering an truefalse question, so the unit test will simply * create and trigger the event and ensure data is returned as expected. */ public function test_question_answered() { // Trigger an event: truefalse question answered. $eventparams = array('context' => context_module::instance($this->lesson->properties()->cmid), 'objectid' => 25, 'other' => array('pagetype' => 'True/false')); $event = \mod_lesson\event\question_answered::create($eventparams); // Trigger and capture the event. $sink = $this->redirectEvents(); $event->trigger(); $events = $sink->get_events(); $event = reset($events); // Check that the event data is valid. $this->assertInstanceOf('\\mod_lesson\\event\\question_answered', $event); $this->assertEquals(25, $event->objectid); $this->assertEquals('True/false', $event->other['pagetype']); $this->assertEventContextNotUsed($event); $this->assertDebuggingNotCalled(); }
/** * Records an attempt at this page * * @final * @global moodle_database $DB * @param stdClass $context * @return stdClass Returns the result of the attempt */ public final function record_attempt($context) { global $DB, $USER, $OUTPUT, $PAGE; /** * This should be overridden by each page type to actually check the response * against what ever custom criteria they have defined */ $result = $this->check_answer(); $result->attemptsremaining = 0; $result->maxattemptsreached = false; if ($result->noanswer) { $result->newpageid = $this->properties->id; // display same page again $result->feedback = get_string('noanswer', 'lesson'); } else { if (!has_capability('mod/lesson:manage', $context)) { $nretakes = $DB->count_records("lesson_grades", array("lessonid" => $this->lesson->id, "userid" => $USER->id)); // record student's attempt $attempt = new stdClass(); $attempt->lessonid = $this->lesson->id; $attempt->pageid = $this->properties->id; $attempt->userid = $USER->id; $attempt->answerid = $result->answerid; $attempt->retry = $nretakes; $attempt->correct = $result->correctanswer; if ($result->userresponse !== null) { $attempt->useranswer = $result->userresponse; } $attempt->timeseen = time(); // if allow modattempts, then update the old attempt record, otherwise, insert new answer record $userisreviewing = false; if (isset($USER->modattempts[$this->lesson->id])) { $attempt->retry = $nretakes - 1; // they are going through on review, $nretakes will be too high $userisreviewing = true; } // Only insert a record if we are not reviewing the lesson. if (!$userisreviewing) { if ($this->lesson->retake || !$this->lesson->retake && $nretakes == 0) { $attempt->id = $DB->insert_record("lesson_attempts", $attempt); // Trigger an event: question answered. $eventparams = array('context' => context_module::instance($PAGE->cm->id), 'objectid' => $this->properties->id, 'other' => array('pagetype' => $this->get_typestring())); $event = \mod_lesson\event\question_answered::create($eventparams); $event->add_record_snapshot('lesson_attempts', $attempt); $event->trigger(); } } // "number of attempts remaining" message if $this->lesson->maxattempts > 1 // displaying of message(s) is at the end of page for more ergonomic display if (!$result->correctanswer && $result->newpageid == 0) { // wrong answer and student is stuck on this page - check how many attempts // the student has had at this page/question $nattempts = $DB->count_records("lesson_attempts", array("pageid" => $this->properties->id, "userid" => $USER->id, "retry" => $attempt->retry)); // retreive the number of attempts left counter for displaying at bottom of feedback page if ($nattempts >= $this->lesson->maxattempts) { if ($this->lesson->maxattempts > 1) { // don't bother with message if only one attempt $result->maxattemptsreached = true; } $result->newpageid = LESSON_NEXTPAGE; } else { if ($this->lesson->maxattempts > 1) { // don't bother with message if only one attempt $result->attemptsremaining = $this->lesson->maxattempts - $nattempts; } } } } // TODO: merge this code with the jump code below. Convert jumpto page into a proper page id if ($result->newpageid == 0) { $result->newpageid = $this->properties->id; } elseif ($result->newpageid == LESSON_NEXTPAGE) { $result->newpageid = $this->lesson->get_next_page($this->properties->nextpageid); } // Determine default feedback if necessary if (empty($result->response)) { if (!$this->lesson->feedback && !$result->noanswer && !($this->lesson->review & !$result->correctanswer && !$result->isessayquestion)) { // These conditions have been met: // 1. The lesson manager has not supplied feedback to the student // 2. Not displaying default feedback // 3. The user did provide an answer // 4. We are not reviewing with an incorrect answer (and not reviewing an essay question) $result->nodefaultresponse = true; // This will cause a redirect below } else { if ($result->isessayquestion) { $result->response = get_string('defaultessayresponse', 'lesson'); } else { if ($result->correctanswer) { $result->response = get_string('thatsthecorrectanswer', 'lesson'); } else { $result->response = get_string('thatsthewronganswer', 'lesson'); } } } } if ($result->response) { if ($this->lesson->review && !$result->correctanswer && !$result->isessayquestion) { $nretakes = $DB->count_records("lesson_grades", array("lessonid" => $this->lesson->id, "userid" => $USER->id)); $qattempts = $DB->count_records("lesson_attempts", array("userid" => $USER->id, "retry" => $nretakes, "pageid" => $this->properties->id)); if ($qattempts == 1) { $result->feedback = $OUTPUT->box(get_string("firstwrong", "lesson"), 'feedback'); } else { $result->feedback = $OUTPUT->box(get_string("secondpluswrong", "lesson"), 'feedback'); } } else { $result->feedback = ''; } $class = 'response'; if ($result->correctanswer) { $class .= ' correct'; // CSS over-ride this if they exist (!important). } else { if (!$result->isessayquestion) { $class .= ' incorrect'; // CSS over-ride this if they exist (!important). } } $options = new stdClass(); $options->noclean = true; $options->para = true; $options->overflowdiv = true; $options->context = $context; $result->feedback .= $OUTPUT->box(format_text($this->get_contents(), $this->properties->contentsformat, $options), 'generalbox boxaligncenter'); if (isset($result->studentanswerformat)) { // This is the student's answer so it should be cleaned. $studentanswer = format_text($result->studentanswer, $result->studentanswerformat, array('context' => $context, 'para' => true)); } else { $studentanswer = format_string($result->studentanswer); } $result->feedback .= '<div class="correctanswer generalbox"><em>' . get_string("youranswer", "lesson") . '</em> : ' . $studentanswer; if (isset($result->responseformat)) { $result->response = file_rewrite_pluginfile_urls($result->response, 'pluginfile.php', $context->id, 'mod_lesson', 'page_responses', $result->answerid); $result->feedback .= $OUTPUT->box(format_text($result->response, $result->responseformat, $options), $class); } else { $result->feedback .= $OUTPUT->box($result->response, $class); } $result->feedback .= '</div>'; } } return $result; }