add setSeed to randomization

This commit is contained in:
Josh de Leeuw 2021-12-07 11:03:48 -05:00
parent 512ea0115e
commit 83b1ba291f
3 changed files with 127 additions and 0 deletions

View File

@ -1,4 +1,20 @@
import rw from "random-words";
import seedrandom from "seedrandom";
/**
* Uses the `seedrandom` package to replace Math.random() with a seedable PRNG.
*
* @param seed An optional seed. If none is given, a random seed will be generated.
* @returns The seed value.
*/
export function setSeed(seed?) {
if (!seed) {
const prng = seedrandom();
seed = prng.int32();
}
seedrandom(seed, { global: true });
return seed;
}
export function repeat(array, repetitions, unpack = false) {
const arr_isArray = Array.isArray(array);

View File

@ -3,6 +3,7 @@ import {
randomID,
randomInt,
repeat,
setSeed,
shuffle,
shuffleAlternateGroups,
shuffleNoRepeats,
@ -165,3 +166,20 @@ describe("randomInt", () => {
}).toThrowError();
});
});
describe("setSeed", () => {
test("Replaces Math.random() with seedable RNG", () => {
setSeed(12603);
const r1_1 = Math.random();
const r1_2 = Math.random();
setSeed(12603);
const r2_1 = Math.random();
const r2_2 = Math.random();
expect(r1_1).toEqual(r2_1);
expect(r1_2).toEqual(r2_2);
});
});

View File

@ -0,0 +1,93 @@
// this file is to test that jsPsych.randomization.setSeed works in context
import htmlKeyboardResponse from "@jspsych/plugin-html-keyboard-response";
import { pressKey, startTimeline } from "@jspsych/test-utils";
import { initJsPsych } from "../../src";
describe("setSeed generates predictable randomization", () => {
test("timeline variable randomization is preserved", async () => {
const jsPsych = initJsPsych();
const seed = jsPsych.randomization.setSeed();
const { getData } = await startTimeline(
[
{
timeline: [
{
type: htmlKeyboardResponse,
stimulus: "this is html",
data: {
i: jsPsych.timelineVariable("i"),
},
},
],
timeline_variables: [
{ i: 0 },
{ i: 1 },
{ i: 2 },
{ i: 3 },
{ i: 4 },
{ i: 5 },
{ i: 6 },
{ i: 7 },
{ i: 8 },
],
randomize_order: true,
},
],
jsPsych
);
for (let i = 0; i < 9; i++) {
pressKey(" ");
}
const data_run_1 = getData().readOnly();
const jsPsych_run2 = initJsPsych();
jsPsych_run2.randomization.setSeed(seed);
const { getData: getData2 } = await startTimeline(
[
{
timeline: [
{
type: htmlKeyboardResponse,
stimulus: "this is html",
data: {
i: jsPsych_run2.timelineVariable("i"),
},
},
],
timeline_variables: [
{ i: 0 },
{ i: 1 },
{ i: 2 },
{ i: 3 },
{ i: 4 },
{ i: 5 },
{ i: 6 },
{ i: 7 },
{ i: 8 },
],
randomize_order: true,
},
],
jsPsych_run2
);
for (let i = 0; i < 9; i++) {
pressKey(" ");
}
const data_run_2 = getData2().readOnly();
console.log(data_run_1.values());
console.log(data_run_2.values());
expect(data_run_1.select("i").values).toEqual(data_run_2.select("i").values);
});
});