Skip to content

Commit

Permalink
fix: handle multiple attempt regrade for multianswer
Browse files Browse the repository at this point in the history
  • Loading branch information
Pol Torrent i Soler committed Mar 12, 2024
1 parent a84d32f commit 3905042
Showing 1 changed file with 36 additions and 9 deletions.
45 changes: 36 additions & 9 deletions question.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
require_once($CFG->dirroot . '/question/type/wq/step.php');

class qtype_shortanswerwiris_question extends qtype_wq_question
implements question_automatically_gradable, question_response_answer_comparer {
implements question_automatically_gradable, question_response_answer_comparer {
/**
* A link to last question attempt step and also a helper class for some
* grading issues.
Expand Down Expand Up @@ -84,9 +84,16 @@ public function grade_response(array $response) {
// Multiply Moodle fraction by quizzes grade (due to custom function
// grading or compound grade distribution).
$grade = $this->step->get_var('_matching_answer_grade');

if (empty($grade)) {
$responsehash = md5($response['answer']);
$grade = $this->step->get_var('_' . substr($responsehash, 0, 6) . '_matching_answer_grade');
}

if (!empty($grade)) {
$fraction = $fraction * $grade;
}

$state = question_state::graded_state_for_fraction($fraction);
return array($fraction, $state);
} else if ($this->step->is_error()) {
Expand All @@ -109,8 +116,11 @@ public function get_matching_answer_fail_test(array $response) {
$conditiona = isset($CFG->wq_fail_shortanswer_grade) && $CFG->wq_fail_shortanswer_grade;
if ($conditiona && $CFG->wq_fail_shortanswer_grade != 'false') {
$fail = explode("@", $CFG->wq_fail_shortanswer_grade);
$attemptid = $DB->get_record('question_attempt_steps',
array('id' => $this->step->step_id), 'questionattemptid')->questionattemptid;
$attemptid = $DB->get_record(
'question_attempt_steps',
array('id' => $this->step->step_id),
'questionattemptid'
)->questionattemptid;
$attemptid = $DB->get_record('question_attempts', array('id' => $attemptid), 'questionusageid')->questionusageid;
$activity = $DB->get_field('question_usages', 'component', array('id' => $attemptid));
if ($activity == 'mod_quiz') {
Expand All @@ -133,8 +143,11 @@ public function get_matching_answer_fail_test(array $response) {
}
// Used to simulate a grade failure when doing tests!
if ($error) {
throw new moodle_exception(get_string('failedtogradetest', 'qtype_shortanswerwiris',
($this->step->get_attempts() + 1)), 'qtype_wq');
throw new moodle_exception(get_string(
'failedtogradetest',
'qtype_shortanswerwiris',
($this->step->get_attempts() + 1)
), 'qtype_wq');
}
// END TEST.
}
Expand All @@ -145,10 +158,18 @@ public function get_matching_answer(array $response) {
if (!isset($response['answer']) || $response['answer'] === null) {
return null;
}

// Optimization in order to avoid a service call.
$responsehash = md5($response['answer']);
if ($this->step->get_var('_response_hash') == $responsehash) {
$cachedresponses = $this->step->get_var('_response_hash') ?? '';

if (str_contains($cachedresponses, $responsehash)) {
$matchinganswer = $this->step->get_var('_matching_answer');

if (empty($matchinganswer)) {
$matchinganswer = $this->step->get_var('_' . substr($responsehash, 0, 6) . '_matching_answer');
}

if (!empty($matchinganswer)) {
return $this->base->answers[$matchinganswer];
} else if (!is_null($matchinganswer)) {
Expand All @@ -162,6 +183,11 @@ public function get_matching_answer(array $response) {
return null;
}

if ($this->parent) {
// Questions with parent should be graded together in multianswerwiris qtype!
throw new moodle_exception('Questions with parent should be graded together');
}

// Test code:
// Does nothing on production, may throw exception on test environment.
$this->get_matching_answer_fail_test($response);
Expand Down Expand Up @@ -192,7 +218,7 @@ public function get_matching_answer(array $response) {
$max = 0.0;
$maxwqgrade = 0.0;
$matchinganswerposition = -1;

for ($i = 0; $i < count($correctanswers); $i++) {
$wqgrade = $qi->getAnswerGrade($i, 0, $this->wirisquestion);
$grade = $wqgrade * $correctanswers[$i]->fraction;
Expand All @@ -210,7 +236,7 @@ public function get_matching_answer(array $response) {
// Backup matching answer.
$matchinganswerid = 0;
$answer = null;

// Reset variable.
$this->step->set_var('_matching_answer_grade', null);
if ($matchinganswerposition != -1) {
Expand All @@ -219,8 +245,9 @@ public function get_matching_answer(array $response) {
if ($max < 1.0) {
$this->step->set_var('_matching_answer_grade', $maxwqgrade, true);
}
$this->step->set_var('_matching_answer_wq_position', $matchinganswerposition, true);
$this->step->set_var('_matching_answer_wq', $matchinganswerposition, true);
}

$this->step->set_var('_matching_answer', $matchinganswerid, true);
$this->step->set_var('_response_hash', $responsehash, true);
$this->step->set_var('_qi', $qi->serialize(), true);
Expand Down

0 comments on commit 3905042

Please sign in to comment.