Quiz question completion

Re: Quiz question completion

by Tim Hunt -
Number of replies: 3
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

I think question_engine_data_mapper::load_questions_usages_latest_steps() is the method you are looking for.

https://github.com/moodle/moodle/blob/master/question/engine/datalib.php#L554


In reply to Tim Hunt

Re: Quiz question completion

by Michael Ko -

Thanks again Tim for your fantastic suggestion.

It reduced the process of determining a quiz's completion from 500ms to 60ms for a 134 question quiz.

Unfortunately, this 60ms is still too much (given these progress bars are on a landing page with a list of up to 30 quizzes), so I've had to go against best practices and directly execute a slightly modified version of the query triggered by: 

question_engine_data_mapper::load_questions_usages_latest_steps()

As follows:

$sql = "SELECT COUNT(*)
FROM {question_attempts} qa
JOIN {question_attempt_steps} qas
ON qas.questionattemptid = qa.id
AND qas.sequencenumber = (SELECT MAX(sequencenumber) FROM {question_attempt_steps} WHERE questionattemptid = qa.id)
WHERE qa.questionusageid = ?
AND state = ?";
$num_answered = $DB->count_records_sql($sql, array($question_usage_id, 'complete'));
This query takes approx 13-25ms to execute.

Thanks again

In reply to Michael Ko

Re: Quiz question completion

by Michael Ko -

In fact hard coding 

AND qas.sequencenumber = (SELECT MAX(sequencenumber) FROM {question_attempt_steps} WHERE questionattemptid = qa.id)

to AND qas.sequencenumber = 1

reduces the time to 1ms

In reply to Michael Ko

Re: Quiz question completion

by Tim Hunt -
Picture of Core developers Picture of Documentation writers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Well, replacing the whole query with

SELECT 1

would be even faster still. There is no point speeding up the query by changing it to give the wrong answer.

Your fundamental problem is doing one DB query for each quiz attempt. You should be trying to load all the data for all attempts in one query, and you can, using the method I suggested, if you understand the qubaid_condition part of the API.

Average of ratings: Useful (1)