import { Cat, Clowder, StopAfterNItems, prepareClowderCorpus } from '@bdelab/jscat';
import enLetterCatCorpus from '../stimuli/en/letterCatCorpus.csv';
const catOrderMap = {
0: 'letterNamePractice',
1: 'letterNameLower',
2: 'letterNameUpper',
3: 'letterPhonemePractice',
4: 'letterPhoneme',
};
const catToSubTaskMap = {
letterNamePractice: 'LetterPractice',
letterNameLower: 'LowercaseNames',
letterNameUpper: 'UppercaseNames',
letterPhonemePractice: 'PhonemePractice',
letterPhoneme: 'Phonemes',
};
export let clowder;
export const initializeClowder = () => {
const catsConfig = {
letterNamePractice: {
method: 'EAP',
itemSelect: store.session('itemSelect'),
minTheta: -8,
maxTheta: 8,
randomSeed: 'seed-lower-practice',
},
letterNameLower: {
method: 'EAP',
itemSelect: store.session('itemSelect'),
minTheta: -8,
maxTheta: 8,
randomSeed: 'seed-lower',
},
letterNameUpper: {
method: 'EAP',
itemSelect: store.session('itemSelect'),
minTheta: -8,
maxTheta: 8,
randomSeed: 'seed-upper',
},
letterPhonemePractice: {
method: 'EAP',
itemSelect: store.session('itemSelect'),
minTheta: -8,
maxTheta: 8,
randomSeed: 'seed-phoneme-practice',
},
letterPhoneme: {
method: 'EAP',
itemSelect: store.session('itemSelect'),
minTheta: -8,
maxTheta: 8,
randomSeed: 'seed-phoneme',
},
total: {
method: 'EAP',
itemSelect: store.session('itemSelect'),
minTheta: -8,
maxTheta: 8,
randomSeed: 'seed-lower-practice',
},
};
let earlyStoppingCats = null;
earlyStoppingCats = new StopAfterNItems({
requiredItems: {
letterNameLower: store.session.get('config').nItems ?? 5,
letterNameUpper: store.session.get('config').nItems ?? 5,
letterPhoneme: store.session.get('config').nItems ?? 15,
},
logicalOperation: store.session.get('config').logicalOperation ?? 'only',
});
const clowderCorpus = prepareClowderCorpus(
enLetterCatCorpus,
['letterNamePractice', 'letterNameLower', 'letterNameUpper', 'letterPhonemePractice', 'letterPhoneme', 'total'],
'.',
);
clowder = new Clowder({
cats: catsConfig,
corpus: clowderCorpus,
randomSeed: store.session.get('config').randomSeed ?? 'random-seed',
earlyStopping: earlyStoppingCats,
});
};
export const setNextStimulus = () => {
let catIndex = store.session.get('currentCatIndex');
if (catIndex == undefined) {
store.session.set('currentCatIndex', 0);
catIndex = 0;
}
const catName = catOrderMap[catIndex];
const previousItem = store.session.get('previousItem');
const previousAnswer = store.session.get('previousAnswer');
const nextStimulus = clowder.updateCatAndGetNextItem({
catToSelect: catName,
catsToUpdate: ['total', 'letterNameLower', 'letterNameUpper', 'letterPhoneme'],
items: previousItem ?? undefined,
answers: previousAnswer ?? undefined,
randomlySelectUnvalidated: false,
});
if (nextStimulus === undefined) {
store.session.remove('nextStimulus');
} else {
store.session.set('nextStimulus', nextStimulus);
}
};
export const moveToNextBlock = () => {
const catIndex = (store.session.get('currentCatIndex') ?? -1) + 1;
store.session.set('subTaskName', catToSubTaskMap[catOrderMap[catIndex]]);
store.session.set('currentCatIndex', catIndex);
store.session.set('correctItems', []);
store.session.set('incorrectItems', []);
store.session.set('trialNumSubtask', 0);
};
import store from 'store2';
import { ifLetterNameTest, ifRealTrialResponse } from './stimulusLetterName';
import { ifPracticeCorrect, ifPracticeIncorrect } from './practice';
import { setNextStimulus, moveToNextBlock } from '../experimentSetup';
export const buildBlock = (preInstructions) => {
const stimulusLoop = {
timeline: [ifLetterNameTest, ifPracticeCorrect, ifPracticeIncorrect, ifRealTrialResponse],
loop_function: () => {
setNextStimulus();
return store.session.get('nextStimulus') !== undefined;
},
};
return {
timeline: [preInstructions, stimulusLoop],
on_timeline_start: () => {
moveToNextBlock();
setNextStimulus();
},
};
};
import { clowder } from './experimentSetup';
const subTaskToCatMap = {
LetterPractice: 'letterNamePractice',
LowercaseNames: 'letterNameLower',
UppercaseNames: 'letterNameUpper',
PhonemePractice: 'letterPhonemePractice',
Phonemes: 'letterPhoneme',
};
export const computedScoreCallback = (rawScores) => {
return {
thetaEstimate: clowder.theta[subTaskToCatMap[store.session.get('subTaskName')]],
thetaSE: clowder.seMeasurement[subTaskToCatMap[store.session.get('subTaskName')]],
thetaEstimateTotal: clowder.theta.total,
thetaSETotal: clowder.seMeasurement.total,
};
};