Skip to main content

Randomization

Each trial should randomize what the word is, and what word's font color is. You might think the place to do that is in the last Action that executes when the presentation scene appears:

Action.custom( {callback: () => {
redButton.hidden = false;
greenButton.hidden = false;
blueButton.hidden = false;
wordLabel.text = CODE TO RANDOMLY CHOOSE A WORD HERE
wordLabel.fontColor = CODE TO RANDOMLY CHOOSE ITS COLOR HERE
redButton.isUserInteractionEnabled = true;
greenButton.isUserInteractionEnabled = true;
blueButton.isUserInteractionEnabled = true;
}}),

While this would work, it would be inadequate for most assessments. Although unlikely, it's possible that the same word could be chosen in all the assessment. Or, the same color could be chosen for all the words. It's impossible to specify exactly how many congruent and incongruent trials the user will see.

Determine the trial configurations in advance

In nearly all cases, you should randomize the trial configurations in advance. This ensures that you can achieve the desired variation for your assessments across the repeated trials.

note

This is probably the most complicated part of programming an assessment. It's a lot of data structures, arrays, indexes, and loops. But, it's worth it to get the randomization right.

Prepare the groundwork for randomization

We define a data structure, wordColors, that is an array of objects. Each object has two properties: text and color. We'll use this data structure to randomize the word and its color.

const wordColors = [
{text: "Red", color: WebColors.Red},
{text: "Green", color: WebColors.Green},
{text: "Blue", color: WebColors.Blue}
];

We define how many trials there will be, and how many will be congruent (later we will parameterize these). We also define an array, trialConfigurations, that will hold the unique combination of word and color for each trial.

const numberOfTrials = 3;
const numberOfCongruentTrials = 2;
const trialConfigurations = [];

The last preparation step is to randomly choose which trials will be congruent. congruentIndexes is an array that specifies which trials will be congruent.

const congruentIndexes = RandomDraws.FromRangeWithoutReplacement(numberOfCongruentTrials, 0, numberOfTrials - 1);

Because we have 3 trials total, and 2 will be congruent, congruentIndexes might be [0, 2]. This means that the first and third trials will be congruent.

Create each trial configuration

To set the properties of each trial, loop through each of the trials. We'll use the i variable to keep track of which trial we're on.

In each iteration through the loop, we put the word in the variable text. We test if the current trial is congruent with if (congruentIndexes.includes(i)). If it is, we set the textColor to be the same as the word. We also store the name of this color in the variable colorAsString. A variable isCongruent notes if this is a congruent trial or not. If the current trial is not congruent, we set the color to be a random color that's not the same as the word.

The properties of the trial are stored in an object, trial, which we push into the trialConfigurations array.

for (let i = 0; i < numberOfTrials; i++) {
const wordIndex = RandomDraws.SingleFromRange(0, wordColors.length - 1);
const text = wordColors[wordIndex].text;
let isCongruent;
let textColor;
let colorAsString;
if (congruentIndexes.includes(i)) {
textColor = wordColors[wordIndex].color;
colorAsString = wordColors[wordIndex].text;
isCongruent = true;
} else {
const colorOptions = wordColors.filter(wc => wc.text != text);
const colorIndex = RandomDraws.SingleFromRange(0, colorOptions.length - 1);
textColor = colorOptions[colorIndex].color;
colorAsString = colorOptions[colorIndex].text;
isCongruent = false;
}
const trial = { word: text, color: textColor, colorString: colorAsString, congruent: isCongruent};
trialConfigurations.push(trial);
}

Use the trial configuration to set the word and color

The code to set the word and color is similar to what we proposed at the top of this page. The important difference is that instead of randomizing within this Action, we draw upon the trial configuration we already created. We placed all our trials' configurations in the array trialConfigurations. We can use the variable game.trialIndex to access the configuration for our current trial.

Action.custom( {callback: () => {
redButton.hidden = false;
greenButton.hidden = false;
blueButton.hidden = false;
wordLabel.text = trialConfigurations[game.trialIndex].word;
wordLabel.fontColor = trialConfigurations[game.trialIndex].color;
redButton.isUserInteractionEnabled = true;
greenButton.isUserInteractionEnabled = true;
blueButton.isUserInteractionEnabled = true;
}}),

Determine if the user has finished all the trials

In the handleResponse function, we add code to mark the trial as complete. We also check if the user has completed all the trials. If they have, we present the end scene. Otherwise, we do another trial.

game.trialComplete();
if (game.trialIndex === numberOfTrials) {
game.presentScene(endScene, Transition.slide({
direction: TransitionDirection.Left,
duration: 500,
easing: Easings.quadraticInOut,
}));
} else {
game.presentScene(presentationScene);
}

Progress so far

The assessment now randomizes the word and its color, and it presents a set number of congruent and incongruent trials. The assessment also ends after a specified number of trials.

However, the assessment does not yet collect any user data (in the console, the data for each trial is undefined).

Loading...