$string['gradeessays'] = 'Grade Essays';
$string['gradehighest'] = 'Highest grade';
$string['grademethod'] = 'Grading method';
+$string['gradesofar'] = '$a->method: $a->mygrade / $a->quizgrade.';
$string['gradingdetails'] = 'Marks for this submission: $a->raw/$a->max.';
$string['gradingdetailsadjustment'] = 'With previous penalties this gives <strong>$a->cur/$a->max</strong>.';
$string['gradingdetailspenalty'] = 'This submission attracted a penalty of $a.';
$string['xhtml'] = 'XHTML Format';
$string['xml'] = 'Moodle XML format';
$string['xmltypeunsupported'] = 'Question type $a is not supported by xml import';
-$string['yourfinalgradeis'] = 'Your final grade for this quiz is $a';
+$string['yourfinalgradeis'] = 'Your final grade for this quiz is $a.';
$string['zerosignificantfiguresnotallowed'] = 'The correct answer cannot have zero significant figures!';
?>
* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
* @package quiz
*/
-
require_once("../../config.php");
require_once("locallib.php");
$id = required_param('id', PARAM_INT);
-
- if (! $course = get_record("course", "id", $id)) {
+ if (!$course = get_record("course", "id", $id)) {
error("Course ID is incorrect");
}
-
+ $coursecontext = get_context_instance(CONTEXT_COURSE, $id);
require_login($course->id);
-
add_to_log($course->id, "quiz", "view all", "index.php?id=$course->id", "");
-
// Print the header
-
$strquizzes = get_string("modulenameplural", "quiz");
- $streditquestions = has_capability('moodle/question:manage', get_context_instance(CONTEXT_COURSE, $course->id))
- ? "<form target=\"_parent\" method=\"get\" "
- ." action=\"$CFG->wwwroot/question/edit.php\">"
- ."<input type=\"hidden\" name=\"courseid\" "
- ." value=\"$course->id\" />"
- ."<input type=\"submit\" "
- ." value=\"".get_string("editquestions", "quiz")."\" /></form>"
-
- : "";
- $strquiz = get_string("modulename", "quiz");
-
- print_header_simple("$strquizzes", "", "$strquizzes",
- "", "", true, $streditquestions, navmenu($course));
+ $streditquestions = '';
+ if (has_capability('moodle/question:manage', $coursecontext)) {
+ $streditquestions =
+ "<form target=\"_parent\" method=\"get\" action=\"$CFG->wwwroot/question/edit.php\">
+ <input type=\"hidden\" name=\"courseid\" value=\"$course->id\" />
+ <input type=\"submit\" value=\"".get_string("editquestions", "quiz")."\" />
+ </form>";
+ }
+ print_header_simple($strquizzes, '', $strquizzes,
+ '', '', true, $streditquestions, navmenu($course));
// Get all the appropriate data
-
- if (! $quizzes = get_all_instances_in_course("quiz", $course)) {
+ if (!$quizzes = get_all_instances_in_course("quiz", $course)) {
notice("There are no quizzes", "../../course/view.php?id=$course->id");
die;
}
-// Print the list of instances (your module will probably extend this)
-
- $timenow = time();
- $strname = get_string("name");
- $strweek = get_string("week");
- $strtopic = get_string("topic");
- $strbestgrade = get_string("bestgrade", "quiz");
- $strquizcloses = get_string("quizcloses", "quiz");
- $strattempts = get_string("attempts", "quiz");
- $strusers = $course->students;
-
- $context = get_context_instance(CONTEXT_COURSE, $id);
- if (has_capability('mod/quiz:viewreports', $context)) {
- $gradecol = $strattempts;
- } else {
- $gradecol = $strbestgrade;
- }
-
+// Configure table for displaying the list of instances.
+ $headings = array(get_string('name'), get_string('quizcloses', 'quiz'));
+ $align = array('left', 'left');
+ $colsize = array('', '');
if ($course->format == "weeks") {
- $table->head = array ($strweek, $strname, $strquizcloses, $gradecol);
- $table->align = array ("center", "left", "left", "left");
- $table->size = array (10, "", "", "");
+ array_unshift($headings, get_string('week'));
+ array_unshift($align, 'center');
+ array_unshift($colsize, 10);
} else if ($course->format == "topics") {
- $table->head = array ($strtopic, $strname, $strquizcloses, $gradecol);
- $table->align = array ("center", "left", "left", "left");
- $table->size = array (10, "", "", "");
- } else {
- $table->head = array ($strname, $strquizcloses, $gradecol);
- $table->align = array ("left", "left", "left");
- $table->size = array ("", "", "");
+ array_unshift($headings, get_string('topic'));
+ array_unshift($align, 'center');
+ array_unshift($colsize, 10);
}
- $currentsection = "";
+ if (has_capability('mod/quiz:viewreports', $coursecontext)) {
+ array_push($headings, get_string('attempts', 'quiz'));
+ array_push($align, 'left');
+ array_push($colsize, '');
+ $showing = 'stats';
+ } else if (has_capability('mod/quiz:attempt', $coursecontext)) {
+ array_push($headings, get_string('bestgrade', 'quiz'), get_string('feedback', 'quiz'));
+ array_push($align, 'left', 'left');
+ array_push($colsize, '', '');
+ $showing = 'scores';
+ }
+ $table->head = $headings;
+ $table->align = $align;
+ $table->size = $colsize;
+
+// Poplate the table with the list of instances.
+ $currentsection = '';
foreach ($quizzes as $quiz) {
-
+
$cm = get_coursemodule_from_instance('quiz', $quiz->id);
$context = get_context_instance(CONTEXT_MODULE, $cm->id);
-
- if (!$quiz->visible) {
- //Show dimmed if the mod is hidden
- $link = "<a class=\"dimmed\" href=\"view.php?id=$quiz->coursemodule\">".format_string($quiz->name,true)."</a>";
- } else {
- //Show normal if the mod is visible
- $link = "<a href=\"view.php?id=$quiz->coursemodule\">".format_string($quiz->name,true)."</a>";
- }
-
- $bestgrade = quiz_get_best_grade($quiz, $USER->id);
+ $data = array();
- $printsection = "";
- if ($quiz->section !== $currentsection) {
- if ($quiz->section) {
- $printsection = $quiz->section;
- }
- if ($currentsection !== "") {
- $table->data[] = 'hr';
+ // Section number if necessary.
+ $strsection = '';
+ if ($course->format == "weeks" or $course->format == "topics") {
+ if ($quiz->section !== $currentsection) {
+ if ($quiz->section) {
+ $strsection = $quiz->section;
+ }
+ if ($currentsection !== "") {
+ $table->data[] = 'hr';
+ }
+ $currentsection = $quiz->section;
}
- $currentsection = $quiz->section;
}
+ $data[] = $strsection;
- $closequiz = $quiz->timeclose ? userdate($quiz->timeclose) : '';
+ // Link to the instance.
+ $class = '';
+ if (!$quiz->visible) {
+ $class = ' class="dimmed"';
+ }
+ $data[] = "<a$class href=\"view.php?id=$quiz->coursemodule\">" . format_string($quiz->name, true) . '</a>';
+
+ // Close date.
+ if ($quiz->timeclose) {
+ $data[] = userdate($quiz->timeclose);
+ } else {
+ $data[] = '';
+ }
- $gradecol = '';
- $feedbackcol = '';
+ if ($showing == 'stats') {
- if (has_capability('mod/quiz:viewreports', $context)) {
+ // Number of students who have attempted this quiz.
if ($a->attemptnum = count_records('quiz_attempts', 'quiz', $quiz->id, 'preview', 0)) {
- $a->studentnum = count_records_select('quiz_attempts', "quiz = '$quiz->id' AND preview = '0'", 'COUNT(DISTINCT userid)');
+ $a->studentnum = count_records_select('quiz_attempts',
+ "quiz = '$quiz->id' AND preview = '0'", 'COUNT(DISTINCT userid)');
$a->studentstring = $course->students;
- $gradecol = "<a href=\"report.php?mode=overview&q=$quiz->id\">".get_string('numattempts', 'quiz', $a).'</a>';
+ $data[] = "<a href=\"report.php?mode=overview&q=$quiz->id\">" .
+ get_string('numattempts', 'quiz', $a) . '</a>';
}
- } else {
- // If student has no grade for this quiz,
- // or the quiz has no grade, display nothing in grade col
- if ($bestgrade !== NULL && $quiz->grade != 0) {
- //If all quiz's attempts have visible results, show bestgrade
- if (all_attempt_results_visible($quiz, $USER)) {
- $gradecol = "$bestgrade / $quiz->grade";
- $feedbackcol = quiz_feedback_for_grade($bestgrade, $quiz->id);
+ } else if ($showing = 'scores') {
+
+ // Grade and feedback.
+ $bestgrade = quiz_get_best_grade($quiz, $USER->id);
+ $attempts = quiz_get_user_attempts($quiz->id, $USER->id, 'all');
+ list($someoptions, $alloptions) = quiz_get_combined_reviewoptions($quiz, $attempts, $context);
+
+ $grade = '';
+ $feedback = '';
+ if ($quiz->grade && !is_null($bestgrade)) {
+ if ($alloptions->scores) {
+ $grade = "$bestgrade / $quiz->grade";
+ }
+ if ($alloptions->overallfeedback) {
+ $feedback = quiz_feedback_for_grade($bestgrade, $quiz->id);
}
}
+ $data[] = $grade;
+ $data[] = $feedback;
}
- if ($course->format == "weeks" or $course->format == "topics") {
- $table->data[] = array ($printsection, $link, $closequiz, $gradecol, $feedbackcol);
- } else {
- $table->data[] = array ($link, $closequiz, $gradecol, $feedbackcol);
- }
- }
+ $table->data[] = $data;
+ } // End of loop over quiz instances.
+// Display the table.
echo '<br />';
-
print_table($table);
// Finish the page
-
print_footer($course);
-
?>
/**
* Returns an unfinished attempt (if there is one) for the given
* user on the given quiz. This function does not return preview attempts.
- *
+ *
* @param integer $quizid the id of the quiz.
* @param integer $userid the id of the user.
- *
- * @return mixed the unfinished attempt if there is one, false if not.
+ *
+ * @return mixed the unfinished attempt if there is one, false if not.
*/
function quiz_get_user_attempt_unfinished($quizid, $userid) {
- return get_record_select("quiz_attempts", "quiz = $quizid AND userid = $userid AND timefinish = 0 AND preview = 0");
+ $attempts = quiz_get_user_attempts($quizid, $userid, 'unfinished');
+ if ($attempts) {
+ return array_shift($attempts);
+ } else {
+ return false;
+ }
}
/**
* @param integer $quizid the quiz id.
* @param integer $userid the userid.
- * @return an array of all the ueser's attempts at this quiz. Returns an empty array if there are none.
+ * @param string $status 'all', 'finished' or 'unfinished' to control
+ * @return an array of all the user's attempts at this quiz. Returns an empty array if there are none.
*/
-function quiz_get_user_attempts($quizid, $userid) {
- if ($attempts = get_records_select("quiz_attempts", "quiz = '$quizid' AND userid = '$userid' AND timefinish > 0",
- "attempt ASC")) {
- return $attempts;
+function quiz_get_user_attempts($quizid, $userid, $status = 'finished') {
+ $status_condition = array(
+ 'all' => '',
+ 'finished' => ' AND timefinish > 0',
+ 'unfinished' => ' AND timefinish = 0'
+ );
+ if ($attempts = get_records_select('quiz_attempts',
+ "quiz = '$quizid' AND userid = '$userid' AND preview = 0" . $status_condition[$status],
+ 'attempt ASC')) {
+ return $attempts;
} else {
return array();
}
/**
* Get the best current grade for a particular user in a quiz.
- *
+ *
* @param object $quiz the quiz object.
* @param integer $userid the id of the user.
* @return float the user's current grade for this quiz.
/**
* Convert the raw grade stored in $attempt into a grade out of the maximum
* grade for this quiz.
- *
+ *
* @param float $rawgrade the unadjusted grade, fof example $attempt->sumgrades
* @param object $quiz the quiz object. Only the fields grade, sumgrades and decimalpoints are used.
* @return float the rescaled grade.
/**
* Get the feedback text that should be show to a student who
* got this grade on this quiz.
- *
+ *
* @param float $grade a grade on this quiz.
* @param integer $quizid the id of the quiz object.
* @return string the comment that corresponds to this grade (empty string if there is not one.
if (empty($feedback)) {
$feedback = '';
}
-
+
return $feedback;
}
}
/**
- * The quiz grade is the score that student's results are marked out of. When it
+ * The quiz grade is the score that student's results are marked out of. When it
* changes, the corresponding data in quiz_grades and quiz_feedback needs to be
* rescaled.
- *
+ *
* @param float $newgrade the new maximum grade for the quiz.
* @param object $quiz the quiz we are updating. Passed by reference so its grade field can be updated too.
* @return boolean indicating success or failure.
// Use a transaction, so that on those databases that support it, this is safer.
begin_sql();
-
+
// Update the quiz table.
$success = set_field('quiz', 'grade', $newgrade, 'id', $quiz->instance);
-
+
// Rescaling the other data is only possible if the old grade was non-zero.
if ($quiz->grade > 1e-7) {
global $CFG;
-
+
$factor = $newgrade/$quiz->grade;
$quiz->grade = $newgrade;
WHERE quizid = $quiz->id
", false);
}
-
+
if ($success) {
return commit_sql();
} else {
// Calculate the best grade
$bestgrade = quiz_calculate_best_grade($quiz, $attempts);
$bestgrade = quiz_rescale_grade($bestgrade, $quiz);
-
+
// Save the best grade in the database
if ($grade = get_record('quiz_grades', 'quiz', $quiz->id, 'userid', $userid)) {
$grade->grade = $bestgrade;
*/
function quiz_get_renderoptions($reviewoptions, $state) {
$options = new stdClass;
-
+
// Show the question in readonly (review) mode if the question is in
// the closed state
$options->readonly = question_state_is_closed($state);
// Show general feedback if the question has been graded and the quiz allows it.
$options->generalfeedback = question_state_is_graded($state) && ($reviewoptions & QUIZ_REVIEW_GENERALFEEDBACK & QUIZ_REVIEW_IMMEDIATELY);
+ // Show overallfeedback once the attempt is over.
+ $options->overallfeedback = false;
+
// Always show responses and scores
$options->responses = true;
$options->scores = true;
/**
* Determine review options
- *
+ *
* @param object $quiz the quiz instance.
* @param object $attempt the attempt in question.
* @param $context the roles and permissions context,
* normally the context for the quiz module instance.
- *
+ *
* @return object an object with boolean fields responses, scores, feedback,
* correct_responses, solutions and general feedback
*/
$options->correct_responses = true;
$options->solutions = false;
$options->generalfeedback = true;
-
+ $options->overallfeedback = true;
+
// Show a link to the comment box only for closed attempts
if ($attempt->timefinish) {
$options->questioncommentlink = '/mod/quiz/comment.php';
$options->correct_responses = ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_ANSWERS) ? 1 : 0;
$options->solutions = ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_SOLUTIONS) ? 1 : 0;
$options->generalfeedback = ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_GENERALFEEDBACK) ? 1 : 0;
+ $options->overallfeedback = $attempt->timefinish && ($quiz->review & $quiz_state_mask & QUIZ_REVIEW_FEEDBACK);
}
-
+
return $options;
}
-////////////////////////////////////////////////////////////////////////////////
+
/**
-* Return boolean indicating if the quiz has attempts with hidden grades
-*
-* Selects all attempts matching specified quiz & user, and examines each to
-* check they all have visible results.
-* @return boolean If the quiz has attempts without visible results
-* @param object $quiz The quiz being examined
-* @param object $user The user concerned
-*/
-function all_attempt_results_visible($quiz, $user) {
- global $CFG;
- $sql = 'SELECT timefinish, preview FROM '.$CFG->prefix.'quiz_attempts qa'.
- ' WHERE qa.quiz='.$quiz->id.' AND qa.userid='.$user->id.
- ' ORDER BY id DESC';
- if ($attempts = get_records_sql($sql)) {
- foreach ($attempts as $attempt) {
- $attemptoptions = quiz_get_reviewoptions($quiz, $attempt);
- //if any attempt has scores option not set, not all attempt results are
- //visible
- if (!$attemptoptions->scores) {
- return false;
- }
- }
+ * Combines the review options from a number of different quiz attempts.
+ * Returns an array of two ojects, so he suggested way of calling this
+ * funciton is:
+ * list($someoptions, $alloptions) = quiz_get_combined_reviewoptions(...)
+ *
+ * @param object $quiz the quiz instance.
+ * @param array $attempts an array of attempt objects.
+ * @param $context the roles and permissions context,
+ * normally the context for the quiz module instance.
+ *
+ * @return array of two options objects, one showing which options are true for
+ * at least one of the attempts, the other showing which options are true
+ * for all attempts.
+ */
+function quiz_get_combined_reviewoptions($quiz, $attempts, $context=null) {
+ $fields = array('readonly', 'scores', 'feedback', 'correct_responses', 'solutions', 'generalfeedback', 'overallfeedback');
+ $someoptions = new stdClass;
+ $alloptions = new stdClass;
+ foreach ($fields as $field) {
+ $someoptions->$field = false;
+ $alloptions->$field = true;
}
- return true;
+ foreach ($attempts as $attempt) {
+ $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $context);
+ $someoptions->$field = $someoptions->$field || $attemptoptions->$field;
+ $alloptions->$field = $someoptions->$field && $attemptoptions->$field;
+ }
+ return array($someoptions, $alloptions);
}
-
?>
if (! $cm = get_coursemodule_from_instance("quiz", $quiz->id, $course->id)) {
error("The course module for the quiz with id $quiz->id is missing");
}
-
+
$grade = quiz_rescale_grade($attempt->sumgrades, $quiz);
$feedback = quiz_feedback_for_grade($grade, $attempt->quiz);
$result->sumgrades = "0";
$result->grade = "0.0";
}
-
+
$a = new stdClass;
$percentage = round(($attempt->sumgrades/$quiz->sumgrades)*100, 0);
$a->grade = $grade;
$table->data[] = array("$strgrade:", get_string('outof', 'quiz', $a));
}
}
- if ($options->feedback && $feedback) {
+ if ($options->overallfeedback && $feedback) {
$table->data[] = array(get_string('feedback', 'quiz'), $feedback);
}
if ($isteacher and $attempt->userid == $USER->id) {
$currenttab = 'info';
include('tabs.php');
- // Print quiz name
+ // Print quiz name
print_heading(format_string($quiz->name));
if ($attempts) {
// Work out which columns we need, taking account what data is available in each attempt.
- $gradecolumn = 0;
- $overallstats = 1;
- foreach ($attempts as $attempt) {
- $attemptoptions = quiz_get_reviewoptions($quiz, $attempt, $context);
- if ($attemptoptions->scores) {
- $gradecolumn = 1;
- } else {
- $overallstats = 0;
- }
- }
- $gradecolumn = $gradecolumn && $quiz->grade && $quiz->sumgrades;
- $markcolumn = $gradecolumn && ($quiz->grade <> $quiz->sumgrades);
+ list($someoptions, $alloptions) = quiz_get_combined_reviewoptions($quiz, $attempts, $context);
+
+ $gradecolumn = $someoptions->scores && $quiz->grade && $quiz->sumgrades;
+ $markcolumn = $gradecolumn && ($quiz->grade != $quiz->sumgrades);
+ $overallstats = $alloptions->scores;
+
$feedbackcolumn = quiz_has_feedback($quiz->id);
+ $overallfeedback = $feedbackcolumn && $alloptions->overallfeedback;
// prepare table header
$table->head = array($strattempt, $strtimecompleted);
}
if ($feedbackcolumn) {
- if ($attemptoptions->feedback) {
+ if ($attemptoptions->overallfeedback) {
$row[] = quiz_feedback_for_grade($attemptgrade, $quiz->id);
} else {
$row[] = '';
print_heading(get_string("nomoreattempts", "quiz"));
}
- if ($numattempts && $quiz->sumgrades) {
- if (!is_null($mygrade)) {
+ if ($numattempts && $quiz->sumgrades && !is_null($mygrade)) {
+ if ($overallstats) {
if ($available && $moreattempts) {
- $strbestgrade = $QUIZ_GRADE_METHOD[$quiz->grademethod];
- $grademessage = "$strbestgrade: $mygrade / $quiz->grade.";
+ $a = new stdClass;
+ $a->method = $QUIZ_GRADE_METHOD[$quiz->grademethod];
+ $a->mygrade = $mygrade;
+ $a->quizgrade = $quiz->grade;
+ print_heading(get_string('gradesofar', 'quiz', $a));
} else {
- $grademessage = get_string("yourfinalgradeis", "quiz", "$mygrade / $quiz->grade");
- }
-
- if ($overallstats) {
- print_heading($grademessage);
- }
-
- if ($feedbackcolumn) {
- echo '<p align="center">', quiz_feedback_for_grade($mygrade, $quiz->id), '</p>';
+ print_heading(get_string('yourfinalgradeis', 'quiz', "$mygrade / $quiz->grade"));
}
}
- if (!($moreattempts && $available)) {
- print_continue($CFG->wwwroot . '/course/view.php?id=' . $course->id);
+ if ($overallfeedback) {
+ echo '<p align="center">', quiz_feedback_for_grade($mygrade, $quiz->id), '</p>';
}
}
// Print a button to start/continue an attempt, if appropriate.
- if ($quiz->questions && $available && $moreattempts) {
+ if (!$quiz->questions) {
+ print_heading(get_string("noquestions", "quiz"));
+
+ } else if ($available && $moreattempts) {
echo "<br />";
echo "<div align=\"center\">";
$buttontext = get_string('reattemptquiz', 'quiz');
}
- // Work out if the quiz is temporarily unavailable becuase of the delay option.
+ // Work out if the quiz is temporarily unavailable because of the delay option.
if (!empty($attempts)) {
$tempunavailable = '';
$lastattempt = end($attempts);
// If so, display a message and prevent the start button from appearing.
if ($tempunavailable) {
print_simple_box($tempunavailable, "center");
+ print_continue($CFG->wwwroot . '/course/view.php?id=' . $course->id);
$buttontext = '';
}
}
$buttontext = htmlspecialchars($buttontext, ENT_QUOTES);
// Do we need a confirm javascript alert?
- $strconfirmstartattempt = '';
- if ($quiz->timelimit && $quiz->attempts) {
+ if ($unfinished) {
+ $strconfirmstartattempt = '';
+ } else if ($quiz->timelimit && $quiz->attempts) {
$strconfirmstartattempt = addslashes(get_string('confirmstartattempttimelimit','quiz', $quiz->attempts));
} else if ($quiz->timelimit) {
$strconfirmstartattempt = addslashes(get_string('confirmstarttimelimit','quiz'));
} else if ($quiz->attempts) {
$strconfirmstartattempt = addslashes(get_string('confirmstartattemptlimit','quiz', $quiz->attempts));
+ } else {
+ $strconfirmstartattempt = '';
}
// Prepare options depending on whether the quiz should be a popup.
}
echo "</div>\n";
-
- } else if (!$quiz->questions) {
- print_heading(get_string("noquestions", "quiz"));
+ } else {
+ print_continue($CFG->wwwroot . '/course/view.php?id=' . $course->id);
}
}
if (!$attempt->timefinish) {
return $linktext;
}
-
+
$url = "review.php?q=$quiz->id&attempt=$attempt->id";
if ($quiz->popup) {
$windowoptions = "left=0, top=0, channelmode=yes, fullscreen=yes, scrollbars=yes, resizeable=no, directories=no, toolbar=no, titlebar=no, location=no, status=no, menubar=no";