3 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
19 * Displays the lesson statistics.
22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late
26 require_once('../../config.php');
27 require_once($CFG->dirroot.'/mod/lesson/locallib.php');
28 require_once($CFG->dirroot.'/mod/lesson/pagetypes/branchtable.php'); // Needed for constant.
30 $id = required_param('id', PARAM_INT); // Course Module ID
31 $pageid = optional_param('pageid', null, PARAM_INT); // Lesson Page ID
32 $action = optional_param('action', 'reportoverview', PARAM_ALPHA); // action to take
33 $nothingtodisplay = false;
35 $cm = get_coursemodule_from_id('lesson', $id, 0, false, MUST_EXIST);
36 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
37 $lesson = new lesson($DB->get_record('lesson', array('id' => $cm->instance), '*', MUST_EXIST));
39 require_login($course, false, $cm);
41 $currentgroup = groups_get_activity_group($cm, true);
43 $context = context_module::instance($cm->id);
44 require_capability('mod/lesson:viewreports', $context);
46 $url = new moodle_url('/mod/lesson/report.php', array('id'=>$id));
47 $url->param('action', $action);
48 if ($pageid !== null) {
49 $url->param('pageid', $pageid);
52 if ($action == 'reportoverview') {
53 $PAGE->navbar->add(get_string('reports', 'lesson'));
54 $PAGE->navbar->add(get_string('overview', 'lesson'));
57 $lessonoutput = $PAGE->get_renderer('mod_lesson');
59 if ($action === 'delete') {
60 /// Process any form data before fetching attempts, grades and times
61 if (has_capability('mod/lesson:edit', $context) and $form = data_submitted() and confirm_sesskey()) {
62 /// Cycle through array of userids with nested arrays of tries
63 if (!empty($form->attempts)) {
64 foreach ($form->attempts as $userid => $tries) {
65 // Modifier IS VERY IMPORTANT! What does it do?
66 // Well, it is for when you delete multiple attempts for the same user.
67 // If you delete try 1 and 3 for a user, then after deleting try 1, try 3 then
68 // becomes try 2 (because try 1 is gone and all tries after try 1 get decremented).
69 // So, the modifier makes sure that the submitted try refers to the current try in the
70 // database - hope this all makes sense :)
73 foreach ($tries as $try => $junk) {
76 /// Clean up the timer table by removing using the order - this is silly, it should be linked to specific attempt (skodak)
77 $params = array ("userid" => $userid, "lessonid" => $lesson->id);
78 $timers = $DB->get_records_sql("SELECT id FROM {lesson_timer}
79 WHERE userid = :userid AND lessonid = :lessonid
80 ORDER BY starttime", $params, $try, 1);
82 $timer = reset($timers);
83 $DB->delete_records('lesson_timer', array('id' => $timer->id));
86 // Remove the grade from the grades tables - this is silly, it should be linked to specific attempt (skodak).
87 $grades = $DB->get_records_sql("SELECT id FROM {lesson_grades}
88 WHERE userid = :userid AND lessonid = :lessonid
89 ORDER BY completed", $params, $try, 1);
92 $grade = reset($grades);
93 $DB->delete_records('lesson_grades', array('id' => $grade->id));
96 /// Remove attempts and update the retry number
97 $DB->delete_records('lesson_attempts', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try));
98 $DB->execute("UPDATE {lesson_attempts} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try));
100 /// Remove seen branches and update the retry number
101 $DB->delete_records('lesson_branch', array('userid' => $userid, 'lessonid' => $lesson->id, 'retry' => $try));
102 $DB->execute("UPDATE {lesson_branch} SET retry = retry - 1 WHERE userid = ? AND lessonid = ? AND retry > ?", array($userid, $lesson->id, $try));
104 /// update central gradebook
105 lesson_update_grades($lesson, $userid);
112 redirect(new moodle_url($PAGE->url, array('action'=>'reportoverview')));
114 } else if ($action === 'reportoverview') {
115 /**************************************************************************
116 this action is for default view and overview view
117 **************************************************************************/
119 // Count the number of branch and question pages in this lesson.
120 $branchcount = $DB->count_records('lesson_pages', array('lessonid' => $lesson->id, 'qtype' => LESSON_PAGE_BRANCHTABLE));
121 $questioncount = ($DB->count_records('lesson_pages', array('lessonid' => $lesson->id)) - $branchcount);
123 // Only load students if there attempts for this lesson.
124 $attempts = $DB->record_exists('lesson_attempts', array('lessonid' => $lesson->id));
125 $branches = $DB->record_exists('lesson_branch', array('lessonid' => $lesson->id));
126 if ($attempts or $branches) {
127 list($esql, $params) = get_enrolled_sql($context, '', $currentgroup, true);
128 list($sort, $sortparams) = users_order_by_sql('u');
130 $params['lessonid'] = $lesson->id;
131 $ufields = user_picture::fields('u');
132 $sql = "SELECT DISTINCT $ufields
134 JOIN (SELECT userid, lessonid FROM {lesson_attempts} a1 UNION
135 SELECT userid, lessonid FROM {lesson_branch} b1) a ON u.id = a.userid
136 JOIN ($esql) ue ON ue.id = a.userid
137 WHERE a.lessonid = :lessonid
140 $students = $DB->get_recordset_sql($sql, $params);
141 if (!$students->valid()) {
143 $nothingtodisplay = true;
146 $nothingtodisplay = true;
149 if ($nothingtodisplay) {
150 echo $lessonoutput->header($lesson, $cm, $action, false, null, get_string('nolessonattempts', 'lesson'));
151 if (!empty($currentgroup)) {
152 $groupname = groups_get_group_name($currentgroup);
153 echo $OUTPUT->notification(get_string('nolessonattemptsgroup', 'lesson', $groupname));
155 echo $OUTPUT->notification(get_string('nolessonattempts', 'lesson'));
157 groups_print_activity_menu($cm, $url);
158 echo $OUTPUT->footer();
162 if (! $grades = $DB->get_records('lesson_grades', array('lessonid' => $lesson->id), 'completed')) {
166 if (! $times = $DB->get_records('lesson_timer', array('lessonid' => $lesson->id), 'starttime')) {
170 echo $lessonoutput->header($lesson, $cm, $action, false, null, get_string('overview', 'lesson'));
171 groups_print_activity_menu($cm, $url);
173 $course_context = context_course::instance($course->id);
174 if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) {
175 $seeallgradeslink = new moodle_url('/grade/report/grader/index.php', array('id'=>$course->id));
176 $seeallgradeslink = html_writer::link($seeallgradeslink, get_string('seeallcoursegrades', 'grades'));
177 echo $OUTPUT->box($seeallgradeslink, 'allcoursegrades');
180 // Build an array for output.
181 $studentdata = array();
183 $attempts = $DB->get_recordset('lesson_attempts', array('lessonid' => $lesson->id), 'timeseen');
184 foreach ($attempts as $attempt) {
185 // if the user is not in the array or if the retry number is not in the sub array, add the data for that try.
186 if (empty($studentdata[$attempt->userid]) || empty($studentdata[$attempt->userid][$attempt->retry])) {
187 // restore/setup defaults
194 // search for the grade record for this try. if not there, the nulls defined above will be used.
195 foreach($grades as $grade) {
196 // check to see if the grade matches the correct user
197 if ($grade->userid == $attempt->userid) {
198 // see if n is = to the retry
199 if ($n == $attempt->retry) {
201 $usergrade = round($grade->grade, 2); // round it here so we only have to do it once
204 $n++; // if not equal, then increment n
208 // search for the time record for this try. if not there, the nulls defined above will be used.
209 foreach($times as $time) {
210 // check to see if the grade matches the correct user
211 if ($time->userid == $attempt->userid) {
212 // see if n is = to the retry
213 if ($n == $attempt->retry) {
215 $timeend = $time->lessontime;
216 $timestart = $time->starttime;
217 $eol = $time->completed;
220 $n++; // if not equal, then increment n
224 // build up the array.
225 // this array represents each student and all of their tries at the lesson
226 $studentdata[$attempt->userid][$attempt->retry] = array( "timestart" => $timestart,
227 "timeend" => $timeend,
228 "grade" => $usergrade,
230 "try" => $attempt->retry,
231 "userid" => $attempt->userid);
236 $branches = $DB->get_recordset('lesson_branch', array('lessonid' => $lesson->id), 'timeseen');
237 foreach ($branches as $branch) {
238 // If the user is not in the array or if the retry number is not in the sub array, add the data for that try.
239 if (empty($studentdata[$branch->userid]) || empty($studentdata[$branch->userid][$branch->retry])) {
240 // Restore/setup defaults.
246 // Search for the time record for this try. if not there, the nulls defined above will be used.
247 foreach ($times as $time) {
248 // Check to see if the grade matches the correct user.
249 if ($time->userid == $branch->userid) {
250 // See if n is = to the retry.
251 if ($n == $branch->retry) {
253 $timeend = $time->lessontime;
254 $timestart = $time->starttime;
255 $eol = $time->completed;
258 $n++; // If not equal, then increment n.
262 // Build up the array.
263 // This array represents each student and all of their tries at the lesson.
264 $studentdata[$branch->userid][$branch->retry] = array( "timestart" => $timestart,
265 "timeend" => $timeend,
266 "grade" => $usergrade,
268 "try" => $branch->retry,
269 "userid" => $branch->userid);
274 // Determine if lesson should have a score.
275 if ($branchcount > 0 AND $questioncount == 0) {
276 // This lesson only contains content pages and is not graded.
277 $lessonscored = false;
279 // This lesson is graded.
280 $lessonscored = true;
282 // set all the stats variables
291 $table = new html_table();
293 // Set up the table object.
295 $table->head = array(get_string('name'), get_string('attempts', 'lesson'), get_string('highscore', 'lesson'));
297 $table->head = array(get_string('name'), get_string('attempts', 'lesson'));
299 $table->align = array('center', 'left', 'left');
300 $table->wrap = array('nowrap', 'nowrap', 'nowrap');
301 $table->attributes['class'] = 'standardtable generaltable';
302 $table->size = array(null, '70%', null);
304 // print out the $studentdata array
305 // going through each student that has attempted the lesson, so, each student should have something to be displayed
306 foreach ($students as $student) {
307 // check to see if the student has attempts to print out
308 if (array_key_exists($student->id, $studentdata)) {
309 // set/reset some variables
311 // gather the data for each user attempt
313 $bestgradefound = false;
314 // $tries holds all the tries/retries a student has done
315 $tries = $studentdata[$student->id];
316 $studentname = fullname($student, true);
317 foreach ($tries as $try) {
318 // start to build up the checkbox and link
319 if (has_capability('mod/lesson:edit', $context)) {
320 $temp = '<input type="checkbox" id="attempts" name="attempts['.$try['userid'].']['.$try['try'].']" /> ';
325 $temp .= "<a href=\"report.php?id=$cm->id&action=reportdetail&userid=".$try['userid']
326 .'&try='.$try['try'].'" class="lesson-attempt-link">';
327 if ($try["grade"] !== null) { // if null then not done yet
328 // this is what the link does when the user has completed the try
329 $timetotake = $try["timeend"] - $try["timestart"];
331 $temp .= $try["grade"]."%";
332 $bestgradefound = true;
333 if ($try["grade"] > $bestgrade) {
334 $bestgrade = $try["grade"];
336 $temp .= " ".userdate($try["timestart"]);
337 $temp .= ", (".format_time($timetotake).")</a>";
340 // User finished the lesson but has no grade. (Happens when there are only content pages).
341 $temp .= " ".userdate($try["timestart"]);
342 $timetotake = $try["timeend"] - $try["timestart"];
343 $temp .= ", (".format_time($timetotake).")</a>";
345 // This is what the link does/looks like when the user has not completed the attempt.
346 $temp .= get_string("notcompleted", "lesson");
347 if ($try['timestart'] !== 0) {
348 // Teacher previews do not track time spent.
349 $temp .= " ".userdate($try["timestart"]);
355 // build up the attempts array
358 // Run these lines for the stats only if the user finnished the lesson.
360 // User has completed the lesson.
362 $avetime += $timetotake;
363 if ($timetotake > $hightime || $hightime == null) {
364 $hightime = $timetotake;
366 if ($timetotake < $lowtime || $lowtime == null) {
367 $lowtime = $timetotake;
369 if ($try["grade"] !== null) {
370 // The lesson was scored.
371 $avescore += $try["grade"];
372 if ($try["grade"] > $highscore || $highscore === null) {
373 $highscore = $try["grade"];
375 if ($try["grade"] < $lowscore || $lowscore === null) {
376 $lowscore = $try["grade"];
382 // get line breaks in after each attempt
383 $attempts = implode("<br />\n", $attempts);
386 // Add the grade if the lesson is graded.
387 $bestgrade = $bestgrade."%";
388 $table->data[] = array($studentname, $attempts, $bestgrade);
390 // This lesson does not have a grade.
391 $table->data[] = array($studentname, $attempts);
397 if (has_capability('mod/lesson:edit', $context)) {
398 echo "<form id=\"theform\" method=\"post\" action=\"report.php\">\n
399 <input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n
400 <input type=\"hidden\" name=\"id\" value=\"$cm->id\" />\n";
402 echo html_writer::table($table);
403 if (has_capability('mod/lesson:edit', $context)) {
404 $checklinks = '<a href="javascript: checkall();">'.get_string('selectall').'</a> / ';
405 $checklinks .= '<a href="javascript: checknone();">'.get_string('deselectall').'</a>';
406 $checklinks .= html_writer::label('action', 'menuaction', false, array('class' => 'accesshide'));
407 $checklinks .= html_writer::select(array('delete' => get_string('deleteselected')), 'action', 0, array(''=>'choosedots'), array('id'=>'actionid', 'class' => 'autosubmit'));
408 $PAGE->requires->yui_module('moodle-core-formautosubmit',
409 'M.core.init_formautosubmit',
410 array(array('selectid' => 'actionid', 'nothing' => false))
412 echo $OUTPUT->box($checklinks, 'center');
416 // Calculate the Statistics.
417 if ($avetime == null) {
418 $avetime = get_string("notcompleted", "lesson");
420 $avetime = format_float($avetime/$numofattempts, 0);
421 $avetime = format_time($avetime);
423 if ($hightime == null) {
424 $hightime = get_string("notcompleted", "lesson");
426 $hightime = format_time($hightime);
428 if ($lowtime == null) {
429 $lowtime = get_string("notcompleted", "lesson");
431 $lowtime = format_time($lowtime);
435 if ($numofattempts == 0) {
436 $avescore = get_string("notcompleted", "lesson");
438 $avescore = format_float($avescore / $numofattempts, 2) . '%';
440 if ($highscore === null) {
441 $highscore = get_string("notcompleted", "lesson");
445 if ($lowscore === null) {
446 $lowscore = get_string("notcompleted", "lesson");
451 // Display the full stats for the lesson.
452 echo $OUTPUT->heading(get_string('lessonstats', 'lesson'), 3);
453 $stattable = new html_table();
454 $stattable->head = array(get_string('averagescore', 'lesson'), get_string('averagetime', 'lesson'),
455 get_string('highscore', 'lesson'), get_string('lowscore', 'lesson'),
456 get_string('hightime', 'lesson'), get_string('lowtime', 'lesson'));
457 $stattable->align = array('center', 'center', 'center', 'center', 'center', 'center');
458 $stattable->wrap = array('nowrap', 'nowrap', 'nowrap', 'nowrap', 'nowrap', 'nowrap');
459 $stattable->attributes['class'] = 'standardtable generaltable';
460 $stattable->data[] = array($avescore, $avetime, $highscore, $lowscore, $hightime, $lowtime);
463 // Display simple stats for the lesson.
464 echo $OUTPUT->heading(get_string('lessonstats', 'lesson'), 3);
465 $stattable = new html_table();
466 $stattable->head = array(get_string('averagetime', 'lesson'), get_string('hightime', 'lesson'),
467 get_string('lowtime', 'lesson'));
468 $stattable->align = array('center', 'center', 'center');
469 $stattable->wrap = array('nowrap', 'nowrap', 'nowrap');
470 $stattable->attributes['class'] = 'standardtable generaltable';
471 $stattable->data[] = array($avetime, $hightime, $lowtime);
474 echo html_writer::table($stattable);
475 } else if ($action === 'reportdetail') {
476 /**************************************************************************
477 this action is for a student detailed view and for the general detailed view
479 General flow of this section of the code
480 1. Generate a object which holds values for the statistics for each question/answer
481 2. Cycle through all the pages to create a object. Foreach page, see if the student actually answered
482 the page. Then process the page appropriatly. Display all info about the question,
483 Highlight correct answers, show how the user answered the question, and display statistics
485 3. Print out info about the try (if needed)
486 4. Print out the object which contains all the try info
488 **************************************************************************/
489 echo $lessonoutput->header($lesson, $cm, $action, false, null, get_string('detailedstats', 'lesson'));
490 groups_print_activity_menu($cm, $url);
492 $course_context = context_course::instance($course->id);
493 if (has_capability('gradereport/grader:view', $course_context) && has_capability('moodle/grade:viewall', $course_context)) {
494 $seeallgradeslink = new moodle_url('/grade/report/grader/index.php', array('id'=>$course->id));
495 $seeallgradeslink = html_writer::link($seeallgradeslink, get_string('seeallcoursegrades', 'grades'));
496 echo $OUTPUT->box($seeallgradeslink, 'allcoursegrades');
499 $formattextdefoptions = new stdClass;
500 $formattextdefoptions->para = false; //I'll use it widely in this page
501 $formattextdefoptions->overflowdiv = true;
503 $userid = optional_param('userid', null, PARAM_INT); // if empty, then will display the general detailed view
504 $try = optional_param('try', null, PARAM_INT);
506 if (!empty($userid)) {
508 $lesson->update_effective_access($userid);
511 $lessonpages = $lesson->load_all_pages();
512 foreach ($lessonpages as $lessonpage) {
513 if ($lessonpage->prevpageid == 0) {
514 $pageid = $lessonpage->id;
518 // now gather the stats into an object
519 $firstpageid = $pageid;
520 $pagestats = array();
521 while ($pageid != 0) { // EOL
522 $page = $lessonpages[$pageid];
523 $params = array ("lessonid" => $lesson->id, "pageid" => $page->id);
524 if ($allanswers = $DB->get_records_select("lesson_attempts", "lessonid = :lessonid AND pageid = :pageid", $params, "timeseen")) {
525 // get them ready for processing
526 $orderedanswers = array();
527 foreach ($allanswers as $singleanswer) {
528 // ordering them like this, will help to find the single attempt record that we want to keep.
529 $orderedanswers[$singleanswer->userid][$singleanswer->retry][] = $singleanswer;
531 // this is foreach user and for each try for that user, keep one attempt record
532 foreach ($orderedanswers as $orderedanswer) {
533 foreach($orderedanswer as $tries) {
534 $page->stats($pagestats, $tries);
538 // no one answered yet...
540 //unset($orderedanswers); initialized above now
541 $pageid = $page->nextpageid;
544 $manager = lesson_page_type_manager::get($lesson);
545 $qtypes = $manager->get_page_type_strings();
547 $answerpages = array();
549 $pageid = $firstpageid;
550 // cycle through all the pages
551 // foreach page, add to the $answerpages[] array all the data that is needed
552 // from the question, the users attempt, and the statistics
553 // grayout pages that the user did not answer and Branch, end of branch, cluster
554 // and end of cluster pages
555 while ($pageid != 0) { // EOL
556 $page = $lessonpages[$pageid];
557 $answerpage = new stdClass;
560 $answerdata = new stdClass;
561 // Set some defaults for the answer data.
562 $answerdata->score = null;
563 $answerdata->response = null;
564 $answerdata->responseformat = FORMAT_PLAIN;
566 $answerpage->title = format_string($page->title);
568 $options = new stdClass;
569 $options->noclean = true;
570 $options->overflowdiv = true;
571 $options->context = $context;
572 $answerpage->contents = format_text($page->contents, $page->contentsformat, $options);
574 $answerpage->qtype = $qtypes[$page->qtype].$page->option_description_string();
575 $answerpage->grayout = $page->grayout;
576 $answerpage->context = $context;
578 if (empty($userid)) {
579 // there is no userid, so set these vars and display stats.
580 $answerpage->grayout = 0;
582 } elseif ($useranswers = $DB->get_records("lesson_attempts",array("lessonid"=>$lesson->id, "userid"=>$userid, "retry"=>$try,"pageid"=>$page->id), "timeseen")) {
583 // get the user's answer for this page
584 // need to find the right one
586 foreach ($useranswers as $userattempt) {
587 $useranswer = $userattempt;
589 if ($lesson->maxattempts == $i) {
590 break; // reached maxattempts, break out
594 // user did not answer this page, gray it out and set some nulls
595 $answerpage->grayout = 1;
600 $answerpages[] = $page->report_answers(clone($answerpage), clone($answerdata), $useranswer, $pagestats, $i, $n);
601 $pageid = $page->nextpageid;
604 /// actually start printing something
605 $table = new html_table();
606 $table->wrap = array();
607 $table->width = "60%";
608 if (!empty($userid)) {
609 // if looking at a students try, print out some basic stats at the top
611 // print out users name
612 //$headingobject->lastname = $students[$userid]->lastname;
613 //$headingobject->firstname = $students[$userid]->firstname;
614 //$headingobject->attempt = $try + 1;
615 //print_heading(get_string("studentattemptlesson", "lesson", $headingobject));
616 echo $OUTPUT->heading(get_string('attempt', 'lesson', $try+1), 3);
618 $table->head = array();
619 $table->align = array('right', 'left');
620 $table->attributes['class'] = 'compacttable generaltable';
622 $params = array("lessonid"=>$lesson->id, "userid"=>$userid);
623 if (!$grades = $DB->get_records_select("lesson_grades", "lessonid = :lessonid and userid = :userid", $params, "completed", "*", $try, 1)) {
627 $grade = current($grades);
628 $completed = $grade->completed;
629 $grade = round($grade->grade, 2);
631 if (!$times = $DB->get_records_select("lesson_timer", "lessonid = :lessonid and userid = :userid", $params, "starttime", "*", $try, 1)) {
634 $timetotake = current($times);
635 $timetotake = $timetotake->lessontime - $timetotake->starttime;
638 if ($timetotake == -1 || $completed == -1 || $grade == -1) {
639 $table->align = array("center");
641 $table->data[] = array(get_string("notcompleted", "lesson"));
643 $user = $DB->get_record('user', array('id' => $userid));
645 $gradeinfo = lesson_grade($lesson, $try, $user->id);
647 $table->data[] = array(get_string('name').':', $OUTPUT->user_picture($user, array('courseid'=>$course->id)).fullname($user, true));
648 $table->data[] = array(get_string("timetaken", "lesson").":", format_time($timetotake));
649 $table->data[] = array(get_string("completed", "lesson").":", userdate($completed));
650 $table->data[] = array(get_string('rawgrade', 'lesson').':', $gradeinfo->earned.'/'.$gradeinfo->total);
651 $table->data[] = array(get_string("grade", "lesson").":", $grade."%");
653 echo html_writer::table($table);
655 // Don't want this class for later tables
656 $table->attributes['class'] = '';
660 $table->align = array('left', 'left');
661 $table->size = array('70%', null);
662 $table->attributes['class'] = 'compacttable generaltable';
664 foreach ($answerpages as $page) {
666 if ($page->grayout) { // set the color of text
667 $fontstart = "<span class=\"dimmed\">";
668 $fontend = "</font>";
669 $fontstart2 = $fontstart;
670 $fontend2 = $fontend;
678 $table->head = array($fontstart2.$page->qtype.": ".format_string($page->title).$fontend2, $fontstart2.get_string("classstats", "lesson").$fontend2);
679 $table->data[] = array($fontstart.get_string("question", "lesson").": <br />".$fontend.$fontstart2.$page->contents.$fontend2, " ");
680 $table->data[] = array($fontstart.get_string("answer", "lesson").":".$fontend, ' ');
681 // apply the font to each answer
682 if (!empty($page->answerdata)) {
683 foreach ($page->answerdata->answers as $answer){
685 foreach ($answer as $single) {
686 // need to apply a font to each one
687 $modified[] = $fontstart2.$single.$fontend2;
689 $table->data[] = $modified;
691 if (isset($page->answerdata->response)) {
692 $table->data[] = array($fontstart.get_string("response", "lesson").": <br />".$fontend
693 .$fontstart2.$page->answerdata->response.$fontend2, " ");
695 $table->data[] = array($page->answerdata->score, " ");
697 $table->data[] = array(get_string('didnotanswerquestion', 'lesson'), " ");
699 echo html_writer::start_tag('div', array('class' => 'no-overflow'));
700 echo html_writer::table($table);
701 echo html_writer::end_tag('div');
704 print_error('unknowaction');
708 echo $OUTPUT->footer();