From d7db097db1b3a4f7cb20103eb824197ff8bb7892 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Tue, 29 Oct 2013 16:19:24 +0000 Subject: [PATCH] MDL-42598 quiz variant randomisation not random enough. A student would get the same question variants (for example for a calculated question) on their first attempt at both copies of a duplicated quiz. --- mod/quiz/locallib.php | 3 ++- question/engine/lib.php | 11 +++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/mod/quiz/locallib.php b/mod/quiz/locallib.php index 4e350060eeb..9a6d82209b7 100644 --- a/mod/quiz/locallib.php +++ b/mod/quiz/locallib.php @@ -199,7 +199,8 @@ function quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $time } else { $variantoffset = $attemptnumber; } - $variantstrategy = new question_variant_pseudorandom_no_repeats_strategy($variantoffset); + $variantstrategy = new question_variant_pseudorandom_no_repeats_strategy( + $variantoffset, $attempt->userid, $quizobj->get_quizid()); if (!empty($forcedvariantsbyslot)) { $forcedvariantsbyseed = question_variant_forced_choices_selection_strategy::prepare_forced_choices_array( diff --git a/question/engine/lib.php b/question/engine/lib.php index 88c0065d418..c96659becd1 100644 --- a/question/engine/lib.php +++ b/question/engine/lib.php @@ -957,12 +957,15 @@ class question_variant_pseudorandom_no_repeats_strategy /** @var int the user id the attempt belongs to. */ protected $userid; + /** @var string extra input fed into the pseudo-random code. */ + protected $extrarandomness = ''; + /** * Constructor. * @param int $attemptno The attempt number. * @param int $userid the user the attempt is for (defaults to $USER->id). */ - public function __construct($attemptno, $userid = null) { + public function __construct($attemptno, $userid = null, $extrarandomness = '') { $this->attemptno = $attemptno; if (is_null($userid)) { global $USER; @@ -970,6 +973,10 @@ class question_variant_pseudorandom_no_repeats_strategy } else { $this->userid = $userid; } + + if ($extrarandomness) { + $this->extrarandomness = '|' . $extrarandomness; + } } public function choose_variant($maxvariants, $seed) { @@ -977,7 +984,7 @@ class question_variant_pseudorandom_no_repeats_strategy return 1; } - $hash = sha1($seed . '|user' . $this->userid); + $hash = sha1($seed . '|user' . $this->userid . $this->extrarandomness); $randint = hexdec(substr($hash, 17, 7)); return ($randint + $this->attemptno) % $maxvariants + 1;