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:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user