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-10-29 16:19:24 +00:00
parent 68291f2d57
commit d7db097db1
2 changed files with 11 additions and 3 deletions
+2 -1
View File
@@ -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(
+9 -2
View File
@@ -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;