Skip to content

Commit

Permalink
New modular plugin structure for quiz reports.
Browse files Browse the repository at this point in the history
The code for reviewing an existing attempt is now separate
in review.php and now has a log entry of it's own.

The overview and regrade reports are now in separate subdirectories
under the "report" directory.  Each has a primary "report.php" file
which implements the report as a class.

These existing reports are very simple, but now more complex ones
can easily be written.  (I am about to do one).
  • Loading branch information
moodler committed Jul 24, 2003
1 parent 350a05c commit 29d5d0b
Show file tree
Hide file tree
Showing 13 changed files with 329 additions and 185 deletions.
3 changes: 3 additions & 0 deletions lang/en/quiz.php
Expand Up @@ -121,6 +121,9 @@
$string['regradecount'] = "\$a->changed out of \$a->attempt grades were changed";
$string['rename'] = "Rename";
$string['report'] = "Reports";
$string['reportoverview'] = "Overview";
$string['reportregrade'] = "Regrade attempts";
$string['review'] = "Review";
$string['save'] = "Save";
$string['savegrades'] = "Save grades";
$string['savemyanswers'] = "Save my answers";
Expand Down
4 changes: 4 additions & 0 deletions mod/quiz/db/mysql.php
Expand Up @@ -105,6 +105,10 @@ function quiz_upgrade($oldversion) {
) TYPE=MyISAM COMMENT='Options for numerical questions'; ");
}

if ($oldversion < 2003072400) {
execute_sql(" INSERT INTO {$CFG->prefix}log_display VALUES ('quiz', 'review', 'quiz', 'name') ");
}

return true;
}

Expand Down
1 change: 1 addition & 0 deletions mod/quiz/db/mysql.sql
Expand Up @@ -249,4 +249,5 @@ INSERT INTO prefix_log_display VALUES ('quiz', 'view', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'report', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'attempt', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'submit', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'review', 'quiz', 'name');

5 changes: 5 additions & 0 deletions mod/quiz/db/postgres7.php
Expand Up @@ -69,6 +69,11 @@ function quiz_upgrade($oldversion) {
); ");
modify_database ("", "CREATE INDEX prefix_quiz_numerical_answer_idx ON prefix_quiz_numerical (answer);");
}

if ($oldversion < 2003072400) {
execute_sql(" INSERT INTO {$CFG->prefix}log_display VALUES ('quiz', 'review', 'quiz', 'name') ");
}

return true;
}

Expand Down
1 change: 1 addition & 0 deletions mod/quiz/db/postgres7.sql
Expand Up @@ -223,4 +223,5 @@ INSERT INTO prefix_log_display VALUES ('quiz', 'view', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'report', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'attempt', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'submit', 'quiz', 'name');
INSERT INTO prefix_log_display VALUES ('quiz', 'review', 'quiz', 'name');

19 changes: 17 additions & 2 deletions mod/quiz/lib.php
Expand Up @@ -1234,9 +1234,9 @@ function quiz_get_user_attempts_string($quiz, $attempts, $bestgrade) {
foreach ($attempts as $attempt) {
$attemptgrade = format_float(($attempt->sumgrades / $quiz->sumgrades) * $quiz->grade);
if ($attemptgrade == $bestgrade) {
$userattempts[] = "<SPAN CLASS=highlight><A HREF=\"report.php?q=$quiz->id&attempt=$attempt->id\">$attemptgrade</A></SPAN>";
$userattempts[] = "<span class=highlight><a href=\"review.php?q=$quiz->id&attempt=$attempt->id\">$attemptgrade</a></span>";
} else {
$userattempts[] = "<A HREF=\"report.php?q=$quiz->id&attempt=$attempt->id\">$attemptgrade</A>";
$userattempts[] = "<a href=\"review.php?q=$quiz->id&attempt=$attempt->id\">$attemptgrade</a>";
}
}
return implode(",", $userattempts);
Expand Down Expand Up @@ -1987,6 +1987,21 @@ function quiz_save_question_options($question) {
}


function quiz_remove_unwanted_questions(&$questions, $quiz) {
/// Used by review.php

$quizquestions = array();
$quizids = explode(",", $quiz->questions);
foreach ($quizids as $quizid) {
$quizquestions[$quizid] = true;
}
foreach ($questions as $key => $question) {
if (!isset($quizquestions[$question->id])) {
unset($questions[$key]);
}
}
}



?>
198 changes: 23 additions & 175 deletions mod/quiz/report.php
@@ -1,16 +1,14 @@
<?PHP // $Id$

// This page prints a particular instance of quiz
// This script uses installed report plugins to print quiz reports

require_once("../../config.php");
require_once("lib.php");

optional_variable($id); // Course Module ID, or
optional_variable($q); // quiz ID

optional_variable($attempt); // A particular attempt ID
optional_variable($review); // A particular attempt ID for review by student
optional_variable($regrade); // Regrade all attempts
optional_variable($mode, "overview"); // Report mode

if ($id) {
if (! $cm = get_record("course_modules", "id", $id)) {
Expand Down Expand Up @@ -39,210 +37,60 @@

require_login($course->id);


if (!isteacher($course->id)) {
if (!$quiz->review) {
error(get_string("noreview", "quiz"));
}
if (time() < $quiz->timeclose) {
error(get_string("noreviewuntil", "quiz", userdate($quiz->timeclose)));
}
if (empty($review)) {
error("You are using this script wrongly.");
}
}

if (!empty($review)) {
$attempt = $review;
error("You are not allowed to use this script");
}

add_to_log($course->id, "quiz", "report", "report.php?id=$cm->id", "$quiz->id");

// Print the page header
/// Print the page header

if ($course->category) {
$navigation = "<A HREF=\"../../course/view.php?id=$course->id\">$course->shortname</A> ->";
$navigation = "<a href=\"../../course/view.php?id=$course->id\">$course->shortname</a> ->";
}

$strquizzes = get_string("modulenameplural", "quiz");
$strquiz = get_string("modulename", "quiz");
$strreport = get_string("report", "quiz");
$strname = get_string("name");
$strattempts = get_string("attempts", "quiz");
$strscore = get_string("score", "quiz");
$strgrade = get_string("grade");
$strbestgrade = get_string("bestgrade", "quiz");
$strtimetaken = get_string("timetaken", "quiz");
$strtimecompleted = get_string("timecompleted", "quiz");

print_header("$course->shortname: $quiz->name", "$course->fullname",
"$navigation <A HREF=index.php?id=$course->id>$strquizzes</A>
-> <A HREF=\"view.php?id=$cm->id\">$quiz->name</A> -> $strreport",
-> <a href=\"view.php?id=$cm->id\">$quiz->name</a> -> $strreport",
"", "", true);

print_heading($quiz->name);


if (!empty($attempt)) { // Show a particular attempt

if (! $attempt = get_record("quiz_attempts", "id", $attempt)) {
error("No such attempt ID exists");
}

if (!isteacher($course->id)) {
if ($attempt->userid != $USER->id) {
error("This is not your attempt!");
}
}

if (! $questions = quiz_get_attempt_responses($attempt, $quiz)) {
error("Could not reconstruct quiz results for attempt $attempt->id!");
}

quiz_remove_unwanted_questions($questions, $quiz);

if (!$result = quiz_grade_attempt_results($quiz, $questions)) {
error("Could not re-grade this quiz attempt!");
}

if ($timetaken = ($attempt->timefinish - $attempt->timestart)) {
$timetaken = format_time($timetaken);
} else {
$timetaken = "-";
}

$table->align = array("RIGHT", "LEFT");
$table->data[] = array("$strtimetaken:", $timetaken);
$table->data[] = array("$strtimecompleted:", userdate($attempt->timefinish));
$table->data[] = array("$strscore:", "$result->sumgrades/$quiz->sumgrades ($result->percentage %)");
$table->data[] = array("$strgrade:", "$result->grade/$quiz->grade");
print_table($table);

if (empty($review)) {
print_continue("report.php?q=$quiz->id");
} else {
print_continue("view.php?q=$quiz->id");
}

$quiz->feedback = true;
$quiz->correctanswers = true;
$quiz->shuffleanswers = false;
$quiz->shufflequestions = false;
quiz_print_quiz_questions($quiz, $result, $questions);
/// Print list of available quiz reports

if (empty($review)) {
print_continue("report.php?q=$quiz->id");
$reports = get_list_of_plugins("mod/quiz/report");
echo "<table cellpadding=10 align=center><tr>";
foreach ($reports as $report) {
$strreport = get_string("report$report", "quiz");
if ($report == $mode) {
echo "<td><u>$strreport</u></td>";
} else {
print_continue("view.php?q=$quiz->id");
echo "<td><a href=\"report.php?id=$cm->id&mode=$report\">$strreport</a></td>";
}
print_footer($course);
exit;
}
echo "</tr></table><br /><br />";

if (!empty($regrade)) {
if (!$attempts = get_records("quiz_attempts", "quiz", $quiz->id)) {
print_header(get_string("noattempts", "quiz"));
print_continue("report.php?id=$cm->id");
print_footer($course);
exit;
}

$users = array();
$count->attempt = 0;
$count->changed = 0;
foreach ($attempts as $attempt) {

set_time_limit(120);

if (!$attempt->timefinish) { // Skip incomplete attempts
continue;
}

$count->attempt++;

if (! $questions = quiz_get_attempt_responses($attempt, $quiz)) {
error("Could not reconstruct quiz results for attempt $attempt->id!");
}
quiz_remove_unwanted_questions($questions, $quiz);

if (!$result = quiz_grade_attempt_results($quiz, $questions)) {
error("Could not re-grade this quiz attempt!");
}

if ($attempt->sumgrades != $result->sumgrades) {
$attempt->sumgrades = $result->sumgrades;
$count->changed++;
/// Open the selected quiz report and display it

if (! update_record("quiz_attempts", $attempt)) {
notify("Could not regrade attempt $attempt->id");
}
}

$users[$attempt->userid] = $attempt->userid;
}

if ($users) {
foreach ($users as $userid) {
if (! quiz_save_best_grade($quiz, $userid)) {
notify("Could not save best grade for user $userid!");
}
}
}
print_heading(get_string("regradecomplete", "quiz"));
print_heading(get_string("regradecount", "quiz", $count));
print_continue("report.php?id=$cm->id");
print_footer($course);
exit;
if (! is_readable("report/$mode/report.php")) {
error("Report not known ($mode)");
}

if (!$grades = quiz_get_grade_records($quiz)) {
print_footer($course);
exit;
}

$table->head = array("&nbsp;", $strname, $strattempts, "$strbestgrade /$quiz->grade");
$table->align = array("CENTER", "LEFT", "LEFT", "CENTER");
$table->width = array(10, "*", "*", 20);

foreach ($grades as $grade) {
$picture = print_user_picture($grade->userid, $course->id, $grade->picture, false, true);
include("report/default.php"); // Parent class
include("report/$mode/report.php");

if ($attempts = quiz_get_user_attempts($quiz->id, $grade->userid)) {
$userattempts = quiz_get_user_attempts_string($quiz, $attempts, $grade->grade);
}
$report = new quiz_report();

$table->data[] = array ($picture,
"<A HREF=\"$CFG->wwwroot/user/view.php?id=$grade->userid&course=$course->id\">$grade->firstname $grade->lastname</A>",
"$userattempts", round($grade->grade,0));
if (! $report->display($quiz, $cm, $course)) { // Do anything before that we need to
error("Error occurred during pre-processing!");
}

print_table($table);

echo "<CENTER><P>";
$options["regrade"] = "true";
$options["id"] = $cm->id;
print_single_button("report.php", $options, get_string("regrade", "quiz"));
echo "</P></CENTER>";

// Finish the page
print_footer($course);


function quiz_remove_unwanted_questions(&$questions, $quiz) {

$quizquestions = array();
$quizids = explode(",", $quiz->questions);
foreach ($quizids as $quizid) {
$quizquestions[$quizid] = true;
}
foreach ($questions as $key => $question) {
if (!isset($quizquestions[$question->id])) {
unset($questions[$key]);
}
}
}




?>
26 changes: 26 additions & 0 deletions mod/quiz/report/default.php
@@ -0,0 +1,26 @@
<?PHP // $Id$

////////////////////////////////////////////////////////////////////
/// Default class for report plugins
///
/// Doesn't do anything on it's own -- it needs to be extended.
/// This class displays quiz reports. Because it is called from
/// within /mod/quiz/report.php you can assume that the page header
/// and footer are taken care of.
///
/// This file can refer to itself as report.php to pass variables
/// to itself - all these will also be globally available. You must
/// pass "id=$cm->id" or q=$quiz->id", and "mode=reportname".
////////////////////////////////////////////////////////////////////

// Included by ../report.php

class quiz_default_report {

function display($cm, $course, $quiz) { /// This function just displays the report
return true;
}

}

?>
42 changes: 42 additions & 0 deletions mod/quiz/report/overview/report.php
@@ -0,0 +1,42 @@
<?PHP // $Id$

/// Overview report just displays a big table of all the attempts

class quiz_report extends quiz_default_report {

function display($quiz, $cm, $course) { /// This function just displays the report

global $CFG;

if (!$grades = quiz_get_grade_records($quiz)) {
return;
}

$strname = get_string("name");
$strattempts = get_string("attempts", "quiz");
$strbestgrade = get_string("bestgrade", "quiz");

$table->head = array("&nbsp;", $strname, $strattempts, "$strbestgrade /$quiz->grade");
$table->align = array("center", "left", "left", "center");
$table->width = array(10, "*", "*", 20);

foreach ($grades as $grade) {
$picture = print_user_picture($grade->userid, $course->id, $grade->picture, false, true);

if ($attempts = quiz_get_user_attempts($quiz->id, $grade->userid)) {
$userattempts = quiz_get_user_attempts_string($quiz, $attempts, $grade->grade);
}

$table->data[] = array ($picture,
"<a href=\"$CFG->wwwroot/user/view.php?id=$grade->userid&course=$course->id\">".
"$grade->firstname $grade->lastname</a>",
"$userattempts", round($grade->grade,0));
}

print_table($table);

return true;
}
}

?>

0 comments on commit 29d5d0b

Please sign in to comment.