diff --git a/lang/en/quiz.php b/lang/en/quiz.php index 079a2cbfa84..9710dd82b81 100644 --- a/lang/en/quiz.php +++ b/lang/en/quiz.php @@ -310,8 +310,11 @@ $string['reattemptquiz'] = 'Re-attempt quiz'; $string['recentlyaddedquestion'] = 'Recently added question!'; $string['recurse'] = 'Display questions from sub-categories too'; $string['regrade'] = 'Regrade all attempts'; +$string['regradeattempt'] = 'Regrading attempt #{$a->attempt}, $a->statecount states are being regraded'; $string['regradecomplete'] = 'All attempts have been regraded'; $string['regradecount'] = '$a->changed out of $a->attempt grades were changed'; +$string['regradedone'] = 'done. Changed grades for $a->changed states out of $a->statecount.'; +$string['regradequiz'] = 'Regrading Quiz $a->name'; $string['relative'] = 'Relative'; $string['remove'] = 'Remove'; $string['rename'] = 'Rename'; diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php index b06b99f0db1..6931baebb4e 100644 --- a/mod/quiz/locallib.php +++ b/mod/quiz/locallib.php @@ -1465,6 +1465,78 @@ function quiz_extract_responses($questions, $responses, $defaultevent) { } + + +function quiz_regrade_question_in_attempt($question, $attempt, $quiz=false, $verbose=false) { + if (!$quiz && !($quiz = get_record('quiz', 'id', $attempt->quiz))) { + $verbose && notify("Regrading of quiz #{$attempt->quiz} failed; " . + "Couldn't load quiz record from database!"); + return false; + } + + if ($states = get_records_select('quiz_states', + "attempt = '{$attempt->id}' ". + "AND question = '{$question->id}'", + 'seq_number ASC')) { + $states = array_values($states); + $attempt->sumgrades -= $states[count($states)-1]->grade; + + // Initialise the replaystate + quiz_restore_state($question, $states[0]); + $states[0]->sumpenalty = 0.0; + $replaystate = clone($states[0]); + $replaystate->last_graded = clone($states[0]); + if ($verbose) { + $a = new stdClass; + $a->attempt = $attempt->id; + $a->statecount = count($states); + print_string('regradeattempt', 'quiz', $a); + echo " . "; + } + $a->changed = 0; + $oldgrade = 0; + for($j = 1; $j < count($states); $j++) { + quiz_restore_state($question, $states[$j]); + $action = new stdClass; + $action->responses = $states[$j]->responses; + $action->timestamp = $states[$j]->timestamp; + + // Close the last state of a finished attempt + if (((count($states) - 1) === $j) && ($attempt->timefinish > 0)) { + $action->event = QUIZ_EVENTCLOSE; + + // Grade instead of closing, quiz_process_responses will then + // work out whether to close it + } else if (QUIZ_EVENTCLOSE == $states[$j]->event) { + $action->event = QUIZ_EVENTGRADE; + + // By default take the event that was saved in the database + } else { + $action->event = $states[$j]->event; + } + // Reprocess (regrade) responses + if (!quiz_process_responses($question, $replaystate, $action, $quiz, + $attempt)) { + $verbose && notify("Couldn't regrade state #{$state->id}!"); + } + + if ((float)$replaystate->raw_grade != (float)$states[$j]->raw_grade) { + $a->changed++; + } + + $verbose && print(". "); // Progress indicator + $replaystate->id = $states[$j]->id; + update_record('quiz_states', $replaystate); + } + update_record('quiz_attempts', $attempt); + quiz_save_best_grade($quiz, $attempt->userid); + $verbose && print_string('regradedone', 'quiz', $a); + $verbose && print("
"); + return true; + } + return true; +} + /** * For a given question instance we walk the complete history of states for * each user and recalculate the grades as we go along. @@ -1532,6 +1604,8 @@ function quiz_regrade_question_in_quizzes($question, $quizlist) { quiz_restore_state($question, $states[$j]); $action = new stdClass; $action->responses = $states[$j]->responses; + $action->timestamp = $states[$j]->timestamp; + // Close the last state of a finished attempt if (((count($states) - 1) === $j) && ($attempts[$i]->timefinish > 0)) { $action->event = QUIZ_EVENTCLOSE; diff --git a/mod/quiz/question.php b/mod/quiz/question.php index d1b8ca1b126..a01836c9eda 100644 --- a/mod/quiz/question.php +++ b/mod/quiz/question.php @@ -256,7 +256,7 @@ set_field('quiz_newest_states', 'questionid', $question->id, 'attemptid', $attempt->id, 'questionid', $oldquestionid); } - + // Now do anything question-type specific that is required to replace the question // For example questions that use the quiz_answers table to hold part of their question will // have to recode the answer ids in the states @@ -272,11 +272,12 @@ } if (empty($question->errors) && $QUIZ_QTYPES[$qtype]->finished_edit_wizard($form)) { + // DISABLED AUTOMATIC REGRADING // Automagically regrade all attempts (and states) in the affected quizzes - if (!empty($replaceinquiz)) { - $QUIZ_QTYPES[$question->qtype]->get_question_options($question); - quiz_regrade_question_in_quizzes($question, $replaceinquiz); - } + //if (!empty($replaceinquiz)) { + // $QUIZ_QTYPES[$question->qtype]->get_question_options($question); + // quiz_regrade_question_in_quizzes($question, $replaceinquiz); + //} redirect("edit.php"); } } diff --git a/mod/quiz/report/regrade/report.php b/mod/quiz/report/regrade/report.php index 0bb803d7aa3..7e5477138bb 100644 --- a/mod/quiz/report/regrade/report.php +++ b/mod/quiz/report/regrade/report.php @@ -9,13 +9,40 @@ class quiz_report extends quiz_default_report { function display($quiz, $cm, $course) { /// This function just displays the report global $CFG, $SESSION, $db, $QUIZ_QTYPES; + $strheading = get_string('regradequiz', 'quiz', $quiz); + $strnoattempts = get_string('noattempts'); + // 'There are no attempts for this quiz that could be regraded.'; + /// Print header $this->print_header_and_tabs($cm, $course, $quiz, $reportmode="regrade"); - notify('Not yet implemented'); + if (!$attempts = get_records('quiz_attempts', 'quiz', $quiz->id)) { + notify($strnoattempts); + return true; + } + + $sql = "SELECT q.*, i.grade AS maxgrade FROM {$CFG->prefix}quiz_questions q, + {$CFG->prefix}quiz_question_instances i + WHERE i.quiz = $quiz->id + AND i.question = q.id"; + + if (! $questions = get_records_sql($sql)) { + error("Failed to get questions for regrading!"); + } + quiz_get_question_options($questions); + + + print_heading($strheading); + print_simple_box_start('center', '70%'); + foreach ($attempts as $attempt) { + foreach ($questions as $question) { + quiz_regrade_question_in_attempt($question, $attempt, $quiz, true); + } + } + print_simple_box_end(); return true; } } -?> +?> \ No newline at end of file