text: ﻿/********************* 
   * Gonogoalpha6 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 = 'goNogoAlpha6';  // 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);
  flowScheduler.add(setupRoutineBegin());
  flowScheduler.add(setupRoutineEachFrame());
  flowScheduler.add(setupRoutineEnd());
  const tasksLoopScheduler = new Scheduler(psychoJS);
  flowScheduler.add(tasksLoopBegin, tasksLoopScheduler);
  flowScheduler.add(tasksLoopScheduler);
  flowScheduler.add(tasksLoopEnd);
  flowScheduler.add(endRoutineBegin());
  flowScheduler.add(endRoutineEachFrame());
  flowScheduler.add(endRoutineEnd());
  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 setupClock;
  var thisExp;
  var win;
  var event;
  var shuffle;
  var pi;
  var sin;
  var cos;
  var sqrt;
  var randint;
  var counterTask;
  var instrClock;
  var instrText;
  var instrResp;
  var instrImg;
  var trialClock;
  var trialCircle;
  var trialResp;
  var trialText;
  var trialCount;
  var endClock;
  var endText;
  var endResp;
  var globalClock;
  var routineTimer;
  function experimentInit() {
    // Initialize components for Routine "setup"
    setupClock = new util.Clock();
    // Code to fix reference errors in JS
    thisExp = psychoJS.experiment;
    win = psychoJS.window;
    event = psychoJS.eventManager;
    Array.prototype.append = [].push;
    shuffle = util.shuffle;
    document.documentElement.style.cursor = 'none';
    // Math related fixes
    pi = Math.PI;
    sin = Math.sin;
    cos = Math.cos;
    sqrt = Math.sqrt;
    randint = function(min, maxplusone) {
      return Math.floor(Math.random() * (maxplusone - min) ) + min;
    }
    shuffle = util.shuffle;
    counterTask = 1;
    
    // Initialize components for Routine "instr"
    instrClock = new util.Clock();
    instrText = new visual.TextStim({
      win: psychoJS.window,
      name: 'instrText',
      text: 'Space',
      font: 'Arial',
      units: undefined, 
      pos: [(- 0.3), 0], height: 0.05,  wrapWidth: undefined, ori: 0,
      color: new util.Color('white'),  opacity: 1,
      depth: -1.0 
    });
    
    instrResp = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true});
    
    instrImg = new visual.ImageStim({
      win : psychoJS.window,
      name : 'instrImg', units : undefined, 
      image : 'gonogo.png', mask : undefined,
      ori : 0, pos : [0.5, 0.0], size : [0.6, 1],
      color : new util.Color([1, 1, 1]), opacity : 1,
      flipHoriz : false, flipVert : false,
      texRes : 128, interpolate : true, depth : -3.0 
    });
    // Initialize components for Routine "trial"
    trialClock = new util.Clock();
    trialCircle = new visual.Polygon ({
      win: psychoJS.window, name: 'trialCircle', 
      edges: 180, size:[0.5, 0.5],
      ori: 0, pos: [0, 0],
      lineWidth: 1, lineColor: new util.Color(1.0),
      fillColor: new util.Color(1.0),
      opacity: 1, depth: -1, interpolate: true,
    });
    
    trialResp = new core.Keyboard({psychoJS: psychoJS, clock: new util.Clock(), waitForStart: true});
    
    trialText = new visual.TextStim({
      win: psychoJS.window,
      name: 'trialText',
      text: '',
      font: 'Arial',
      units: undefined, 
      pos: [0, 0], height: 0.1,  wrapWidth: undefined, ori: 0,
      color: new util.Color('white'),  opacity: 1,
      depth: -3.0 
    });
    
    trialCount = new visual.TextStim({
      win: psychoJS.window,
      name: 'trialCount',
      text: '',
      font: 'Arial',
      units: undefined, 
      pos: [(- 0.4), 0.4], height: 0.05,  wrapWidth: undefined, ori: 0,
      color: new util.Color('white'),  opacity: 1,
      depth: -4.0 
    });
    
    // Initialize components for Routine "end"
    endClock = new util.Clock();
    endText = new visual.TextStim({
      win: psychoJS.window,
      name: 'endText',
      text: 'This is the end of the experiment. Thank you for your time. Please remember to return to the questionnaire to carry on with the study. Press ‘space’ to finish experiment.',
      font: 'Arial',
      units: undefined, 
      pos: [0, 0], height: 0.05,  wrapWidth: undefined, ori: 0,
      color: new util.Color('white'),  opacity: 1,
      depth: 0.0 
    });
    
    endResp = 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 t;
  var frameN;
  var setupComponents;
  function setupRoutineBegin(trials) {
    return function () {
      //------Prepare to start Routine 'setup'-------
      t = 0;
      setupClock.reset(); // clock
      frameN = -1;
      // update component parameters for each repeat
      // keep track of which components have finished
      setupComponents = [];
      
      for (const thisComponent of setupComponents)
        if ('status' in thisComponent)
          thisComponent.status = PsychoJS.Status.NOT_STARTED;
      
      return Scheduler.Event.NEXT;
    };
  }
  
  
  var continueRoutine;
  function setupRoutineEachFrame(trials) {
    return function () {
      //------Loop for each frame of Routine 'setup'-------
      let continueRoutine = true; // until we're told otherwise
      // get current time
      t = setupClock.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 setupComponents)
        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 setupRoutineEnd(trials) {
    return function () {
      //------Ending Routine 'setup'-------
      for (const thisComponent of setupComponents) {
        if (typeof thisComponent.setAutoDraw === 'function') {
          thisComponent.setAutoDraw(false);
        }
      }
      // the Routine "setup" was not non-slip safe, so reset the non-slip timer
      routineTimer.reset();
      
      return Scheduler.Event.NEXT;
    };
  }
  
  
  var tasks;
  var currentLoop;
  function tasksLoopBegin(thisScheduler) {
    // set up handler to look after randomisation of conditions etc
    tasks = new TrialHandler({
      psychoJS: psychoJS,
      nReps: 3, method: TrialHandler.Method.SEQUENTIAL,
      extraInfo: expInfo, originPath: undefined,
      trialList: undefined,
      seed: undefined, name: 'tasks'
    });
    psychoJS.experiment.addLoop(tasks); // add the loop to the experiment
    currentLoop = tasks;  // we're now the current loop
  
    // Schedule all the trials in the trialList:
    for (const thisTask of tasks) {
      const snapshot = tasks.getSnapshot();
      thisScheduler.add(importConditions(snapshot));
      thisScheduler.add(instrRoutineBegin(snapshot));
      thisScheduler.add(instrRoutineEachFrame(snapshot));
      thisScheduler.add(instrRoutineEnd(snapshot));
      const trialsLoopScheduler = new Scheduler(psychoJS);
      thisScheduler.add(trialsLoopBegin, trialsLoopScheduler);
      thisScheduler.add(trialsLoopScheduler);
      thisScheduler.add(trialsLoopEnd);
      thisScheduler.add(endLoopIteration(thisScheduler, snapshot));
    }
  
    return Scheduler.Event.NEXT;
  }
  
  
  var trials;
  function trialsLoopBegin(thisScheduler) {
    // set up handler to look after randomisation of conditions etc
    trials = new TrialHandler({
      psychoJS: psychoJS,
      nReps: 100, method: TrialHandler.Method.SEQUENTIAL,
      extraInfo: expInfo, originPath: undefined,
      trialList: undefined,
      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;
  }
  
  
  function tasksLoopEnd() {
    psychoJS.experiment.removeLoop(tasks);
  
    return Scheduler.Event.NEXT;
  }
  
  
  var colorChoice;
  var colorBlock;
  var _instrResp_allKeys;
  var instrComponents;
  function instrRoutineBegin(trials) {
    return function () {
      //------Prepare to start Routine 'instr'-------
      t = 0;
      instrClock.reset(); // clock
      frameN = -1;
      // update component parameters for each repeat
      if ((counterTask === 1)) {
          instrText.text = "For this task, please press 'space' when you see the blue circle, and press nothing for orange. There are 300 total trials split into 3 trial blocks with 100 trials each. Press 's' to start.";
      } else {
          instrText.text = "Time for a break if you need it. Again, please press 'space' when you see the blue circle, and press nothing for orange. There are 300 total trials split into 3 trial blocks with 100 trials each. Press 's' to start.";
      }
      colorChoice = [0, 0, 0, 0, 1];
      colorBlock = [1, 0, 0, 0, 0];
      for (var i = 0, _pj_a = 19; (i < _pj_a); i += 1) {
          shuffle(colorBlock);
          for (var j = 0, _pj_b = 5; (j < _pj_b); j += 1) {
              colorChoice.append(colorBlock[j]);
          }
      }
      counterTask = (counterTask + 1);
      
      instrResp.keys = undefined;
      instrResp.rt = undefined;
      _instrResp_allKeys = [];
      // keep track of which components have finished
      instrComponents = [];
      instrComponents.push(instrText);
      instrComponents.push(instrResp);
      instrComponents.push(instrImg);
      
      for (const thisComponent of instrComponents)
        if ('status' in thisComponent)
          thisComponent.status = PsychoJS.Status.NOT_STARTED;
      
      return Scheduler.Event.NEXT;
    };
  }
  
  
  function instrRoutineEachFrame(trials) {
    return function () {
      //------Loop for each frame of Routine 'instr'-------
      let continueRoutine = true; // until we're told otherwise
      // get current time
      t = instrClock.getTime();
      frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
      // update/draw components on each frame
      
      // *instrText* updates
      if (t >= 0.0 && instrText.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        instrText.tStart = t;  // (not accounting for frame time here)
        instrText.frameNStart = frameN;  // exact frame index
        
        instrText.setAutoDraw(true);
      }
  
      
      // *instrResp* updates
      if (t >= 0.0 && instrResp.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        instrResp.tStart = t;  // (not accounting for frame time here)
        instrResp.frameNStart = frameN;  // exact frame index
        
        // keyboard checking is just starting
        psychoJS.window.callOnFlip(function() { instrResp.clock.reset(); });  // t=0 on next screen flip
        psychoJS.window.callOnFlip(function() { instrResp.start(); }); // start on screen flip
        psychoJS.window.callOnFlip(function() { instrResp.clearEvents(); });
      }
  
      if (instrResp.status === PsychoJS.Status.STARTED) {
        let theseKeys = instrResp.getKeys({keyList: ['s'], waitRelease: false});
        _instrResp_allKeys = _instrResp_allKeys.concat(theseKeys);
        if (_instrResp_allKeys.length > 0) {
          instrResp.keys = _instrResp_allKeys[_instrResp_allKeys.length - 1].name;  // just the last key pressed
          instrResp.rt = _instrResp_allKeys[_instrResp_allKeys.length - 1].rt;
          // a response ends the routine
          continueRoutine = false;
        }
      }
      
      
      // *instrImg* updates
      if (t >= 0.0 && instrImg.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        instrImg.tStart = t;  // (not accounting for frame time here)
        instrImg.frameNStart = frameN;  // exact frame index
        
        instrImg.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 instrComponents)
        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 instrRoutineEnd(trials) {
    return function () {
      //------Ending Routine 'instr'-------
      for (const thisComponent of instrComponents) {
        if (typeof thisComponent.setAutoDraw === 'function') {
          thisComponent.setAutoDraw(false);
        }
      }
      // the Routine "instr" was not non-slip safe, so reset the non-slip timer
      routineTimer.reset();
      
      return Scheduler.Event.NEXT;
    };
  }
  
  
  var colorPick;
  var colorName;
  var corrAns;
  var _trialResp_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
      if ((colorChoice[trials.thisN] === 1)) {
          colorPick = [1.0, 0.004, (- 1.0)];
          colorName = "orange";
          trialText.text = "NO GO";
      } else {
          colorPick = [(- 1.0), (- 1.0), 1.0];
          colorName = "blue";
          trialText.text = "GO";
      }
      if ((colorName === "blue")) {
          corrAns = "space";
      } else {
          corrAns = "None";
      }
      trialCount.text = ((trials.thisN + 1).toString() + " / 100");
      
      trialCircle.setFillColor(new util.Color(colorPick));
      trialCircle.setLineColor(new util.Color(colorPick));
      trialResp.keys = undefined;
      trialResp.rt = undefined;
      _trialResp_allKeys = [];
      // keep track of which components have finished
      trialComponents = [];
      trialComponents.push(trialCircle);
      trialComponents.push(trialResp);
      trialComponents.push(trialText);
      trialComponents.push(trialCount);
      
      for (const thisComponent of trialComponents)
        if ('status' in thisComponent)
          thisComponent.status = PsychoJS.Status.NOT_STARTED;
      
      return Scheduler.Event.NEXT;
    };
  }
  
  
  var frameRemains;
  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
      
      // *trialCircle* updates
      if (t >= 0.25 && trialCircle.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        trialCircle.tStart = t;  // (not accounting for frame time here)
        trialCircle.frameNStart = frameN;  // exact frame index
        
        trialCircle.setAutoDraw(true);
      }
  
      frameRemains = 0.25 + 1.75 - psychoJS.window.monitorFramePeriod * 0.75;  // most of one frame period left
      if (trialCircle.status === PsychoJS.Status.STARTED && t >= frameRemains) {
        trialCircle.setAutoDraw(false);
      }
      
      // *trialResp* updates
      if (t >= 0.25 && trialResp.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        trialResp.tStart = t;  // (not accounting for frame time here)
        trialResp.frameNStart = frameN;  // exact frame index
        
        // keyboard checking is just starting
        psychoJS.window.callOnFlip(function() { trialResp.clock.reset(); });  // t=0 on next screen flip
        psychoJS.window.callOnFlip(function() { trialResp.start(); }); // start on screen flip
        psychoJS.window.callOnFlip(function() { trialResp.clearEvents(); });
      }
  
      frameRemains = 0.25 + 1.75 - psychoJS.window.monitorFramePeriod * 0.75;  // most of one frame period left
      if (trialResp.status === PsychoJS.Status.STARTED && t >= frameRemains) {
        trialResp.status = PsychoJS.Status.FINISHED;
    }
  
      if (trialResp.status === PsychoJS.Status.STARTED) {
        let theseKeys = trialResp.getKeys({keyList: ['space'], waitRelease: false});
        _trialResp_allKeys = _trialResp_allKeys.concat(theseKeys);
        if (_trialResp_allKeys.length > 0) {
          trialResp.keys = _trialResp_allKeys[_trialResp_allKeys.length - 1].name;  // just the last key pressed
          trialResp.rt = _trialResp_allKeys[_trialResp_allKeys.length - 1].rt;
          // was this correct?
          if (trialResp.keys == corrAns) {
              trialResp.corr = 1;
          } else {
              trialResp.corr = 0;
          }
          // a response ends the routine
          continueRoutine = false;
        }
      }
      
      
      // *trialText* updates
      if (t >= 0.25 && trialText.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        trialText.tStart = t;  // (not accounting for frame time here)
        trialText.frameNStart = frameN;  // exact frame index
        
        trialText.setAutoDraw(true);
      }
  
      frameRemains = 0.25 + 1.75 - psychoJS.window.monitorFramePeriod * 0.75;  // most of one frame period left
      if (trialText.status === PsychoJS.Status.STARTED && t >= frameRemains) {
        trialText.setAutoDraw(false);
      }
      
      // *trialCount* updates
      if (t >= 0.0 && trialCount.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        trialCount.tStart = t;  // (not accounting for frame time here)
        trialCount.frameNStart = frameN;  // exact frame index
        
        trialCount.setAutoDraw(true);
      }
  
      frameRemains = 0.0 + 2 - psychoJS.window.monitorFramePeriod * 0.75;  // most of one frame period left
      if (trialCount.status === PsychoJS.Status.STARTED && t >= frameRemains) {
        trialCount.setAutoDraw(false);
      }
      // 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);
        }
      }
      thisExp.addData("corrAns", corrAns);
      thisExp.addData("colorName", colorName);
      
      // was no response the correct answer?!
      if (trialResp.keys === undefined) {
        if (['None','none',undefined].includes(corrAns)) {
           trialResp.corr = 1;  // correct non-response
        } else {
           trialResp.corr = 0;  // failed to respond (incorrectly)
        }
      }
      // store data for thisExp (ExperimentHandler)
      psychoJS.experiment.addData('trialResp.keys', trialResp.keys);
      psychoJS.experiment.addData('trialResp.corr', trialResp.corr);
      if (typeof trialResp.keys !== 'undefined') {  // we had a response
          psychoJS.experiment.addData('trialResp.rt', trialResp.rt);
          routineTimer.reset();
          }
      
      trialResp.stop();
      return Scheduler.Event.NEXT;
    };
  }
  
  
  var _endResp_allKeys;
  var endComponents;
  function endRoutineBegin(trials) {
    return function () {
      //------Prepare to start Routine 'end'-------
      t = 0;
      endClock.reset(); // clock
      frameN = -1;
      // update component parameters for each repeat
      endResp.keys = undefined;
      endResp.rt = undefined;
      _endResp_allKeys = [];
      // keep track of which components have finished
      endComponents = [];
      endComponents.push(endText);
      endComponents.push(endResp);
      
      for (const thisComponent of endComponents)
        if ('status' in thisComponent)
          thisComponent.status = PsychoJS.Status.NOT_STARTED;
      
      return Scheduler.Event.NEXT;
    };
  }
  
  
  function endRoutineEachFrame(trials) {
    return function () {
      //------Loop for each frame of Routine 'end'-------
      let continueRoutine = true; // until we're told otherwise
      // get current time
      t = endClock.getTime();
      frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
      // update/draw components on each frame
      
      // *endText* updates
      if (t >= 0.0 && endText.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        endText.tStart = t;  // (not accounting for frame time here)
        endText.frameNStart = frameN;  // exact frame index
        
        endText.setAutoDraw(true);
      }
  
      
      // *endResp* updates
      if (t >= 0.0 && endResp.status === PsychoJS.Status.NOT_STARTED) {
        // keep track of start time/frame for later
        endResp.tStart = t;  // (not accounting for frame time here)
        endResp.frameNStart = frameN;  // exact frame index
        
        // keyboard checking is just starting
        psychoJS.window.callOnFlip(function() { endResp.clock.reset(); });  // t=0 on next screen flip
        psychoJS.window.callOnFlip(function() { endResp.start(); }); // start on screen flip
        psychoJS.window.callOnFlip(function() { endResp.clearEvents(); });
      }
  
      if (endResp.status === PsychoJS.Status.STARTED) {
        let theseKeys = endResp.getKeys({keyList: ['space'], waitRelease: false});
        _endResp_allKeys = _endResp_allKeys.concat(theseKeys);
        if (_endResp_allKeys.length > 0) {
          endResp.keys = _endResp_allKeys[_endResp_allKeys.length - 1].name;  // just the last key pressed
          endResp.rt = _endResp_allKeys[_endResp_allKeys.length - 1].rt;
          // a response ends the routine
          continueRoutine = false;
        }
      }
      
      // 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 endComponents)
        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 endRoutineEnd(trials) {
    return function () {
      //------Ending Routine 'end'-------
      for (const thisComponent of endComponents) {
        if (typeof thisComponent.setAutoDraw === 'function') {
          thisComponent.setAutoDraw(false);
        }
      }
      // the Routine "end" was not non-slip safe, so reset the non-slip timer
      routineTimer.reset();
      
      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();
    }
    
    
    
    document.documentElement.style.cursor = 'auto';
    
    
    
    
    
    psychoJS.window.close();
    psychoJS.quit({message: message, isCompleted: isCompleted});
    
    return Scheduler.Event.QUIT;
  }
  