We are trying with self hosting an experiment the data handling part is handled by firestore.
Our only issue is that a save as dialog appears after the completion of the experiment. How can we turn that off?
import {
core,
data,
sound,
util,
visual,
hardware,
} from "./lib/psychojs-2024.2.4.js";
const { PsychoJS } = core;
const { TrialHandler, MultiStairHandler } = data;
const { Scheduler } = util;
//some handy aliases as in the psychopy scripts;
const { abs, sin, cos, PI: pi, sqrt } = Math;
const { round } = util;
// store info about the experiment session:
let expName = "bart"; // from the Builder filename that created this script
let expInfo = {
participant: "",
age: "",
};
// Start code blocks for 'Before Experiment'
// init psychoJS:
const psychoJS = new PsychoJS({
debug: true,
});
// open window:
psychoJS.openWindow({
fullscr: true,
color: new util.Color([-1.0, 0.6157, 0.6392]),
units: "height",
waitBlanking: true,
backgroundImage: "",
backgroundFit: "none",
});
// 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);
flowScheduler.add(instructionsRoutineBegin());
flowScheduler.add(instructionsRoutineEachFrame());
flowScheduler.add(instructionsRoutineEnd());
const trialsLoopScheduler = new Scheduler(psychoJS);
flowScheduler.add(trialsLoopBegin(trialsLoopScheduler));
flowScheduler.add(trialsLoopScheduler);
flowScheduler.add(trialsLoopEnd);
flowScheduler.add(finalScoreRoutineBegin());
flowScheduler.add(finalScoreRoutineEachFrame());
flowScheduler.add(finalScoreRoutineEnd());
flowScheduler.add(quitPsychoJS, "", true);
// quit if user presses Cancel in dialog box:
dialogCancelScheduler.add(quitPsychoJS, "", false);
psychoJS.start({
expName: expName,
expInfo: expInfo,
resources: [
// resources:
{
name: "spreadsheets/conditions.xlsx",
path: "spreadsheets/conditions.xlsx",
},
{ name: "assets/background.png", path: "assets/background.png" },
{ name: "assets/bang.wav", path: "assets/bang.wav" },
{ name: "assets/redBalloon.png", path: "assets/redBalloon.png" },
{ name: "assets/bang.wav", path: "assets/bang.wav" },
{ name: "assets/blueBalloon.png", path: "assets/blueBalloon.png" },
{ name: "assets/greenBalloon.png", path: "assets/greenBalloon.png" },
{ name: "assets/redBalloon.png", path: "assets/redBalloon.png" },
{ name: "assets/bang.mp3", path: "assets/bang.mp3" },
],
});
psychoJS.experimentLogger.setLevel(core.Logger.ServerLevel.WARNING);
var currentLoop;
var frameDur;
async function updateInfo() {
currentLoop = psychoJS.experiment; // right now there are no loops
expInfo["date"] = util.MonotonicClock.getDateStr(); // add a simple timestamp
expInfo["expName"] = expName;
expInfo["psychopyVersion"] = "2024.2.4";
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);
psychoJS.experiment.dataFileName =
"." + "/" + ("data" + "/" + `${expInfo["participant"]}_${expInfo["date"]}`);
psychoJS.experiment.field_separator = "\t";
return Scheduler.Event.NEXT;
}
.....some of the code were removed..............
placeholder: "Type here...",
font: "Arial",
pos: [0, 0],
draggable: false,
letterHeight: 0.04,
lineSpacing: 1.0,
size: [1, 0.7],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -2.0,
});
pop_sound = new sound.Sound({
win: psychoJS.window,
value: "assets/bang.wav",
secs: 1.0,
});
pop_sound.setVolume(0.0);
// Initialize components for Routine "reset_balloon"
reset_balloonClock = new util.Clock();
// Initialize components for Routine "trial"
trialClock = new util.Clock();
background_2 = new visual.ImageStim({
win: psychoJS.window,
name: "background_2",
units: undefined,
image: "assets/background.png",
mask: undefined,
anchor: "center",
ori: 0.0,
pos: [0, 0],
draggable: false,
size: [2.2, 1],
color: new util.Color([1, 1, 1]),
opacity: undefined,
flipHoriz: false,
flipVert: false,
texRes: 128.0,
interpolate: true,
depth: 0.0,
});
bankButton = new core.Keyboard({
psychoJS: psychoJS,
clock: new util.Clock(),
waitForStart: true,
});
// Run 'Begin Experiment' code from updateEarnings
bankedEarnings = 0.0;
balloonEarnings = "";
bankedText = "";
lastBalloonEarnings = 0.0;
thisBalloonEarnings = 0.0;
reminder = new visual.TextBox({
win: psychoJS.window,
name: "reminder",
text: "Press SPACE to pump the balloon\nPress RETURN to bank this sum",
placeholder: "Type here...",
font: "Arial",
pos: [-0.4, -0.3],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -3.0,
});
balloonValTxt = new visual.TextBox({
win: psychoJS.window,
name: "balloonValTxt",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [-0.4, 0.4],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -4.0,
});
bankedTxt = new visual.TextBox({
win: psychoJS.window,
name: "bankedTxt",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [0.4, 0.4],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -5.0,
});
// Run 'Begin Experiment' code from setBalloonSize
balloonSize = 0.08;
balloonMsgHeight = 0.01;
balloonBody = new visual.ImageStim({
win: psychoJS.window,
name: "balloonBody",
units: "height",
image: "assets/redBalloon.png",
mask: undefined,
anchor: "center",
ori: -90,
pos: [0, 0],
draggable: false,
size: 1.0,
color: new util.Color([1, 1, 1]),
opacity: 1,
flipHoriz: false,
flipVert: false,
texRes: 128,
interpolate: true,
depth: -7.0,
});
trialcount = new visual.TextBox({
win: psychoJS.window,
name: "trialcount",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [0.4, -0.3],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -8.0,
});
// Initialize components for Routine "feedback"
feedbackClock = new util.Clock();
background_3 = new visual.ImageStim({
win: psychoJS.window,
name: "background_3",
units: undefined,
image: "assets/background.png",
mask: undefined,
anchor: "center",
ori: 0.0,
pos: [0, 0],
draggable: false,
size: [2.2, 1],
color: new util.Color([1, 1, 1]),
opacity: undefined,
flipHoriz: false,
flipVert: false,
texRes: 128.0,
interpolate: true,
depth: 0.0,
});
// Run 'Begin Experiment' code from checkPopped
feedbackText = "";
feedbacktxt = new visual.TextBox({
win: psychoJS.window,
name: "feedbacktxt",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [0, 0],
draggable: false,
letterHeight: 0.05,
lineSpacing: 1.0,
size: [0.4, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: undefined,
borderColor: undefined,
languageStyle: "LTR",
bold: false,
italic: false,
opacity: undefined,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -2.0,
});
bankedTxt_2 = new visual.TextBox({
win: psychoJS.window,
name: "bankedTxt_2",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [0.4, 0.4],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -3.0,
});
balloonValTxt_2 = new visual.TextBox({
win: psychoJS.window,
name: "balloonValTxt_2",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [-0.4, 0.4],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -4.0,
});
reminder_2 = new visual.TextBox({
win: psychoJS.window,
name: "reminder_2",
text: "Press SPACE to pump the balloon\nPress RETURN to bank this sum",
placeholder: "Type here...",
font: "Arial",
pos: [-0.4, -0.3],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -5.0,
});
trialcount_2 = new visual.TextBox({
win: psychoJS.window,
name: "trialcount_2",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [0.4, -0.3],
draggable: false,
letterHeight: 0.03,
lineSpacing: 1.0,
size: [0.5, 0.2],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -6.0,
});
// Initialize components for Routine "finalScore"
finalScoreClock = new util.Clock();
background_4 = new visual.ImageStim({
win: psychoJS.window,
name: "background_4",
units: undefined,
image: "assets/background.png",
mask: undefined,
anchor: "center",
ori: 0.0,
pos: [0, 0],
draggable: false,
size: [2.2, 1],
color: new util.Color([1, 1, 1]),
opacity: undefined,
flipHoriz: false,
flipVert: false,
texRes: 128.0,
interpolate: true,
depth: 0.0,
});
scoremsg = new visual.TextBox({
win: psychoJS.window,
name: "scoremsg",
text: "",
placeholder: "Type here...",
font: "Arial",
pos: [0, 0],
draggable: false,
letterHeight: 0.04,
lineSpacing: 1.0,
size: [1, 0.7],
units: undefined,
ori: 0.0,
color: "black",
colorSpace: "rgb",
fillColor: "white",
borderColor: "black",
languageStyle: "LTR",
bold: false,
italic: false,
opacity: 0.8,
padding: 0.0,
alignment: "center",
overflow: "visible",
editable: false,
multiline: true,
anchor: "center",
depth: -2.0,
});
// 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 t;
var frameN;
var continueRoutine;
var instructionsMaxDurationReached;
var _resp_allKeys;
var instructionsMaxDuration;
var instructionsComponents;
function instructionsRoutineBegin(snapshot) {
return async function () {
TrialHandler.fromSnapshot(snapshot); // ensure that .thisN vals are up to date
//--- Prepare to start Routine 'instructions' ---
t = 0;
frameN = -1;
continueRoutine = true; // until we're told otherwise
instructionsClock.reset();
routineTimer.reset();
instructionsMaxDurationReached = false;
// update component parameters for each repeat
resp.keys = undefined;
resp.rt = undefined;
_resp_allKeys = [];
pop_sound.secs = 1.0;
pop_sound.setVolume(0.0);
psychoJS.experiment.addData("instructions.started", globalClock.getTime());
instructionsMaxDuration = null;
// keep track of which components have finished
instructionsComponents = [];
instructionsComponents.push(background);
instructionsComponents.push(resp);
instructionsComponents.push(instrtxt);
instructionsComponents.push(pop_sound);
for (const thisComponent of instructionsComponents)
if ("status" in thisComponent)
thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;
};
}
var frameRemains;
function instructionsRoutineEachFrame() {
return async function () {
//--- Loop for each frame of Routine 'instructions' ---
// get current time
t = instructionsClock.getTime();
frameN = frameN + 1; // number of completed frames (so 0 is the first frame)
// update/draw components on each frame
// *background* updates
if (t >= 0.0 && background.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
background.tStart = t; // (not accounting for frame time here)
background.frameNStart = frameN; // exact frame index
background.setAutoDraw(true);
}
......some code was removed......
if (resp.status === PsychoJS.Status.STARTED) {
let theseKeys = resp.getKeys({ keyList: ["space"], waitRelease: false });
_resp_allKeys = _resp_allKeys.concat(theseKeys);
if (_resp_allKeys.length > 0) {
resp.keys = _resp_allKeys[_resp_allKeys.length - 1].name; // just the last key pressed
resp.rt = _resp_allKeys[_resp_allKeys.length - 1].rt;
resp.duration = _resp_allKeys[_resp_allKeys.length - 1].duration;
// a response ends the routine
continueRoutine = false;
}
}
// *instrtxt* updates
if (t >= 0.0 && instrtxt.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
instrtxt.tStart = t; // (not accounting for frame time here)
instrtxt.frameNStart = frameN; // exact frame index
instrtxt.setAutoDraw(true);
}
// start/stop pop_sound
if (t >= 0.0 && pop_sound.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
pop_sound.tStart = t; // (not accounting for frame time here)
pop_sound.frameNStart = frameN; // exact frame index
psychoJS.window.callOnFlip(function () {
pop_sound.play();
}); // screen flip
pop_sound.status = PsychoJS.Status.STARTED;
}
frameRemains = 0.0 + 1.0 - psychoJS.window.monitorFramePeriod * 0.75; // most of one frame period left
if (pop_sound.status === PsychoJS.Status.STARTED && t >= frameRemains) {
if (t >= pop_sound.tStart + 0.5) {
pop_sound.stop(); // stop the sound (if longer than duration)
pop_sound.status = PsychoJS.Status.FINISHED;
}
}
// 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 instructionsComponents)
if (
"status" in thisComponent &&
thisComponent.status !== PsychoJS.Status.FINISHED
) {
continueRoutine = true;
break;
}
// refresh the screen if continuing
if (continueRoutine) {
return Scheduler.Event.FLIP_REPEAT;
} else {
return Scheduler.Event.NEXT;
}
};
}
function instructionsRoutineEnd(snapshot) {
return async function () {
//--- Ending Routine 'instructions' ---
for (const thisComponent of instructionsComponents) {
if (typeof thisComponent.setAutoDraw === "function") {
thisComponent.setAutoDraw(false);
}
}
psychoJS.experiment.addData("instructions.stopped", globalClock.getTime());
resp.stop();
pop_sound.stop(); // ensure sound has stopped at end of Routine
// the Routine "instructions" was not non-slip safe, so reset the non-slip timer
routineTimer.reset();
// Routines running outside a loop should always advance the datafile row
if (currentLoop === psychoJS.experiment) {
psychoJS.experiment.nextEntry(snapshot);
}
return Scheduler.Event.NEXT;
};
}
var trials;
function trialsLoopBegin(trialsLoopScheduler, snapshot) {
return async function () {
TrialHandler.fromSnapshot(snapshot); // update internal variables (.thisN etc) of the loop
// set up handler to look after randomisation of conditions etc
trials = new TrialHandler({
psychoJS: psychoJS,
nReps: 1,
method: TrialHandler.Method.RANDOM,
extraInfo: expInfo,
originPath: undefined,
trialList: "spreadsheets/conditions.xlsx",
seed: 1832,
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) {
snapshot = trials.getSnapshot();
trialsLoopScheduler.add(importConditions(snapshot));
trialsLoopScheduler.add(reset_balloonRoutineBegin(snapshot));
trialsLoopScheduler.add(reset_balloonRoutineEachFrame());
trialsLoopScheduler.add(reset_balloonRoutineEnd(snapshot));
const pumpLoopScheduler = new Scheduler(psychoJS);
trialsLoopScheduler.add(pumpLoopBegin(pumpLoopScheduler, snapshot));
trialsLoopScheduler.add(pumpLoopScheduler);
trialsLoopScheduler.add(pumpLoopEnd);
trialsLoopScheduler.add(feedbackRoutineBegin(snapshot));
trialsLoopScheduler.add(feedbackRoutineEachFrame());
trialsLoopScheduler.add(feedbackRoutineEnd(snapshot));
trialsLoopScheduler.add(
trialsLoopEndIteration(trialsLoopScheduler, snapshot)
);
}
return Scheduler.Event.NEXT;
};
}
var pump;
function pumpLoopBegin(pumpLoopScheduler, snapshot) {
return async function () {
TrialHandler.fromSnapshot(snapshot); // update internal variables (.thisN etc) of the loop
// set up handler to look after randomisation of conditions etc
pump = new TrialHandler({
psychoJS: psychoJS,
nReps: maxPumps,
method: TrialHandler.Method.RANDOM,
extraInfo: expInfo,
originPath: undefined,
trialList: undefined,
seed: undefined,
name: "pump",
});
psychoJS.experiment.addLoop(pump); // add the loop to the experiment
currentLoop = pump; // we're now the current loop
// Schedule all the trials in the trialList:
for (const thisPump of pump) {
snapshot = pump.getSnapshot();
pumpLoopScheduler.add(importConditions(snapshot));
pumpLoopScheduler.add(trialRoutineBegin(snapshot));
pumpLoopScheduler.add(trialRoutineEachFrame());
pumpLoopScheduler.add(trialRoutineEnd(snapshot));
pumpLoopScheduler.add(pumpLoopEndIteration(pumpLoopScheduler, snapshot));
}
return Scheduler.Event.NEXT;
};
}
async function pumpLoopEnd() {
// terminate loop
psychoJS.experiment.removeLoop(pump);
// update the current loop from the ExperimentHandler
if (psychoJS.experiment._unfinishedLoops.length > 0)
currentLoop = psychoJS.experiment._unfinishedLoops.at(-1);
else currentLoop = psychoJS.experiment; // so we use addData from the experiment
return Scheduler.Event.NEXT;
}
function pumpLoopEndIteration(scheduler, snapshot) {
// ------Prepare for next entry------
return async function () {
if (typeof snapshot !== "undefined") {
// ------Check if user ended loop early------
if (snapshot.finished) {
// Check for and save orphaned data
if (psychoJS.experiment.isEntryEmpty()) {
psychoJS.experiment.nextEntry(snapshot);
}
scheduler.stop();
}
return Scheduler.Event.NEXT;
}
};
}
async function trialsLoopEnd() {
// terminate loop
psychoJS.experiment.removeLoop(trials);
// update the current loop from the ExperimentHandler
if (psychoJS.experiment._unfinishedLoops.length > 0)
currentLoop = psychoJS.experiment._unfinishedLoops.at(-1);
else currentLoop = psychoJS.experiment; // so we use addData from the experiment
return Scheduler.Event.NEXT;
}
function trialsLoopEndIteration(scheduler, snapshot) {
// ------Prepare for next entry------
return async function () {
if (typeof snapshot !== "undefined") {
// ------Check if user ended loop early------
if (snapshot.finished) {
// Check for and save orphaned data
if (psychoJS.experiment.isEntryEmpty()) {
psychoJS.experiment.nextEntry(snapshot);
}
scheduler.stop();
} else {
psychoJS.experiment.nextEntry(snapshot);
}
return Scheduler.Event.NEXT;
}
};
}
var reset_balloonMaxDurationReached;
var popped;
var nPumps;
var reset_balloonMaxDuration;
var reset_balloonComponents;
function reset_balloonRoutineBegin(snapshot) {
return async function () {
TrialHandler.fromSnapshot(snapshot); // ensure that .thisN vals are up to date
//--- Prepare to start Routine 'reset_balloon' ---
t = 0;
frameN = -1;
continueRoutine = true; // until we're told otherwise
reset_balloonClock.reset();
routineTimer.reset();
reset_balloonMaxDurationReached = false;
// update component parameters for each repeat
// Run 'Begin Routine' code from code
balloonSize = 0.08;
popped = false;
nPumps = 0;
psychoJS.experiment.addData("reset_balloon.started", globalClock.getTime());
reset_balloonMaxDuration = null;
// keep track of which components have finished
reset_balloonComponents = [];
for (const thisComponent of reset_balloonComponents)
if ("status" in thisComponent)
thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;
};
}
function reset_balloonRoutineEachFrame() {
return async function () {
//--- Loop for each frame of Routine 'reset_balloon' ---
// get current time
t = reset_balloonClock.getTime();
frameN = frameN + 1; // number of completed frames (so 0 is the first frame)
// update/draw components on each frame
// 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 reset_balloonComponents)
if (
"status" in thisComponent &&
thisComponent.status !== PsychoJS.Status.FINISHED
) {
continueRoutine = true;
break;
}
// refresh the screen if continuing
if (continueRoutine) {
return Scheduler.Event.FLIP_REPEAT;
} else {
return Scheduler.Event.NEXT;
}
};
}
.......................some code was removed because it was too much.........................
function feedbackRoutineEnd(snapshot) {
return async function () {
//--- Ending Routine 'feedback' ---
for (const thisComponent of feedbackComponents) {
if (typeof thisComponent.setAutoDraw === "function") {
thisComponent.setAutoDraw(false);
}
}
psychoJS.experiment.addData("feedback.stopped", globalClock.getTime());
if (feedbackMaxDurationReached) {
feedbackClock.add(feedbackMaxDuration);
} else {
feedbackClock.add(1.5);
}
// Routines running outside a loop should always advance the datafile row
if (currentLoop === psychoJS.experiment) {
psychoJS.experiment.nextEntry(snapshot);
}
return Scheduler.Event.NEXT;
};
}
var finalScoreMaxDurationReached;
var scoreText;
var finalScoreMaxDuration;
var finalScoreComponents;
function finalScoreRoutineBegin(snapshot) {
return async function () {
TrialHandler.fromSnapshot(snapshot); // ensure that .thisN vals are up to date
//--- Prepare to start Routine 'finalScore' ---
t = 0;
frameN = -1;
continueRoutine = true; // until we're told otherwise
finalScoreClock.reset();
routineTimer.reset();
finalScoreMaxDurationReached = false;
// update component parameters for each repeat
// Run 'Begin Routine' code from finalScoreCode
scoreText =
"Well done! You banked a total of\n£" + bankedEarnings.toFixed(2);
scoremsg.setText(scoreText);
psychoJS.experiment.addData("finalScore.started", globalClock.getTime());
finalScoreMaxDuration = null;
// keep track of which components have finished
finalScoreComponents = [];
finalScoreComponents.push(background_4);
finalScoreComponents.push(scoremsg);
for (const thisComponent of finalScoreComponents)
if ("status" in thisComponent)
thisComponent.status = PsychoJS.Status.NOT_STARTED;
return Scheduler.Event.NEXT;
};
}
function finalScoreRoutineEachFrame() {
return async function () {
//--- Loop for each frame of Routine 'finalScore' ---
// get current time
t = finalScoreClock.getTime();
frameN = frameN + 1; // number of completed frames (so 0 is the first frame)
// update/draw components on each frame
// *background_4* updates
if (t >= 0.0 && background_4.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
background_4.tStart = t; // (not accounting for frame time here)
background_4.frameNStart = frameN; // exact frame index
background_4.setAutoDraw(true);
}
// *scoremsg* updates
if (t >= 0.0 && scoremsg.status === PsychoJS.Status.NOT_STARTED) {
// keep track of start time/frame for later
scoremsg.tStart = t; // (not accounting for frame time here)
scoremsg.frameNStart = frameN; // exact frame index
scoremsg.setAutoDraw(true);
}
// 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 finalScoreComponents)
if (
"status" in thisComponent &&
thisComponent.status !== PsychoJS.Status.FINISHED
) {
continueRoutine = true;
break;
}
// refresh the screen if continuing
if (continueRoutine) {
return Scheduler.Event.FLIP_REPEAT;
} else {
return Scheduler.Event.NEXT;
}
};
}
function finalScoreRoutineEnd(snapshot) {
return async function () {
//--- Ending Routine 'finalScore' ---
for (const thisComponent of finalScoreComponents) {
if (typeof thisComponent.setAutoDraw === "function") {
thisComponent.setAutoDraw(false);
}
}
console.log("finalScore ended");
//firebase
await fetch(
"https://data-handler-efc09-default-rtdb.europe-west1.firebasedatabase.app/experiments.json",
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
alma: "piros",
}),
}
);
psychoJS.experiment.addData("finalScore.stopped", globalClock.getTime());
// the Routine "finalScore" was not non-slip safe, so reset the non-slip timer
routineTimer.reset();
// Routines running outside a loop should always advance the datafile row
if (currentLoop === psychoJS.experiment) {
psychoJS.experiment.nextEntry(snapshot);
}
return Scheduler.Event.NEXT;
};
}
function importConditions(currentLoop) {
return async function () {
psychoJS.importAttributes(currentLoop.getCurrentTrial());
return Scheduler.Event.NEXT;
};
}
async 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;
}