Skip to content

Instantly share code, notes, and snippets.

@ChrisShank
Last active October 31, 2024 22:01
Show Gist options
  • Save ChrisShank/cc5eb9d96224b8710326cc391daf7098 to your computer and use it in GitHub Desktop.
Save ChrisShank/cc5eb9d96224b8710326cc391daf7098 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html>
<head>
<title>My experiment</title>
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://unpkg.com/@jspsych/[email protected]"></script>
<script src="https://unpkg.com/@jspsych/[email protected]"></script>
<script src="https://unpkg.com/@jspsych/[email protected]"></script>
<link
href="https://unpkg.com/[email protected]/css/jspsych.css"
rel="stylesheet"
type="text/css"
/>
</head>
<body></body>
<script>
const jsPsych = initJsPsych();
// Function that randomly shuffles an array.
const shuffle = jsPsych.randomization.shuffle;
// Update these values to change the delay for certain trials
const NAME_DELAY = 2000;
const IMAGE_DELAY = 3000;
const BIO_DELAY = 4000;
const MATH_DELAY = 4000;
function createRandomMathTrial() {
// TODO: generate different math expressions.
const expression = '3 + 12 = 15';
const answer = 't';
return [
{
type: jsPsychHtmlKeyboardResponse,
stimulus: `<p>${expression}</p><p>T/F?</p>`,
choices: ['t', 'f'],
trial_duration: MATH_DELAY,
data: {},
on_finish(data) {
// Score the keyboard response as correct or incorrect.
data.correct = jsPsych.pluginAPI.compareKeys(data.response, answer);
},
},
{
type: jsPsychHtmlKeyboardResponse,
stimulus() {
const lastTrial = jsPsych.data.get().last(1).values()[0];
return `<p>${expression}</p><p>${
lastTrial.correct ? 'Correct!' : 'Wrong.'
}</p>`;
},
choices: 'NO_KEYS',
trial_duration() {
const lastTrial = jsPsych.data.get().last(1).values()[0];
const BASE_FEEDBACK_TIME = 1000;
// Currently always shows feedback for 1 second + any extra time left over
if (lastTrial.rt === null) return 1000;
return MATH_DELAY - lastTrial.rt + BASE_FEEDBACK_TIME;
},
},
];
}
// Helper to general a biography-first trial.
function createBioFirstTrial(name, description) {
return [
{
type: jsPsychHtmlKeyboardResponse,
stimulus: `<h1>${name}</h1>`,
choices: 'NO_KEYS',
trial_duration: NAME_DELAY,
},
{
type: jsPsychHtmlKeyboardResponse,
stimulus: description,
choices: 'NO_KEYS',
trial_duration: BIO_DELAY,
},
{
type: jsPsychImageKeyboardResponse,
stimulus: `img/${name}.png`,
choices: 'NO_KEYS',
trial_duration: IMAGE_DELAY,
},
...createRandomMathTrial(),
];
}
// Helper to general a face-first trial.
function createFaceFirstTrial(name, description) {
return [
{
type: jsPsychHtmlKeyboardResponse,
stimulus: `<h1>${name}</h1>`,
choices: 'NO_KEYS',
trial_duration: NAME_DELAY,
},
{
type: jsPsychImageKeyboardResponse,
stimulus: `img/${name}.png`,
choices: 'NO_KEYS',
trial_duration: IMAGE_DELAY,
},
{
type: jsPsychHtmlKeyboardResponse,
stimulus: description,
choices: 'NO_KEYS',
trial_duration: BIO_DELAY,
},
...createRandomMathTrial(),
];
}
// Helper to general a control trial.
function createControlTrail(name) {
return [
{
type: jsPsychHtmlKeyboardResponse,
stimulus: `<h1>${name}</h1>`,
choices: 'NO_KEYS',
trial_duration: NAME_DELAY,
},
{
type: jsPsychImageKeyboardResponse,
stimulus: `img/${name}.png`,
choices: 'NO_KEYS',
trial_duration: IMAGE_DELAY,
},
{
type: jsPsychHtmlKeyboardResponse,
stimulus: `<h1>${name}</h1>`,
choices: 'NO_KEYS',
trial_duration: NAME_DELAY,
},
...createRandomMathTrial(),
];
}
function sequenceLearningPhase() {
// Lets assume the length of each pool is the same as this constant.
const length = 18;
// A list of randomized pools, one for each condition.
// You'll have to update this hardcoded list (or generate it) with the proper names and descriptions.
// Images are assumed to be in an `/img` folder in the same directory as this HTML file and labeled with the names of person display.
const pools = [
shuffle([
createControlTrail('control 1'),
createControlTrail('control 2'),
createControlTrail('control 3'),
createControlTrail('control 4'),
createControlTrail('control 5'),
createControlTrail('control 6'),
createControlTrail('control 7'),
createControlTrail('control 8'),
createControlTrail('control 9'),
createControlTrail('control 10'),
createControlTrail('control 11'),
createControlTrail('control 12'),
createControlTrail('control 13'),
createControlTrail('control 14'),
createControlTrail('control 15'),
createControlTrail('control 16'),
createControlTrail('control 17'),
createControlTrail('control 18'),
]),
shuffle([
createFaceFirstTrial('face-first 1', 'face-first 1 description'),
createFaceFirstTrial('face-first 2', 'face-first 2 description'),
createFaceFirstTrial('face-first 3', 'face-first 3 description'),
createFaceFirstTrial('face-first 4', 'face-first 4 description'),
createFaceFirstTrial('face-first 5', 'face-first 5 description'),
createFaceFirstTrial('face-first 6', 'face-first 6 description'),
createFaceFirstTrial('face-first 7', 'face-first 7 description'),
createFaceFirstTrial('face-first 8', 'face-first 8 description'),
createFaceFirstTrial('face-first 9', 'face-first 9 description'),
createFaceFirstTrial('face-first 10', 'face-first 10 description'),
createFaceFirstTrial('face-first 11', 'face-first 11 description'),
createFaceFirstTrial('face-first 12', 'face-first 12 description'),
createFaceFirstTrial('face-first 13', 'face-first 13 description'),
createFaceFirstTrial('face-first 14', 'face-first 14 description'),
createFaceFirstTrial('face-first 15', 'face-first 15 description'),
createFaceFirstTrial('face-first 16', 'face-first 16 description'),
createFaceFirstTrial('face-first 17', 'face-first 17 description'),
createFaceFirstTrial('face-first 18', 'face-first 18 description'),
]),
shuffle([
createBioFirstTrial('bio-first 1', 'bio-first 1 description'),
createBioFirstTrial('bio-first 2', 'bio-first 2 description'),
createBioFirstTrial('bio-first 3', 'bio-first 3 description'),
createBioFirstTrial('bio-first 4', 'bio-first 4 description'),
createBioFirstTrial('bio-first 5', 'bio-first 5 description'),
createBioFirstTrial('bio-first 6', 'bio-first 6 description'),
createBioFirstTrial('bio-first 7', 'bio-first 7 description'),
createBioFirstTrial('bio-first 8', 'bio-first 8 description'),
createBioFirstTrial('bio-first 9', 'bio-first 9 description'),
createBioFirstTrial('bio-first 10', 'bio-first 10 description'),
createBioFirstTrial('bio-first 11', 'bio-first 11 description'),
createBioFirstTrial('bio-first 12', 'bio-first 12 description'),
createBioFirstTrial('bio-first 13', 'bio-first 13 description'),
createBioFirstTrial('bio-first 14', 'bio-first 14 description'),
createBioFirstTrial('bio-first 15', 'bio-first 15 description'),
createBioFirstTrial('bio-first 16', 'bio-first 16 description'),
createBioFirstTrial('bio-first 17', 'bio-first 17 description'),
createBioFirstTrial('bio-first 18', 'bio-first 18 description'),
]),
];
const sequence = [];
// Interleave the pools together, but make sure there are at most 2 repeating conditions.
for (let i = 0; i < length; i++) {
sequence.push(...shuffle(pools.map((pool) => pool[i])));
}
// Flatten the sequence out into a single array for jspsych.
return sequence.flat();
}
const timeline = sequenceLearningPhase();
jsPsych.run([
{
type: jsPsychPreload,
// TODO: add paths of images to preload.
images: [],
},
{
type: jsPsychHtmlKeyboardResponse,
stimulus: 'Welcome to the experiment. Press any key to begin.',
},
...timeline,
]);
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment