MDL-11082 Improved groups upgrade performance 1.8x -> 1.9; thanks Eloy for telling...
[moodle-pu.git] / mod / lesson / report.php
blobbc6b6f915608ec646fc9bce624b45ce7320855ab
1 <?php // $Id$
2 /**
3 * Displays the lesson statistics.
5 * @version $Id$
6 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
7 * @package lesson
8 **/
10 require_once('../../config.php');
11 require_once('lib.php');
12 require_once('locallib.php');
14 $id = required_param('id', PARAM_INT); // Course Module ID
15 $pageid = optional_param('pageid', NULL, PARAM_INT); // Lesson Page ID
16 $action = optional_param('action', 'reportoverview', PARAM_ALPHA); // action to take
17 $nothingtodisplay = false;
19 list($cm, $course, $lesson) = lesson_get_basics($id);
21 if (!empty($CFG->enablegroupings) && !empty($cm->groupingid)) {
22 $sql = "SELECT DISTINCT u.*
23 FROM {$CFG->prefix}lesson_attempts a
24 INNER JOIN {$CFG->prefix}user u ON u.id = a.userid
25 INNER JOIN {$CFG->prefix}groups_members gm ON gm.userid = u.id
26 INNER JOIN {$CFG->prefix}groupings_groups gg ON gm.groupid = {$cm->groupingid}
27 WHERE a.lessonid = '$lesson->id'
28 ORDER BY u.lastname";
29 } else {
30 $sql = "SELECT u.*
31 FROM {$CFG->prefix}user u,
32 {$CFG->prefix}lesson_attempts a
33 WHERE a.lessonid = '$lesson->id' and
34 u.id = a.userid
35 ORDER BY u.lastname";
38 if (! $students = get_records_sql($sql)) {
39 $nothingtodisplay = true;
42 // make sure people are where they should be
43 require_login($course->id, false, $cm);
44 $context = get_context_instance(CONTEXT_MODULE, $cm->id);
45 require_capability('mod/lesson:manage', $context);
47 /// Process any form data before fetching attempts, grades and times
48 if (has_capability('mod/lesson:edit', $context) and
49 $form = data_submitted($CFG->wwwroot.'/mod/lesson/report.php') and
50 confirm_sesskey()) {
51 /// Cycle through array of userids with nested arrays of tries
52 if (!empty($form->attempts)) {
53 foreach ($form->attempts as $userid => $tries) {
54 // Modifier IS VERY IMPORTANT! What does it do?
55 // Well, it is for when you delete multiple attempts for the same user.
56 // If you delete try 1 and 3 for a user, then after deleting try 1, try 3 then
57 // becomes try 2 (because try 1 is gone and all tries after try 1 get decremented).
58 // So, the modifier makes sure that the submitted try refers to the current try in the
59 // database - hope this all makes sense :)
60 $modifier = 0;
62 foreach ($tries as $try => $junk) {
63 $try -= $modifier;
65 /// Clean up the timer table
66 $timeid = get_field_sql("SELECT id FROM {$CFG->prefix}lesson_timer
67 WHERE userid = $userid AND lessonid = $lesson->id
68 ORDER BY starttime", $try, 1);
70 delete_records('lesson_timer', 'id', $timeid);
72 /// Remove the grade from the grades and high_scores tables
73 $gradeid = get_field_sql("SELECT id FROM {$CFG->prefix}lesson_grades
74 WHERE userid = $userid AND lessonid = $lesson->id
75 ORDER BY completed", $try, 1);
77 delete_records('lesson_grades', 'id', $gradeid);
78 delete_records('lesson_high_scores', 'gradeid', $gradeid, 'lessonid', $lesson->id, 'userid', $userid);
80 /// Remove attempts and update the retry number
81 delete_records('lesson_attempts', 'userid', $userid, 'lessonid', $lesson->id, 'retry', $try);
82 execute_sql("UPDATE {$CFG->prefix}lesson_attempts SET retry = retry - 1 WHERE userid = $userid AND lessonid = $lesson->id AND retry > $try", false);
84 /// Remove seen branches and update the retry number
85 delete_records('lesson_branch', 'userid', $userid, 'lessonid', $lesson->id, 'retry', $try);
86 execute_sql("UPDATE {$CFG->prefix}lesson_branch SET retry = retry - 1 WHERE userid = $userid AND lessonid = $lesson->id AND retry > $try", false);
88 /// update central gradebook
89 lesson_update_grades($lesson, $userid);
91 $modifier++;
94 lesson_set_message(get_string('attemptsdeleted', 'lesson'), 'notifysuccess');
98 if (! $attempts = get_records('lesson_attempts', 'lessonid', $lesson->id, 'timeseen')) {
99 $nothingtodisplay = true;
102 if (! $grades = get_records('lesson_grades', 'lessonid', $lesson->id, 'completed')) {
103 $grades = array();
106 if (! $times = get_records('lesson_timer', 'lessonid', $lesson->id, 'starttime')) {
107 $times = array();
110 lesson_print_header($cm, $course, $lesson, $action);
112 if ($nothingtodisplay) {
113 notify(get_string('nolessonattempts', 'lesson'));
114 print_footer($course);
115 exit();
118 /**************************************************************************
119 this action is for default view and overview view
120 **************************************************************************/
121 if ($action == 'reportoverview') {
122 $studentdata = array();
124 // build an array for output
125 foreach ($attempts as $attempt) {
126 // 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.
127 if (!array_key_exists($attempt->userid, $studentdata) || !array_key_exists($attempt->retry, $studentdata[$attempt->userid])) {
128 // restore/setup defaults
129 $n = 0;
130 $timestart = 0;
131 $timeend = 0;
132 $usergrade = NULL;
134 // search for the grade record for this try. if not there, the nulls defined above will be used.
135 foreach($grades as $grade) {
136 // check to see if the grade matches the correct user
137 if ($grade->userid == $attempt->userid) {
138 // see if n is = to the retry
139 if ($n == $attempt->retry) {
140 // get grade info
141 $usergrade = round($grade->grade, 2); // round it here so we only have to do it once
142 break;
144 $n++; // if not equal, then increment n
147 $n = 0;
148 // search for the time record for this try. if not there, the nulls defined above will be used.
149 foreach($times as $time) {
150 // check to see if the grade matches the correct user
151 if ($time->userid == $attempt->userid) {
152 // see if n is = to the retry
153 if ($n == $attempt->retry) {
154 // get grade info
155 $timeend = $time->lessontime;
156 $timestart = $time->starttime;
157 break;
159 $n++; // if not equal, then increment n
163 // build up the array.
164 // this array represents each student and all of their tries at the lesson
165 $studentdata[$attempt->userid][$attempt->retry] = array( "timestart" => $timestart,
166 "timeend" => $timeend,
167 "grade" => $usergrade,
168 "try" => $attempt->retry,
169 "userid" => $attempt->userid);
172 // set all the stats variables
173 $numofattempts = 0;
174 $avescore = 0;
175 $avetime = 0;
176 $highscore = NULL;
177 $lowscore = NULL;
178 $hightime = NULL;
179 $lowtime = NULL;
180 $table = new stdClass;
182 // set up the table object
183 $table->head = array(get_string('studentname', 'lesson', $course->student), get_string('attempts', 'lesson'), get_string('highscore', 'lesson'));
184 $table->align = array("center", "left", "left");
185 $table->wrap = array("nowrap", "nowrap", "nowrap");
186 $table->width = "90%";
187 $table->size = array("*", "70%", "*");
189 // print out the $studentdata array
190 // going through each student that has attempted the lesson, so, each student should have something to be displayed
191 foreach ($students as $student) {
192 // check to see if the student has attempts to print out
193 if (array_key_exists($student->id, $studentdata)) {
194 // set/reset some variables
195 $attempts = array();
196 // gather the data for each user attempt
197 $bestgrade = 0;
198 $bestgradefound = false;
199 // $tries holds all the tries/retries a student has done
200 $tries = $studentdata[$student->id];
201 $studentname = "{$student->lastname},&nbsp;$student->firstname";
202 foreach ($tries as $try) {
203 // start to build up the checkbox and link
204 if (has_capability('mod/lesson:edit', $context)) {
205 $temp = '<input type="checkbox" id="attempts" name="attempts['.$try['userid'].']['.$try['try'].']" /> ';
206 } else {
207 $temp = '';
210 $temp .= "<a href=\"report.php?id=$cm->id&amp;action=reportdetail&amp;userid=".$try['userid'].'&amp;try='.$try['try'].'">';
211 if ($try["grade"] !== NULL) { // if NULL then not done yet
212 // this is what the link does when the user has completed the try
213 $timetotake = $try["timeend"] - $try["timestart"];
215 $temp .= $try["grade"]."%";
216 $bestgradefound = true;
217 if ($try["grade"] > $bestgrade) {
218 $bestgrade = $try["grade"];
220 $temp .= "&nbsp;".userdate($try["timestart"]);
221 $temp .= ",&nbsp;(".format_time($timetotake).")</a>";
222 } else {
223 // this is what the link does/looks like when the user has not completed the try
224 $temp .= get_string("notcompleted", "lesson");
225 $temp .= "&nbsp;".userdate($try["timestart"])."</a>";
226 $timetotake = NULL;
228 // build up the attempts array
229 $attempts[] = $temp;
231 // run these lines for the stats only if the user finnished the lesson
232 if ($try["grade"] !== NULL) {
233 $numofattempts++;
234 $avescore += $try["grade"];
235 $avetime += $timetotake;
236 if ($try["grade"] > $highscore || $highscore == NULL) {
237 $highscore = $try["grade"];
239 if ($try["grade"] < $lowscore || $lowscore == NULL) {
240 $lowscore = $try["grade"];
242 if ($timetotake > $hightime || $hightime == NULL) {
243 $hightime = $timetotake;
245 if ($timetotake < $lowtime || $lowtime == NULL) {
246 $lowtime = $timetotake;
250 // get line breaks in after each attempt
251 $attempts = implode("<br />\n", $attempts);
252 // add it to the table data[] object
253 $table->data[] = array($studentname, $attempts, $bestgrade."%");
256 // print it all out !
257 if (has_capability('mod/lesson:edit', $context)) {
258 echo "<form id=\"theform\" method=\"post\" action=\"report.php\">\n
259 <input type=\"hidden\" name=\"sesskey\" value=\"".sesskey()."\" />\n
260 <input type=\"hidden\" name=\"id\" value=\"$cm->id\" />\n
261 <input type=\"hidden\" name=\"id\" value=\"$cm->id\" />\n";
263 print_table($table);
265 if (has_capability('mod/lesson:edit', $context)) {
266 echo '<br /><table width="90%" align="center"><tr><td>'.
267 '<a href="javascript: checkall();">'.get_string('selectall').'</a> / '.
268 '<a href="javascript: checknone();">'.get_string('deselectall').'</a> ';
270 $options = array();
271 $options['delete'] = get_string('deleteselected');
272 choose_from_menu($options, 'attemptaction', 0, 'choose', 'submitFormById(\'theform\')');
274 echo '</td></tr></table></form>';
277 // some stat calculations
278 if ($numofattempts == 0) {
279 $avescore = get_string("notcompleted", "lesson");
280 } else {
281 $avescore = format_float($avescore/$numofattempts, 2);
283 if ($avetime == NULL) {
284 $avetime = get_string("notcompleted", "lesson");
285 } else {
286 $avetime = format_float($avetime/$numofattempts, 0);
287 $avetime = format_time($avetime);
289 if ($hightime == NULL) {
290 $hightime = get_string("notcompleted", "lesson");
291 } else {
292 $hightime = format_time($hightime);
294 if ($lowtime == NULL) {
295 $lowtime = get_string("notcompleted", "lesson");
296 } else {
297 $lowtime = format_time($lowtime);
299 if ($highscore == NULL) {
300 $highscore = get_string("notcompleted", "lesson");
302 if ($lowscore == NULL) {
303 $lowscore = get_string("notcompleted", "lesson");
306 // output the stats
307 print_heading(get_string('lessonstats', 'lesson'));
308 $stattable = new stdClass;
309 $stattable->head = array(get_string('averagescore', 'lesson'), get_string('averagetime', 'lesson'),
310 get_string('highscore', 'lesson'), get_string('lowscore', 'lesson'),
311 get_string('hightime', 'lesson'), get_string('lowtime', 'lesson'));
312 $stattable->align = array("center", "center", "center", "center", "center", "center");
313 $stattable->wrap = array("nowrap", "nowrap", "nowrap", "nowrap", "nowrap", "nowrap");
314 $stattable->width = "90%";
315 $stattable->data[] = array($avescore.'%', $avetime, $highscore.'%', $lowscore.'%', $hightime, $lowtime);
317 print_table($stattable);
319 /**************************************************************************
320 this action is for a student detailed view and for the general detailed view
322 General flow of this section of the code
323 1. Generate a object which holds values for the statistics for each question/answer
324 2. Cycle through all the pages to create a object. Foreach page, see if the student actually answered
325 the page. Then process the page appropriatly. Display all info about the question,
326 Highlight correct answers, show how the user answered the question, and display statistics
327 about each page
328 3. Print out info about the try (if needed)
329 4. Print out the object which contains all the try info
331 **************************************************************************/
332 else if ($action == 'reportdetail') {
334 $formattextdefoptions->para = false; //I'll use it widely in this page
336 $userid = optional_param('userid', NULL, PARAM_INT); // if empty, then will display the general detailed view
337 $try = optional_param('try', NULL, PARAM_INT);
339 if (! $lessonpages = get_records("lesson_pages", "lessonid", $lesson->id)) {
340 error("Could not find Lesson Pages");
342 if (! $pageid = get_field("lesson_pages", "id", "lessonid", $lesson->id, "prevpageid", 0)) {
343 error("Could not find first page");
346 // now gather the stats into an object
347 $firstpageid = $pageid;
348 $pagestats = array();
349 while ($pageid != 0) { // EOL
350 $page = $lessonpages[$pageid];
352 if ($allanswers = get_records_select("lesson_attempts", "lessonid = $lesson->id AND pageid = $page->id", "timeseen")) {
353 // get them ready for processing
354 $orderedanswers = array();
355 foreach ($allanswers as $singleanswer) {
356 // ordering them like this, will help to find the single attempt record that we want to keep.
357 $orderedanswers[$singleanswer->userid][$singleanswer->retry][] = $singleanswer;
359 // this is foreach user and for each try for that user, keep one attempt record
360 foreach ($orderedanswers as $orderedanswer) {
361 foreach($orderedanswer as $tries) {
362 if(count($tries) > $lesson->maxattempts) { // if there are more tries than the max that is allowed, grab the last "legal" attempt
363 $temp = $tries[$lesson->maxattempts - 1];
364 } else {
365 // else, user attempted the question less than the max, so grab the last one
366 $temp = end($tries);
368 // page interpretation
369 // depending on the page type, process stat info for that page
370 switch ($page->qtype) {
371 case LESSON_MULTICHOICE:
372 case LESSON_TRUEFALSE:
373 if ($page->qoption) {
374 $userresponse = explode(",", $temp->useranswer);
375 foreach ($userresponse as $response) {
376 if (isset($pagestats[$temp->pageid][$response])) {
377 $pagestats[$temp->pageid][$response]++;
378 } else {
379 $pagestats[$temp->pageid][$response] = 1;
382 } else {
383 if (isset($pagestats[$temp->pageid][$temp->answerid])) {
384 $pagestats[$temp->pageid][$temp->answerid]++;
385 } else {
386 $pagestats[$temp->pageid][$temp->answerid] = 1;
389 if (isset($pagestats[$temp->pageid]["total"])) {
390 $pagestats[$temp->pageid]["total"]++;
391 } else {
392 $pagestats[$temp->pageid]["total"] = 1;
394 break;
395 case LESSON_SHORTANSWER:
396 case LESSON_NUMERICAL:
397 if (isset($pagestats[$temp->pageid][$temp->useranswer])) {
398 $pagestats[$temp->pageid][$temp->useranswer]++;
399 } else {
400 $pagestats[$temp->pageid][$temp->useranswer] = 1;
402 if (isset($pagestats[$temp->pageid]["total"])) {
403 $pagestats[$temp->pageid]["total"]++;
404 } else {
405 $pagestats[$temp->pageid]["total"] = 1;
407 break;
408 case LESSON_MATCHING:
409 if ($temp->correct) {
410 if (isset($pagestats[$temp->pageid]["correct"])) {
411 $pagestats[$temp->pageid]["correct"]++;
412 } else {
413 $pagestats[$temp->pageid]["correct"] = 1;
416 if (isset($pagestats[$temp->pageid]["total"])) {
417 $pagestats[$temp->pageid]["total"]++;
418 } else {
419 $pagestats[$temp->pageid]["total"] = 1;
421 break;
422 case LESSON_ESSAY:
423 $essayinfo = unserialize($temp->useranswer);
424 if ($essayinfo->graded) {
425 if (isset($pagestats[$temp->pageid])) {
426 $essaystats = $pagestats[$temp->pageid];
427 $essaystats->totalscore += $essayinfo->score;
428 $essaystats->total++;
429 $pagestats[$temp->pageid] = $essaystats;
430 } else {
431 $essaystats->totalscore = $essayinfo->score;
432 $essaystats->total = 1;
433 $pagestats[$temp->pageid] = $essaystats;
436 break;
441 } else {
442 // no one answered yet...
444 //unset($orderedanswers); initialized above now
445 $pageid = $page->nextpageid;
450 $answerpages = array();
451 $answerpage = "";
452 $pageid = $firstpageid;
453 // cycle through all the pages
454 // foreach page, add to the $answerpages[] array all the data that is needed
455 // from the question, the users attempt, and the statistics
456 // grayout pages that the user did not answer and Branch, end of branch, cluster
457 // and end of cluster pages
458 while ($pageid != 0) { // EOL
459 $page = $lessonpages[$pageid];
460 $answerpage = new stdClass;
461 $data ='';
462 $answerdata = new stdClass;
464 $answerpage->title = format_string($page->title);
466 $options = new stdClass;
467 $options->noclean = true;
468 $answerpage->contents = format_text($page->contents, FORMAT_MOODLE, $options);
470 // get the page qtype
471 switch ($page->qtype) {
472 case LESSON_ESSAY :
473 case LESSON_MATCHING :
474 case LESSON_TRUEFALSE :
475 case LESSON_NUMERICAL :
476 $answerpage->qtype = $LESSON_QUESTION_TYPE[$page->qtype];
477 $answerpage->grayout = 0;
478 break;
479 case LESSON_SHORTANSWER :
480 $answerpage->qtype = $LESSON_QUESTION_TYPE[$page->qtype];
481 if ($page->qoption) {
482 $answerpage->qtype .= " - ".get_string("casesensitive", "lesson");
484 $answerpage->grayout = 0;
485 break;
486 case LESSON_MULTICHOICE :
487 $answerpage->qtype = $LESSON_QUESTION_TYPE[$page->qtype];
488 if ($page->qoption) {
489 $answerpage->qtype .= " - ".get_string("multianswer", "lesson");
491 $answerpage->grayout = 0;
492 break;
493 case LESSON_BRANCHTABLE :
494 $answerpage->qtype = get_string("branchtable", "lesson");
495 $answerpage->grayout = 1;
496 break;
497 case LESSON_ENDOFBRANCH :
498 $answerpage->qtype = get_string("endofbranch", "lesson");
499 $answerpage->grayout = 1;
500 break;
501 case LESSON_CLUSTER :
502 $answerpage->qtype = get_string("clustertitle", "lesson");
503 $answerpage->grayout = 1;
504 break;
505 case LESSON_ENDOFCLUSTER :
506 $answerpage->qtype = get_string("endofclustertitle", "lesson");
507 $answerpage->grayout = 1;
508 break;
512 if (empty($userid)) {
513 // there is no userid, so set these vars and display stats.
514 $answerpage->grayout = 0;
515 $useranswer = NULL;
516 $answerdata->score = NULL;
517 $answerdata->response = NULL;
518 } elseif ($useranswers = get_records_select("lesson_attempts",
519 "lessonid = $lesson->id AND userid = $userid AND retry = $try AND pageid = $page->id", "timeseen")) {
520 // get the user's answer for this page
521 // need to find the right one
522 $i = 0;
523 foreach ($useranswers as $userattempt) {
524 $useranswer = $userattempt;
525 $i++;
526 if ($lesson->maxattempts == $i) {
527 break; // reached maxattempts, break out
530 } else {
531 // user did not answer this page, gray it out and set some nulls
532 $answerpage->grayout = 1;
533 $useranswer = NULL;
534 $answerdata->score = NULL;
535 $answerdata->response = NULL;
538 // build up the answer data
539 if ($answers = get_records("lesson_answers", "pageid", $page->id, "id")) {
540 $i = 0;
541 $n = 0;
542 // go through each answer and display it properly with statistics, highlight if correct answer,
543 // and display what the user entered
544 foreach ($answers as $answer) {
545 switch ($page->qtype) {
546 case LESSON_MULTICHOICE:
547 case LESSON_TRUEFALSE:
548 if ($page->qoption) {
549 if ($useranswer == NULL) {
550 $userresponse = array();
551 } else {
552 $userresponse = explode(",", $useranswer->useranswer);
554 if (in_array($answer->id, $userresponse)) {
555 // make checked
556 $data = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />";
557 if (!isset($answerdata->response)) {
558 if ($answer->response == NULL) {
559 if ($useranswer->correct) {
560 $answerdata->response = get_string("thatsthecorrectanswer", "lesson");
561 } else {
562 $answerdata->response = get_string("thatsthewronganswer", "lesson");
564 } else {
565 $answerdata->response = $answer->response;
568 if (!isset($answerdata->score)) {
569 if ($lesson->custom) {
570 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
571 } elseif ($useranswer->correct) {
572 $answerdata->score = get_string("receivedcredit", "lesson");
573 } else {
574 $answerdata->score = get_string("didnotreceivecredit", "lesson");
577 } else {
578 // unchecked
579 $data = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />";
581 if (($answer->score > 0 && $lesson->custom) || (lesson_iscorrect($page->id, $answer->jumpto) && !$lesson->custom)) {
582 $data .= "<font class=highlight>".format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."</font>";
583 } else {
584 $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions);
586 } else {
587 if ($useranswer != NULL and $answer->id == $useranswer->answerid) {
588 // make checked
589 $data = "<input readonly=\"readonly\" disabled=\"disabled\" name=\"answer[$i]\" checked=\"checked\" type=\"checkbox\" value=\"1\" />";
590 if ($answer->response == NULL) {
591 if ($useranswer->correct) {
592 $answerdata->response = get_string("thatsthecorrectanswer", "lesson");
593 } else {
594 $answerdata->response = get_string("thatsthewronganswer", "lesson");
596 } else {
597 $answerdata->response = $answer->response;
599 if ($lesson->custom) {
600 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
601 } elseif ($useranswer->correct) {
602 $answerdata->score = get_string("receivedcredit", "lesson");
603 } else {
604 $answerdata->score = get_string("didnotreceivecredit", "lesson");
606 } else {
607 // unchecked
608 $data = "<input type=\"checkbox\" readonly=\"readonly\" name=\"answer[$i]\" value=\"0\" disabled=\"disabled\" />";
610 if (($answer->score > 0 && $lesson->custom) || (lesson_iscorrect($page->id, $answer->jumpto) && !$lesson->custom)) {
611 $data .= "<font class=\"highlight\">".format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions)."</font>";
612 } else {
613 $data .= format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions);
616 if (isset($pagestats[$page->id][$answer->id])) {
617 $percent = $pagestats[$page->id][$answer->id] / $pagestats[$page->id]["total"] * 100;
618 $percent = round($percent, 2);
619 $percent .= "% ".get_string("checkedthisone", "lesson");
620 } else {
621 $percent = get_string("noonecheckedthis", "lesson");
624 $answerdata->answers[] = array($data, $percent);
625 break;
626 case LESSON_SHORTANSWER:
627 case LESSON_NUMERICAL:
628 if ($useranswer == NULL && $i == 0) {
629 // I have the $i == 0 because it is easier to blast through it all at once.
630 if (isset($pagestats[$page->id])) {
631 $stats = $pagestats[$page->id];
632 $total = $stats["total"];
633 unset($stats["total"]);
634 foreach ($stats as $valentered => $ntimes) {
635 $data = '<input type="text" size="50" disabled="disabled" readonly="readonly" value="'.s($valentered).'" />';
636 $percent = $ntimes / $total * 100;
637 $percent = round($percent, 2);
638 $percent .= "% ".get_string("enteredthis", "lesson");
639 $answerdata->answers[] = array($data, $percent);
641 } else {
642 $answerdata->answers[] = array(get_string("nooneansweredthisquestion", "lesson"), " ");
644 $i++;
645 } else if ($useranswer != NULL and $answer->id == $useranswer->answerid) {
646 // get in here when a user answer matches one of the answers to the page
647 $data = '<input type="text" size="50" disabled="disabled" readonly="readonly" value="'.s($useranswer->useranswer).'">';
648 if (isset($pagestats[$page->id][$useranswer->useranswer])) {
649 $percent = $pagestats[$page->id][$useranswer->useranswer] / $pagestats[$page->id]["total"] * 100;
650 $percent = round($percent, 2);
651 $percent .= "% ".get_string("enteredthis", "lesson");
652 } else {
653 $percent = get_string("nooneenteredthis", "lesson");
655 $answerdata->answers[] = array($data, $percent);
657 if ($answer->response == NULL) {
658 if ($useranswer->correct) {
659 $answerdata->response = get_string("thatsthecorrectanswer", "lesson");
660 } else {
661 $answerdata->response = get_string("thatsthewronganswer", "lesson");
663 } else {
664 $answerdata->response = $answer->response;
666 if ($lesson->custom) {
667 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
668 } elseif ($useranswer->correct) {
669 $answerdata->score = get_string("receivedcredit", "lesson");
670 } else {
671 $answerdata->score = get_string("didnotreceivecredit", "lesson");
673 } elseif ($answer == end($answers) && empty($answerdata) && $useranswer != NULL) {
674 // get in here when what the user entered is not one of the answers
675 $data = '<input type="text" size="50" disabled="disabled" readonly="readonly" value="'.s($useranswer->useranswer).'">';
676 if (isset($pagestats[$page->id][$useranswer->useranswer])) {
677 $percent = $pagestats[$page->id][$useranswer->useranswer] / $pagestats[$page->id]["total"] * 100;
678 $percent = round($percent, 2);
679 $percent .= "% ".get_string("enteredthis", "lesson");
680 } else {
681 $percent = get_string("nooneenteredthis", "lesson");
683 $answerdata->answers[] = array($data, $percent);
685 $answerdata->response = get_string("thatsthewronganswer", "lesson");
686 if ($lesson->custom) {
687 $answerdata->score = get_string("pointsearned", "lesson").": 0";
688 } else {
689 $answerdata->score = get_string("didnotreceivecredit", "lesson");
692 break;
693 case LESSON_MATCHING:
694 if ($n == 0 && $useranswer->correct) {
695 if ($answer->response == NULL && $useranswer != NULL) {
696 $answerdata->response = get_string("thatsthecorrectanswer", "lesson");
697 } else {
698 $answerdata->response = $answer->response;
700 } elseif ($n == 1 && !$useranswer->correct) {
701 if ($answer->response == NULL && $useranswer != NULL) {
702 $answerdata->response = get_string("thatsthewronganswer", "lesson");
703 } else {
704 $answerdata->response = $answer->response;
706 } elseif ($n > 1) {
707 if ($n == 2 && $useranswer->correct && $useranswer != NULL) {
708 if ($lesson->custom) {
709 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
710 } else {
711 $answerdata->score = get_string("receivedcredit", "lesson");
713 } elseif ($n == 3 && !$useranswer->correct && $useranswer != NULL) {
714 if ($lesson->custom) {
715 $answerdata->score = get_string("pointsearned", "lesson").": ".$answer->score;
716 } else {
717 $answerdata->score = get_string("didnotreceivecredit", "lesson");
720 $data = "<select disabled=\"disabled\"><option selected>".strip_tags(format_text($answer->answer,FORMAT_MOODLE,$formattextdefoptions))."</option></select>";
721 if ($useranswer != NULL) {
722 $userresponse = explode(",", $useranswer->useranswer);
723 $data .= "<select disabled=\"disabled\"><option selected>".strip_tags(format_string($answers[$userresponse[$i]]->response,FORMAT_PLAIN,$formattextdefoptions))."</option></select>";
724 } else {
725 $data .= "<select disabled=\"disabled\"><option selected>".strip_tags(format_string($answer->response,FORMAT_PLAIN,$formattextdefoptions))."</option></select>";
728 if ($n == 2) {
729 if (isset($pagestats[$page->id])) {
730 $percent = $pagestats[$page->id]["correct"] / $pagestats[$page->id]["total"] * 100;
731 $percent = round($percent, 2);
732 $percent .= "% ".get_string("answeredcorrectly", "lesson");
733 } else {
734 $percent = get_string("nooneansweredthisquestion", "lesson");
736 } else {
737 $percent = "";
740 $answerdata->answers[] = array($data, $percent);
741 $i++;
743 $n++;
744 break;
745 case LESSON_ESSAY :
746 if ($useranswer != NULL) {
747 $essayinfo = unserialize($useranswer->useranswer);
748 if ($essayinfo->response == NULL) {
749 $answerdata->response = get_string("nocommentyet", "lesson");
750 } else {
751 $answerdata->response = s($essayinfo->response);
753 if (isset($pagestats[$page->id])) {
754 $percent = $pagestats[$page->id]->totalscore / $pagestats[$page->id]->total * 100;
755 $percent = round($percent, 2);
756 $percent = get_string("averagescore", "lesson").": ". $percent ."%";
757 } else {
758 // dont think this should ever be reached....
759 $percent = get_string("nooneansweredthisquestion", "lesson");
761 if ($essayinfo->graded) {
762 if ($lesson->custom) {
763 $answerdata->score = get_string("pointsearned", "lesson").": ".$essayinfo->score;
764 } elseif ($essayinfo->score) {
765 $answerdata->score = get_string("receivedcredit", "lesson");
766 } else {
767 $answerdata->score = get_string("didnotreceivecredit", "lesson");
769 } else {
770 $answerdata->score = get_string("havenotgradedyet", "lesson");
772 } else {
773 $essayinfo->answer = get_string("didnotanswerquestion", "lesson");
776 if (isset($pagestats[$page->id])) {
777 $avescore = $pagestats[$page->id]->totalscore / $pagestats[$page->id]->total;
778 $avescore = round($avescore, 2);
779 $avescore = get_string("averagescore", "lesson").": ". $avescore ;
780 } else {
781 // dont think this should ever be reached....
782 $avescore = get_string("nooneansweredthisquestion", "lesson");
784 $answerdata->answers[] = array(s(stripslashes_safe($essayinfo->answer)), $avescore);
785 break;
786 case LESSON_BRANCHTABLE :
787 $data = "<input type=\"button\" name=\"$answer->id\" value=\"".strip_tags(format_text($answer->answer, FORMAT_MOODLE,$formattextdefoptions))."\" disabled=\"disabled\"> ";
788 $data .= get_string('jumpsto', 'lesson', lesson_get_jump_name($answer->jumpto));
790 $answerdata->answers[] = array($data, "");
791 $answerpage->grayout = 1; // always grayed out
792 break;
793 case LESSON_ENDOFBRANCH :
794 case LESSON_CLUSTER :
795 case LESSON_ENDOFCLUSTER :
796 $data = get_string('jumpsto', 'lesson', lesson_get_jump_name($answer->jumpto));
798 $answerdata->answers[] = array($data, "");
799 $answerpage->grayout = 1; // always grayed out
800 break;
802 if (isset($answerdata)) {
803 $answerpage->answerdata = $answerdata;
806 $answerpages[] = $answerpage;
808 $pageid = $page->nextpageid;
811 /// actually start printing something
812 $table = new stdClass;
813 $table->wrap = array();
814 $table->width = "60%";
817 if (!empty($userid)) {
818 // if looking at a students try, print out some basic stats at the top
820 // print out users name
821 //$headingobject->lastname = $students[$userid]->lastname;
822 //$headingobject->firstname = $students[$userid]->firstname;
823 //$headingobject->attempt = $try + 1;
824 //print_heading(get_string("studentattemptlesson", "lesson", $headingobject));
825 print_heading(get_string('attempt', 'lesson', $try+1));
827 $table->head = array();
828 $table->align = array("right", "left");
829 $table->class = 'generaltable userinfotable';
831 if (!$grades = get_records_select("lesson_grades", "lessonid = $lesson->id and userid = $userid", "completed", "*", $try, 1)) {
832 $grade = -1;
833 $completed = -1;
834 } else {
835 $grade = current($grades);
836 $completed = $grade->completed;
837 $grade = round($grade->grade, 2);
839 if (!$times = get_records_select("lesson_timer", "lessonid = $lesson->id and userid = $userid", "starttime", "*", $try, 1)) {
840 $timetotake = -1;
841 } else {
842 $timetotake = current($times);
843 $timetotake = $timetotake->lessontime - $timetotake->starttime;
846 if ($timetotake == -1 || $completed == -1 || $grade == -1) {
847 $table->align = array("center");
849 $table->data[] = array(get_string("notcompleted", "lesson"));
850 } else {
851 $user = $students[$userid];
853 $gradeinfo = lesson_grade($lesson, $try, $user->id);
855 $table->data[] = array($course->student.':', print_user_picture($user->id, $course->id, $user->picture, 0, true).fullname($user, true));
856 $table->data[] = array(get_string("timetaken", "lesson").":", format_time($timetotake));
857 $table->data[] = array(get_string("completed", "lesson").":", userdate($completed));
858 $table->data[] = array(get_string('rawgrade', 'lesson').':', $gradeinfo->earned.'/'.$gradeinfo->total);
859 $table->data[] = array(get_string("grade", "lesson").":", $grade."%");
861 print_table($table);
863 // Don't want this class for later tables
864 unset($table->class);
865 echo "<br />";
869 $table->align = array("left", "left");
870 $table->size = array("70%", "*");
872 foreach ($answerpages as $page) {
873 unset($table->data);
874 if ($page->grayout) { // set the color of text
875 $fontstart = "<span class=\"dimmed\">";
876 $fontend = "</font>";
877 $fontstart2 = $fontstart;
878 $fontend2 = $fontend;
879 } else {
880 $fontstart = "";
881 $fontend = "";
882 $fontstart2 = "";
883 $fontend2 = "";
886 $table->head = array($fontstart2.$page->qtype.": ".format_string($page->title).$fontend2, $fontstart2.get_string("classstats", "lesson").$fontend2);
887 $table->data[] = array($fontstart.get_string("question", "lesson").": <br />".$fontend.$fontstart2.$page->contents.$fontend2, " ");
888 $table->data[] = array($fontstart.get_string("answer", "lesson").":".$fontend);
889 // apply the font to each answer
890 foreach ($page->answerdata->answers as $answer){
891 $modified = array();
892 foreach ($answer as $single) {
893 // need to apply a font to each one
894 $modified[] = $fontstart2.$single.$fontend2;
896 $table->data[] = $modified;
898 if ($page->answerdata->response != NULL) {
899 $table->data[] = array($fontstart.get_string("response", "lesson").": <br />".$fontend.$fontstart2.format_text($page->answerdata->response,FORMAT_MOODLE,$formattextdefoptions).$fontend2, " ");
901 $table->data[] = array($page->answerdata->score, " ");
902 print_table($table);
903 echo "<br />";
907 else {
908 error("Fatal Error: Unknown Action: ".$action."\n");
911 /// Finish the page
912 print_footer($course);