From 2104481530c204cc2a8b2b58c566edab6314ce24 Mon Sep 17 00:00:00 2001 From: Ryan Cortez Date: Thu, 14 May 2020 13:33:28 -0400 Subject: [PATCH] _ --- N-back.psyexp | 27 ++- N-back.py | 2 +- N-backtest.psyexp | 144 +++++++++++ html/N-backtest-legacy-browsers.js | 370 ++++++++++++++++++++++++++++ html/N-backtest.js | 376 +++++++++++++++++++++++++++++ html/index.html | 6 +- 6 files changed, 914 insertions(+), 11 deletions(-) create mode 100644 N-backtest.psyexp create mode 100644 html/N-backtest-legacy-browsers.js create mode 100644 html/N-backtest.js diff --git a/N-back.psyexp b/N-back.psyexp index 18b0a53..bfdc756 100644 --- a/N-back.psyexp +++ b/N-back.psyexp @@ -140,7 +140,7 @@ - + @@ -149,7 +149,7 @@ - + @@ -162,10 +162,10 @@ - + - + @@ -175,7 +175,7 @@ - + @@ -190,12 +190,12 @@ - + - + @@ -364,6 +364,19 @@ + + + + + + + + + + + + + diff --git a/N-back.py b/N-back.py index b7ef03f..f890c86 100644 --- a/N-back.py +++ b/N-back.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- """ This experiment was created using PsychoPy3 Experiment Builder (v2020.1.3), - on May 13, 2020, at 14:12 + on May 13, 2020, at 14:27 If you publish work using this script the most relevant publication is: Peirce J, Gray JR, Simpson S, MacAskill M, Höchenberger R, Sogo H, Kastman E, Lindeløv JK. (2019) diff --git a/N-backtest.psyexp b/N-backtest.psyexp new file mode 100644 index 0000000..d6d9f9d --- /dev/null +++ b/N-backtest.psyexp @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/html/N-backtest-legacy-browsers.js b/html/N-backtest-legacy-browsers.js new file mode 100644 index 0000000..e3a2bc3 --- /dev/null +++ b/html/N-backtest-legacy-browsers.js @@ -0,0 +1,370 @@ +/******************* + * N-Backtest Test * + *******************/ + +// init psychoJS: +const psychoJS = new PsychoJS({ + debug: true +}); + +// open window: +psychoJS.openWindow({ + fullscr: true, + color: new util.Color([0, 0, 0]), + units: 'height', + waitBlanking: true +}); + +// store info about the experiment session: +let expName = 'N-backtest'; // from the Builder filename that created this script +let expInfo = {'participant': '', 'session': '001'}; + +// schedule the experiment: +psychoJS.schedule(psychoJS.gui.DlgFromDict({ + dictionary: expInfo, + title: expName +})); + +const flowScheduler = new Scheduler(psychoJS); +const dialogCancelScheduler = new Scheduler(psychoJS); +psychoJS.scheduleCondition(function() { return (psychoJS.gui.dialogComponent.button === 'OK'); }, flowScheduler, dialogCancelScheduler); + +// flowScheduler gets run if the participants presses OK +flowScheduler.add(updateInfo); // add timeStamp +flowScheduler.add(experimentInit); +const trialsLoopScheduler = new Scheduler(psychoJS); +flowScheduler.add(trialsLoopBegin, trialsLoopScheduler); +flowScheduler.add(trialsLoopScheduler); +flowScheduler.add(trialsLoopEnd); +flowScheduler.add(quitPsychoJS, '', true); + +// quit if user presses Cancel in dialog box: +dialogCancelScheduler.add(quitPsychoJS, '', false); + +psychoJS.start({ + expName: expName, + expInfo: expInfo, + }); + + +var frameDur; +function updateInfo() { + expInfo['date'] = util.MonotonicClock.getDateStr(); // add a simple timestamp + expInfo['expName'] = expName; + expInfo['psychopyVersion'] = '2020.1.3'; + expInfo['OS'] = window.navigator.platform; + + // store frame rate of monitor if we can measure it successfully + expInfo['frameRate'] = psychoJS.window.getActualFrameRate(); + if (typeof expInfo['frameRate'] !== 'undefined') + frameDur = 1.0 / Math.round(expInfo['frameRate']); + else + frameDur = 1.0 / 60.0; // couldn't get a reliable measure so guess + + // add info from the URL: + util.addInfoFromUrl(expInfo); + + return Scheduler.Event.NEXT; +} + + +var trialClock; +var grid_lines; +var target_square; +var fixation_2; +var response; +var globalClock; +var routineTimer; +function experimentInit() { + // Initialize components for Routine "trial" + trialClock = new util.Clock(); + grid_lines = new visual.ImageStim({ + win : psychoJS.window, + name : 'grid_lines', units : undefined, + image : 'grid.png', mask : undefined, + ori : 0, pos : [0, 0], size : [0.5, 0.5], + color : new util.Color([1, 1, 1]), opacity : 1, + flipHoriz : false, flipVert : false, + texRes : 128, interpolate : true, depth : 0.0 + }); + target_square = new visual.Rect ({ + win: psychoJS.window, name: 'target_square', + width: [0.15, 0.15][0], height: [0.15, 0.15][1], + ori: 0, pos: [0, 0], + lineWidth: 1, lineColor: new util.Color([1, 1, 1]), + fillColor: new util.Color([1, 1, 1]), + opacity: 1, depth: -1, interpolate: true, + }); + + fixation_2 = new visual.TextStim({ + win: psychoJS.window, + name: 'fixation_2', + text: '+', + font: 'Arial', + units: undefined, + pos: [0, 0], height: 0.05, wrapWidth: undefined, ori: 0, + color: new util.Color('white'), opacity: 1, + depth: -2.0 + }); + + response = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true}); + + // Create some handy timers + globalClock = new util.Clock(); // to track the time since experiment started + routineTimer = new util.CountdownTimer(); // to track time remaining of each (non-slip) routine + + return Scheduler.Event.NEXT; +} + + +var trials; +var currentLoop; +function trialsLoopBegin(thisScheduler) { + // set up handler to look after randomisation of conditions etc + trials = new TrialHandler({ + psychoJS: psychoJS, + nReps: 5, method: TrialHandler.Method.RANDOM, + extraInfo: expInfo, originPath: undefined, + trialList: '../../Users/Ryan/Downloads/PavloviaNback/N-back-1.xlsx', + seed: undefined, name: 'trials' + }); + psychoJS.experiment.addLoop(trials); // add the loop to the experiment + currentLoop = trials; // we're now the current loop + + // Schedule all the trials in the trialList: + trials.forEach(function() { + const snapshot = trials.getSnapshot(); + + thisScheduler.add(importConditions(snapshot)); + thisScheduler.add(trialRoutineBegin(snapshot)); + thisScheduler.add(trialRoutineEachFrame(snapshot)); + thisScheduler.add(trialRoutineEnd(snapshot)); + thisScheduler.add(endLoopIteration(thisScheduler, snapshot)); + }); + + return Scheduler.Event.NEXT; +} + + +function trialsLoopEnd() { + psychoJS.experiment.removeLoop(trials); + + return Scheduler.Event.NEXT; +} + + +var t; +var frameN; +var _response_allKeys; +var trialComponents; +function trialRoutineBegin(trials) { + return function () { + //------Prepare to start Routine 'trial'------- + t = 0; + trialClock.reset(); // clock + frameN = -1; + routineTimer.add(2.000000); + // update component parameters for each repeat + target_square.setPos(location); + response.keys = undefined; + response.rt = undefined; + _response_allKeys = []; + // keep track of which components have finished + trialComponents = []; + trialComponents.push(grid_lines); + trialComponents.push(target_square); + trialComponents.push(fixation_2); + trialComponents.push(response); + + trialComponents.forEach( function(thisComponent) { + if ('status' in thisComponent) + thisComponent.status = PsychoJS.Status.NOT_STARTED; + }); + + return Scheduler.Event.NEXT; + }; +} + + +var frameRemains; +var continueRoutine; +function trialRoutineEachFrame(trials) { + return function () { + //------Loop for each frame of Routine 'trial'------- + let continueRoutine = true; // until we're told otherwise + // get current time + t = trialClock.getTime(); + frameN = frameN + 1;// number of completed frames (so 0 is the first frame) + // update/draw components on each frame + + // *grid_lines* updates + if (t >= 0.0 && grid_lines.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + grid_lines.tStart = t; // (not accounting for frame time here) + grid_lines.frameNStart = frameN; // exact frame index + + grid_lines.setAutoDraw(true); + } + + frameRemains = 0.0 + 2.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (grid_lines.status === PsychoJS.Status.STARTED && t >= frameRemains) { + grid_lines.setAutoDraw(false); + } + + // *target_square* updates + if (t >= 0.0 && target_square.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + target_square.tStart = t; // (not accounting for frame time here) + target_square.frameNStart = frameN; // exact frame index + + target_square.setAutoDraw(true); + } + + frameRemains = 0.0 + 1.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (target_square.status === PsychoJS.Status.STARTED && t >= frameRemains) { + target_square.setAutoDraw(false); + } + + // *fixation_2* updates + if (t >= 1.0 && fixation_2.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + fixation_2.tStart = t; // (not accounting for frame time here) + fixation_2.frameNStart = frameN; // exact frame index + + fixation_2.setAutoDraw(true); + } + + frameRemains = 1.0 + 1.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (fixation_2.status === PsychoJS.Status.STARTED && t >= frameRemains) { + fixation_2.setAutoDraw(false); + } + + // *response* updates + if (t >= 0.0 && response.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + response.tStart = t; // (not accounting for frame time here) + response.frameNStart = frameN; // exact frame index + + // keyboard checking is just starting + psychoJS.window.callOnFlip(function() { response.clock.reset(); }); // t=0 on next screen flip + psychoJS.window.callOnFlip(function() { response.start(); }); // start on screen flip + psychoJS.window.callOnFlip(function() { response.clearEvents(); }); + } + + frameRemains = 0.0 + 2.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (response.status === PsychoJS.Status.STARTED && t >= frameRemains) { + response.status = PsychoJS.Status.FINISHED; + } + + if (response.status === PsychoJS.Status.STARTED) { + let theseKeys = response.getKeys({keyList: ['space'], waitRelease: false}); + _response_allKeys = _response_allKeys.concat(theseKeys); + if (_response_allKeys.length > 0) { + response.keys = _response_allKeys[_response_allKeys.length - 1].name; // just the last key pressed + response.rt = _response_allKeys[_response_allKeys.length - 1].rt; + // was this correct? + if (response.keys == corrAns) { + response.corr = 1; + } else { + response.corr = 0; + } + } + } + + // check for quit (typically the Esc key) + if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) { + return quitPsychoJS('The [Escape] key was pressed. Goodbye!', false); + } + + // check if the Routine should terminate + if (!continueRoutine) { // a component has requested a forced-end of Routine + return Scheduler.Event.NEXT; + } + + continueRoutine = false; // reverts to True if at least one component still running + trialComponents.forEach( function(thisComponent) { + if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) { + continueRoutine = true; + } + }); + + // refresh the screen if continuing + if (continueRoutine && routineTimer.getTime() > 0) { + return Scheduler.Event.FLIP_REPEAT; + } else { + return Scheduler.Event.NEXT; + } + }; +} + + +function trialRoutineEnd(trials) { + return function () { + //------Ending Routine 'trial'------- + trialComponents.forEach( function(thisComponent) { + if (typeof thisComponent.setAutoDraw === 'function') { + thisComponent.setAutoDraw(false); + } + }); + // was no response the correct answer?! + if (response.keys === undefined) { + if (['None','none',undefined].includes(corrAns)) { + response.corr = 1; // correct non-response + } else { + response.corr = 0; // failed to respond (incorrectly) + } + } + // store data for thisExp (ExperimentHandler) + psychoJS.experiment.addData('response.keys', response.keys); + psychoJS.experiment.addData('response.corr', response.corr); + if (typeof response.keys !== 'undefined') { // we had a response + psychoJS.experiment.addData('response.rt', response.rt); + } + + response.stop(); + return Scheduler.Event.NEXT; + }; +} + + +function endLoopIteration(thisScheduler, loop) { + // ------Prepare for next entry------ + return function () { + if (typeof loop !== 'undefined') { + // ------Check if user ended loop early------ + if (loop.finished) { + // Check for and save orphaned data + if (psychoJS.experiment.isEntryEmpty()) { + psychoJS.experiment.nextEntry(loop); + } + thisScheduler.stop(); + } else { + const thisTrial = loop.getCurrentTrial(); + if (typeof thisTrial === 'undefined' || !('isTrials' in thisTrial) || thisTrial.isTrials) { + psychoJS.experiment.nextEntry(loop); + } + } + return Scheduler.Event.NEXT; + } + }; +} + + +function importConditions(trials) { + return function () { + psychoJS.importAttributes(trials.getCurrentTrial()); + return Scheduler.Event.NEXT; + }; +} + + +function quitPsychoJS(message, isCompleted) { + // Check for and save orphaned data + if (psychoJS.experiment.isEntryEmpty()) { + psychoJS.experiment.nextEntry(); + } + psychoJS.window.close(); + psychoJS.quit({message: message, isCompleted: isCompleted}); + + return Scheduler.Event.QUIT; +} diff --git a/html/N-backtest.js b/html/N-backtest.js new file mode 100644 index 0000000..b8abcf1 --- /dev/null +++ b/html/N-backtest.js @@ -0,0 +1,376 @@ +/******************* + * N-Backtest Test * + *******************/ + +import { PsychoJS } from './lib/core-2020.1.js'; +import * as core from './lib/core-2020.1.js'; +import { TrialHandler } from './lib/data-2020.1.js'; +import { Scheduler } from './lib/util-2020.1.js'; +import * as util from './lib/util-2020.1.js'; +import * as visual from './lib/visual-2020.1.js'; +import * as sound from './lib/sound-2020.1.js'; + +// init psychoJS: +const psychoJS = new PsychoJS({ + debug: true +}); + +// open window: +psychoJS.openWindow({ + fullscr: true, + color: new util.Color([0, 0, 0]), + units: 'height', + waitBlanking: true +}); + +// store info about the experiment session: +let expName = 'N-backtest'; // from the Builder filename that created this script +let expInfo = {'participant': '', 'session': '001'}; + +// schedule the experiment: +psychoJS.schedule(psychoJS.gui.DlgFromDict({ + dictionary: expInfo, + title: expName +})); + +const flowScheduler = new Scheduler(psychoJS); +const dialogCancelScheduler = new Scheduler(psychoJS); +psychoJS.scheduleCondition(function() { return (psychoJS.gui.dialogComponent.button === 'OK'); }, flowScheduler, dialogCancelScheduler); + +// flowScheduler gets run if the participants presses OK +flowScheduler.add(updateInfo); // add timeStamp +flowScheduler.add(experimentInit); +const trialsLoopScheduler = new Scheduler(psychoJS); +flowScheduler.add(trialsLoopBegin, trialsLoopScheduler); +flowScheduler.add(trialsLoopScheduler); +flowScheduler.add(trialsLoopEnd); +flowScheduler.add(quitPsychoJS, '', true); + +// quit if user presses Cancel in dialog box: +dialogCancelScheduler.add(quitPsychoJS, '', false); + +psychoJS.start({ + expName: expName, + expInfo: expInfo, + }); + + +var frameDur; +function updateInfo() { + expInfo['date'] = util.MonotonicClock.getDateStr(); // add a simple timestamp + expInfo['expName'] = expName; + expInfo['psychopyVersion'] = '2020.1.3'; + expInfo['OS'] = window.navigator.platform; + + // store frame rate of monitor if we can measure it successfully + expInfo['frameRate'] = psychoJS.window.getActualFrameRate(); + if (typeof expInfo['frameRate'] !== 'undefined') + frameDur = 1.0 / Math.round(expInfo['frameRate']); + else + frameDur = 1.0 / 60.0; // couldn't get a reliable measure so guess + + // add info from the URL: + util.addInfoFromUrl(expInfo); + + return Scheduler.Event.NEXT; +} + + +var trialClock; +var grid_lines; +var target_square; +var fixation_2; +var response; +var globalClock; +var routineTimer; +function experimentInit() { + // Initialize components for Routine "trial" + trialClock = new util.Clock(); + grid_lines = new visual.ImageStim({ + win : psychoJS.window, + name : 'grid_lines', units : undefined, + image : 'grid.png', mask : undefined, + ori : 0, pos : [0, 0], size : [0.5, 0.5], + color : new util.Color([1, 1, 1]), opacity : 1, + flipHoriz : false, flipVert : false, + texRes : 128, interpolate : true, depth : 0.0 + }); + target_square = new visual.Rect ({ + win: psychoJS.window, name: 'target_square', + width: [0.15, 0.15][0], height: [0.15, 0.15][1], + ori: 0, pos: [0, 0], + lineWidth: 1, lineColor: new util.Color([1, 1, 1]), + fillColor: new util.Color([1, 1, 1]), + opacity: 1, depth: -1, interpolate: true, + }); + + fixation_2 = new visual.TextStim({ + win: psychoJS.window, + name: 'fixation_2', + text: '+', + font: 'Arial', + units: undefined, + pos: [0, 0], height: 0.05, wrapWidth: undefined, ori: 0, + color: new util.Color('white'), opacity: 1, + depth: -2.0 + }); + + response = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true}); + + // Create some handy timers + globalClock = new util.Clock(); // to track the time since experiment started + routineTimer = new util.CountdownTimer(); // to track time remaining of each (non-slip) routine + + return Scheduler.Event.NEXT; +} + + +var trials; +var currentLoop; +function trialsLoopBegin(thisScheduler) { + // set up handler to look after randomisation of conditions etc + trials = new TrialHandler({ + psychoJS: psychoJS, + nReps: 5, method: TrialHandler.Method.RANDOM, + extraInfo: expInfo, originPath: undefined, + trialList: '../../Users/Ryan/Downloads/PavloviaNback/N-back-1.xlsx', + seed: undefined, name: 'trials' + }); + psychoJS.experiment.addLoop(trials); // add the loop to the experiment + currentLoop = trials; // we're now the current loop + + // Schedule all the trials in the trialList: + for (const thisTrial of trials) { + const snapshot = trials.getSnapshot(); + thisScheduler.add(importConditions(snapshot)); + thisScheduler.add(trialRoutineBegin(snapshot)); + thisScheduler.add(trialRoutineEachFrame(snapshot)); + thisScheduler.add(trialRoutineEnd(snapshot)); + thisScheduler.add(endLoopIteration(thisScheduler, snapshot)); + } + + return Scheduler.Event.NEXT; +} + + +function trialsLoopEnd() { + psychoJS.experiment.removeLoop(trials); + + return Scheduler.Event.NEXT; +} + + +var t; +var frameN; +var _response_allKeys; +var trialComponents; +function trialRoutineBegin(trials) { + return function () { + //------Prepare to start Routine 'trial'------- + t = 0; + trialClock.reset(); // clock + frameN = -1; + routineTimer.add(2.000000); + // update component parameters for each repeat + target_square.setPos(location); + response.keys = undefined; + response.rt = undefined; + _response_allKeys = []; + // keep track of which components have finished + trialComponents = []; + trialComponents.push(grid_lines); + trialComponents.push(target_square); + trialComponents.push(fixation_2); + trialComponents.push(response); + + for (const thisComponent of trialComponents) + if ('status' in thisComponent) + thisComponent.status = PsychoJS.Status.NOT_STARTED; + + return Scheduler.Event.NEXT; + }; +} + + +var frameRemains; +var continueRoutine; +function trialRoutineEachFrame(trials) { + return function () { + //------Loop for each frame of Routine 'trial'------- + let continueRoutine = true; // until we're told otherwise + // get current time + t = trialClock.getTime(); + frameN = frameN + 1;// number of completed frames (so 0 is the first frame) + // update/draw components on each frame + + // *grid_lines* updates + if (t >= 0.0 && grid_lines.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + grid_lines.tStart = t; // (not accounting for frame time here) + grid_lines.frameNStart = frameN; // exact frame index + + grid_lines.setAutoDraw(true); + } + + frameRemains = 0.0 + 2.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (grid_lines.status === PsychoJS.Status.STARTED && t >= frameRemains) { + grid_lines.setAutoDraw(false); + } + + // *target_square* updates + if (t >= 0.0 && target_square.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + target_square.tStart = t; // (not accounting for frame time here) + target_square.frameNStart = frameN; // exact frame index + + target_square.setAutoDraw(true); + } + + frameRemains = 0.0 + 1.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (target_square.status === PsychoJS.Status.STARTED && t >= frameRemains) { + target_square.setAutoDraw(false); + } + + // *fixation_2* updates + if (t >= 1.0 && fixation_2.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + fixation_2.tStart = t; // (not accounting for frame time here) + fixation_2.frameNStart = frameN; // exact frame index + + fixation_2.setAutoDraw(true); + } + + frameRemains = 1.0 + 1.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (fixation_2.status === PsychoJS.Status.STARTED && t >= frameRemains) { + fixation_2.setAutoDraw(false); + } + + // *response* updates + if (t >= 0.0 && response.status === PsychoJS.Status.NOT_STARTED) { + // keep track of start time/frame for later + response.tStart = t; // (not accounting for frame time here) + response.frameNStart = frameN; // exact frame index + + // keyboard checking is just starting + psychoJS.window.callOnFlip(function() { response.clock.reset(); }); // t=0 on next screen flip + psychoJS.window.callOnFlip(function() { response.start(); }); // start on screen flip + psychoJS.window.callOnFlip(function() { response.clearEvents(); }); + } + + frameRemains = 0.0 + 2.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left + if (response.status === PsychoJS.Status.STARTED && t >= frameRemains) { + response.status = PsychoJS.Status.FINISHED; + } + + if (response.status === PsychoJS.Status.STARTED) { + let theseKeys = response.getKeys({keyList: ['space'], waitRelease: false}); + _response_allKeys = _response_allKeys.concat(theseKeys); + if (_response_allKeys.length > 0) { + response.keys = _response_allKeys[_response_allKeys.length - 1].name; // just the last key pressed + response.rt = _response_allKeys[_response_allKeys.length - 1].rt; + // was this correct? + if (response.keys == corrAns) { + response.corr = 1; + } else { + response.corr = 0; + } + } + } + + // check for quit (typically the Esc key) + if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) { + return quitPsychoJS('The [Escape] key was pressed. Goodbye!', false); + } + + // check if the Routine should terminate + if (!continueRoutine) { // a component has requested a forced-end of Routine + return Scheduler.Event.NEXT; + } + + continueRoutine = false; // reverts to True if at least one component still running + for (const thisComponent of trialComponents) + if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) { + continueRoutine = true; + break; + } + + // refresh the screen if continuing + if (continueRoutine && routineTimer.getTime() > 0) { + return Scheduler.Event.FLIP_REPEAT; + } else { + return Scheduler.Event.NEXT; + } + }; +} + + +function trialRoutineEnd(trials) { + return function () { + //------Ending Routine 'trial'------- + for (const thisComponent of trialComponents) { + if (typeof thisComponent.setAutoDraw === 'function') { + thisComponent.setAutoDraw(false); + } + } + // was no response the correct answer?! + if (response.keys === undefined) { + if (['None','none',undefined].includes(corrAns)) { + response.corr = 1; // correct non-response + } else { + response.corr = 0; // failed to respond (incorrectly) + } + } + // store data for thisExp (ExperimentHandler) + psychoJS.experiment.addData('response.keys', response.keys); + psychoJS.experiment.addData('response.corr', response.corr); + if (typeof response.keys !== 'undefined') { // we had a response + psychoJS.experiment.addData('response.rt', response.rt); + } + + response.stop(); + return Scheduler.Event.NEXT; + }; +} + + +function endLoopIteration(thisScheduler, loop) { + // ------Prepare for next entry------ + return function () { + if (typeof loop !== 'undefined') { + // ------Check if user ended loop early------ + if (loop.finished) { + // Check for and save orphaned data + if (psychoJS.experiment.isEntryEmpty()) { + psychoJS.experiment.nextEntry(loop); + } + thisScheduler.stop(); + } else { + const thisTrial = loop.getCurrentTrial(); + if (typeof thisTrial === 'undefined' || !('isTrials' in thisTrial) || thisTrial.isTrials) { + psychoJS.experiment.nextEntry(loop); + } + } + return Scheduler.Event.NEXT; + } + }; +} + + +function importConditions(trials) { + return function () { + psychoJS.importAttributes(trials.getCurrentTrial()); + return Scheduler.Event.NEXT; + }; +} + + +function quitPsychoJS(message, isCompleted) { + // Check for and save orphaned data + if (psychoJS.experiment.isEntryEmpty()) { + psychoJS.experiment.nextEntry(); + } + psychoJS.window.close(); + psychoJS.quit({message: message, isCompleted: isCompleted}); + + return Scheduler.Event.QUIT; +} diff --git a/html/index.html b/html/index.html index 53d2f8b..0b3eef8 100644 --- a/html/index.html +++ b/html/index.html @@ -2,7 +2,7 @@ - N-back [PsychoPy] + N-backtest [PsychoPy] @@ -28,13 +28,13 @@ - + - + -- 2.18.1