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.
This commit is contained in:
Tim Hunt
2013-11-11 14:15:36 +00:00
parent 560c1c8ea3
commit 50a946f5bb
2 changed files with 12 additions and 3 deletions
+3 -1
View File
@@ -209,7 +209,9 @@ if (!($quizobj->get_quiz()->attemptonlast && $lastattempt)) {
$variantoffset = $attemptnumber;
}
$quba->start_all_questions(
new question_variant_pseudorandom_no_repeats_strategy($variantoffset), $timenow);
new question_variant_pseudorandom_no_repeats_strategy(
$variantoffset, $attempt->userid, $quizobj->get_quizid()),
$timenow);
// Update attempt layout.
$newlayout = array();
+9 -2
View File
@@ -884,12 +884,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;
@@ -897,6 +900,10 @@ class question_variant_pseudorandom_no_repeats_strategy
} else {
$this->userid = $userid;
}
if ($extrarandomness) {
$this->extrarandomness = '|' . $extrarandomness;
}
}
public function choose_variant($maxvariants, $seed) {
@@ -904,7 +911,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;