I'd appreciate any hint on how to fix Moodle's grade algorithm to take unfinished but answered quizzes into account.
Hi Haruhiko,
This is due to a security mechanism that removes the grade if a student gets past the deadline without submitting. To save the grades of individual students you could extend the deadline (and turn off the timer if you had it enabled) and manually submit the quizzes.
I would not know how to change the quiz coding, but I guess the best way around the problem is to give clear instructions to the students to submit their work on time (or face the consequences).
Rgrds,
Paul.
Could we agree on the following desirable scenario?
A certain Quiz has a deadline.
Students take the Quiz.
Most students actually finish and submit their Quiz in time before the deadline.
A few students answer some (or all) of the questions but forget (or do not have the time) to submit their quiz before the deadline.
- When the deadline date & time has been reached for that certain Quiz, then Moodle automatically a) checks students' attempts and b) submits all those attempts which have not already been sumbitted.
- OR when the teacher view the students' attempts for that certain Quiz, they have a "Submit all non-submitted attempts" button which enables them to just do that, manually but for all non-submitted attempts at once, rather than one by one.
What do you think?
Joseph
I think your second solution is easier to implement.
A "Submit all non-submitted attempts" button triggers a command like:
modify_database("", "UPDATE prefix_quiz_attempts SET timefinish=timemodified WHERE quiz={$quiz->id};");
mod/quiz/report/overview/report.php:
/// Only print headers if not asked to download data
if (!$download = optional_param('download', NULL)) {
$this->print_header_and_tabs($cm, $course, $quiz, $reportmode="overview");
}
/// addition:
if (optional_param('finishall', NULL) == "YES") {
modify_database("", "UPDATE prefix_quiz_attempts SET timefinish=timemodified WHERE quiz={$quiz->id};");
}
...
if (!empty($attempts)) {
...
helpbutton("download", get_string("download","quiz"), "quiz");
echo "</td></tr>\n";
echo '<tr><td colspan="3" align="center">';
unset($options["download"]);
$options["finishall"] = "YES";
print_single_button('report.php', $options, get_string("finishall","quiz"));
echo "</td>\n";
echo '</tr></table>';
}
}
elseif ($download == 'Excel') {
$workbook->close();
}
elseif ($download == 'CSV') {
exit;
}
lang/*/quiz.php:
$string['finishall'] = 'Finish all unfinished tests';
$action = optional_param('action', '');
switch($action) {
case 'delete': /// Some attempts need to be deleted
...
break;
case 'recalculate':
$attemptids = isset($_POST['attemptid']) ? $_POST['attemptid'] : array();
if(!is_array($attemptids) || empty($attemptids)) {
break;
}
foreach($attemptids as $num => $attemptid) {
if(empty($attemptid)) {
unset($attemptids[$num]);
}
}
foreach($attemptids as $attemptid) {
if ($toupdate = get_record('quiz_attempts', 'id', $attemptid)) {
$userid = $toupdate->userid;
if (record_exists('quiz_attempts', 'userid', $userid, 'quiz', $quiz->id)) {
quiz_save_best_grade($quiz, $userid);
}
}
}
break;
}
...
$options = array('delete' => get_string('delete'), 'recalculate' => "Recalculate");
Check all and "Recalculate" should update the grades.
Joseph
But a better solution might be to always store the current (best) quiz record in the grade data.
Joseph
should be
if (optional_param('finishall', NULL) == "YES") {
The added code closes an attempt by registering the "event" of the last state as submitted.
The implication of comments by Tim Hunt in
http://tracker.moodle.org/browse/MDL-3030
is that this is likely to be tricky to implement. Does the code in this thread work well or have side effects?
Graham
http://moodle.org/mod/forum/discuss.php?d=118343