mirror of
https://github.com/moodle/moodle.git
synced 2025-03-23 09:00:30 +01:00
MDL-77094 quiz_statistics: improve efficiency of the recalculate task
quiz_settings::create() requires at least 3 DB queries, so the point is that we can avoid doing that until after we have worked out if we need to calculate statistics for this quiz. Also, we order the list of quizzes to consier, to process the ones with more recent attempts first.
This commit is contained in:
parent
67bbf6c416
commit
514b6f13d9
@ -16,6 +16,7 @@
|
||||
|
||||
namespace quiz_statistics\task;
|
||||
|
||||
use core\dml\sql_join;
|
||||
use quiz_attempt;
|
||||
use quiz;
|
||||
use quiz_statistics_report;
|
||||
@ -50,59 +51,61 @@ class recalculate extends \core\task\scheduled_task {
|
||||
|
||||
// TODO: MDL-75197, add quizid in quiz_statistics so that it is simpler to find quizzes for stats calculation.
|
||||
// Only calculate stats for quizzes which have recently finished attempt.
|
||||
$sql = "
|
||||
SELECT q.id AS quizid,
|
||||
q.name AS quizname,
|
||||
c.id AS courseid,
|
||||
c.shortname AS courseshortname,
|
||||
MAX(qa.timefinish) AS mostrecentattempttime,
|
||||
COUNT(1) AS numberofattempts
|
||||
FROM {quiz_attempts} qa
|
||||
JOIN {quiz} q ON q.id = qa.quiz
|
||||
JOIN {course} c ON c.id = q.course
|
||||
WHERE qa.preview = 0
|
||||
AND qa.state = :quizstatefinished
|
||||
GROUP BY q.id, q.name, c.id, c.shortname
|
||||
";
|
||||
$latestattempts = $DB->get_records_sql("
|
||||
SELECT q.id AS quizid,
|
||||
q.name AS quizname,
|
||||
q.grademethod AS quizgrademethod,
|
||||
c.id AS courseid,
|
||||
c.shortname AS courseshortname,
|
||||
MAX(quiza.timefinish) AS mostrecentattempttime,
|
||||
COUNT(1) AS numberofattempts
|
||||
|
||||
$params = [
|
||||
"quizstatefinished" => quiz_attempt::FINISHED,
|
||||
];
|
||||
FROM {quiz_attempts} quiza
|
||||
JOIN {quiz} q ON q.id = quiza.quiz
|
||||
JOIN {course} c ON c.id = q.course
|
||||
|
||||
$latestattempts = $DB->get_records_sql($sql, $params);
|
||||
WHERE quiza.preview = 0
|
||||
AND quiza.state = :quizstatefinished
|
||||
|
||||
GROUP BY q.id, q.name, q.grademethod, c.id, c.shortname
|
||||
ORDER BY MAX(quiza.timefinish) DESC
|
||||
", ["quizstatefinished" => quiz_attempt::FINISHED]);
|
||||
|
||||
$anyexception = null;
|
||||
foreach ($latestattempts as $attempt) {
|
||||
foreach ($latestattempts as $latestattempt) {
|
||||
if (time() >= $stoptime) {
|
||||
mtrace("This task has been running for more than " .
|
||||
format_time(self::TIME_LIMIT) . " so stopping this execution.");
|
||||
break;
|
||||
}
|
||||
|
||||
mtrace(" Examining quiz '$attempt->quizname' ($attempt->quizid) in course " .
|
||||
"$attempt->courseshortname ($attempt->courseid) with most recent attempt at " .
|
||||
userdate($attempt->mostrecentattempttime, $dateformat) . ".");
|
||||
$quizobj = quiz::create($attempt->quizid);
|
||||
$quiz = $quizobj->get_quiz();
|
||||
// Hash code for question stats option in question bank.
|
||||
$qubaids = quiz_statistics_qubaids_condition($quiz->id, new \core\dml\sql_join(), $quiz->grademethod);
|
||||
|
||||
// Check if there is any existing question stats, and it has been calculated after latest quiz attempt.
|
||||
$qubaids = quiz_statistics_qubaids_condition($latestattempt->quizid,
|
||||
new sql_join(), $latestattempt->quizgrademethod);
|
||||
$lateststatstime = $DB->get_field('quiz_statistics', 'COALESCE(MAX(timemodified), 0)',
|
||||
['hashcode' => $qubaids->get_hash_code()]);
|
||||
|
||||
if ($lateststatstime >= $attempt->mostrecentattempttime) {
|
||||
mtrace(" Statistics already calculated at " . userdate($lateststatstime, $dateformat) .
|
||||
" so nothing to do for this quiz.");
|
||||
$quizinfo = "'$latestattempt->quizname' ($latestattempt->quizid) in course " .
|
||||
"$latestattempt->courseshortname ($latestattempt->courseid) has most recent attempt finished at " .
|
||||
userdate($latestattempt->mostrecentattempttime, $dateformat);
|
||||
if ($lateststatstime) {
|
||||
$quizinfo .= " and statistics from " . userdate($lateststatstime, $dateformat);
|
||||
}
|
||||
|
||||
if ($lateststatstime >= $latestattempt->mostrecentattempttime) {
|
||||
mtrace(" " . $quizinfo . " so nothing to do.");
|
||||
continue;
|
||||
}
|
||||
|
||||
mtrace(" Calculating statistics for $attempt->numberofattempts attempts, starting at " .
|
||||
// OK, so we need to calculate for this quiz.
|
||||
mtrace(" " . $quizinfo . " so re-calculating statistics for $latestattempt->numberofattempts attempts, start time " .
|
||||
userdate(time(), $dateformat) . " ...");
|
||||
|
||||
try {
|
||||
$quizobj = quiz::create($latestattempt->quizid);
|
||||
$report = new quiz_statistics_report();
|
||||
$report->clear_cached_data($qubaids);
|
||||
$report->calculate_questions_stats_for_question_bank($quiz->id);
|
||||
$report->calculate_questions_stats_for_question_bank($quizobj->get_quizid());
|
||||
mtrace(" Calculations completed at " . userdate(time(), $dateformat) . ".");
|
||||
|
||||
} catch (\Throwable $e) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user