#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
This experiment was created using PsychoPy3 Experiment Builder (v2023.2.3),
    on 一月 17, 2024, at 17:36
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) 
        PsychoPy2: Experiments in behavior made easy Behav Res 51: 195. 
        https://doi.org/10.3758/s13428-018-01193-y

"""

# --- Import packages ---
from psychopy import locale_setup
from psychopy import prefs
from psychopy import plugins
plugins.activatePlugins()
prefs.hardware['audioLib'] = 'ptb'
prefs.hardware['audioLatencyMode'] = '3'
from psychopy import sound, gui, visual, core, data, event, logging, clock, colors, layout
from psychopy.tools import environmenttools
from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
                                STOPPED, FINISHED, PRESSED, RELEASED, FOREVER, priority)

import numpy as np  # whole numpy lib is available, prepend 'np.'
from numpy import (sin, cos, tan, log, log10, pi, average,
                   sqrt, std, deg2rad, rad2deg, linspace, asarray)
from numpy.random import random, randint, normal, shuffle, choice as randchoice
import os  # handy system and path functions
import sys  # to get file system encoding

import psychopy.iohub as io
from psychopy.hardware import keyboard

# Run 'Before Experiment' code from config
import argparse
from device.trigger_box import TriggerNeuracle
# get train params
def parse_args():
    parser = argparse.ArgumentParser(
        description='Daily routine'
    )
    parser.add_argument(
        '--side',
        dest='side',
        help='left hand or right hand',
        type=str
    )
    parser.add_argument(
        '--trial-num',
        dest='trial_num',
        help='total trial number',
        type=int
    )
    parser.add_argument(
        '--major-side-num',
        dest='major_side_num',
        help='trial number of major side',
        type=int
    )
    parser.add_argument(
        '--trigger-port',
        dest='trigger_port',
        help='Triggerbox serial port',
        type=str
    )
    return parser.parse_args()
args = parse_args()

# connect to trigger box
trigger = TriggerNeuracle(port=args.trigger_port)

# Run 'Before Experiment' code from assign_L_R_trails
import random
trials_list = []
for i in range(args.trial_num):
    trials_list.append(i+1)
    
random.shuffle(trials_list)
elbow_opposite = trials_list[:(args.trial_num-args.major_side_num)] 
print("elbow_opposite:",sorted(elbow_opposite))
random.shuffle(trials_list)
hand_opposite = trials_list[:(args.trial_num-args.major_side_num)]
print("hand_opposite:",sorted(hand_opposite))
# --- Setup global variables (available in all functions) ---
# Ensure that relative paths start from the same directory as this script
_thisDir = os.path.dirname(os.path.abspath(__file__))
# Store info about the experiment session
psychopyVersion = '2023.2.3'
expName = 'daily_rountine'  # from the Builder filename that created this script
expInfo = {
    'participant': f"{randint(0, 999999):06.0f}",
    'session': '001',
    'date': data.getDateStr(),  # add a simple timestamp
    'expName': expName,
    'psychopyVersion': psychopyVersion,
}


def showExpInfoDlg(expInfo):
    """
    Show participant info dialog.
    Parameters
    ==========
    expInfo : dict
        Information about this experiment, created by the `setupExpInfo` function.
    
    Returns
    ==========
    dict
        Information about this experiment.
    """
    # temporarily remove keys which the dialog doesn't need to show
    poppedKeys = {
        'date': expInfo.pop('date', data.getDateStr()),
        'expName': expInfo.pop('expName', expName),
        'psychopyVersion': expInfo.pop('psychopyVersion', psychopyVersion),
    }
    # show participant info dialog
    dlg = gui.DlgFromDict(dictionary=expInfo, sortKeys=False, title=expName)
    if dlg.OK == False:
        core.quit()  # user pressed cancel
    # restore hidden keys
    expInfo.update(poppedKeys)
    # return expInfo
    return expInfo


def setupData(expInfo, dataDir=None):
    """
    Make an ExperimentHandler to handle trials and saving.
    
    Parameters
    ==========
    expInfo : dict
        Information about this experiment, created by the `setupExpInfo` function.
    dataDir : Path, str or None
        Folder to save the data to, leave as None to create a folder in the current directory.    
    Returns
    ==========
    psychopy.data.ExperimentHandler
        Handler object for this experiment, contains the data to save and information about 
        where to save it to.
    """
    
    # data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
    if dataDir is None:
        dataDir = _thisDir
    filename = u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'])
    # make sure filename is relative to dataDir
    if os.path.isabs(filename):
        dataDir = os.path.commonprefix([dataDir, filename])
        filename = os.path.relpath(filename, dataDir)
    
    # an ExperimentHandler isn't essential but helps with data saving
    thisExp = data.ExperimentHandler(
        name=expName, version='',
        extraInfo=expInfo, runtimeInfo=None,
        originPath='C:\\Users\\asena\\Desktop\\kraken\\backend\\daily_routine.py',
        savePickle=True, saveWideText=True,
        dataFileName=dataDir + os.sep + filename, sortColumns='time'
    )
    thisExp.setPriority('thisRow.t', priority.CRITICAL)
    thisExp.setPriority('expName', priority.LOW)
    # return experiment handler
    return thisExp


def setupLogging(filename):
    """
    Setup a log file and tell it what level to log at.
    
    Parameters
    ==========
    filename : str or pathlib.Path
        Filename to save log file and data files as, doesn't need an extension.
    
    Returns
    ==========
    psychopy.logging.LogFile
        Text stream to receive inputs from the logging system.
    """
    # this outputs to the screen, not a file
    logging.console.setLevel(logging.EXP)
    # save a log file for detail verbose info
    logFile = logging.LogFile(filename+'.log', level=logging.EXP)
    
    return logFile


def setupWindow(expInfo=None, win=None):
    """
    Setup the Window
    
    Parameters
    ==========
    expInfo : dict
        Information about this experiment, created by the `setupExpInfo` function.
    win : psychopy.visual.Window
        Window to setup - leave as None to create a new window.
    
    Returns
    ==========
    psychopy.visual.Window
        Window in which to run this experiment.
    """
    if win is None:
        # if not given a window to setup, make one
        win = visual.Window(
            size=[1707, 1067], fullscr=True, screen=0,
            winType='pyglet', allowStencil=False,
            monitor='testMonitor', color=[1.0000, 1.0000, 1.0000], colorSpace='rgb',
            backgroundImage='', backgroundFit='none',
            blendMode='avg', useFBO=True,
            units='height'
        )
        if expInfo is not None:
            # store frame rate of monitor if we can measure it
            expInfo['frameRate'] = win.getActualFrameRate()
    else:
        # if we have a window, just set the attributes which are safe to set
        win.color = [1.0000, 1.0000, 1.0000]
        win.colorSpace = 'rgb'
        win.backgroundImage = ''
        win.backgroundFit = 'none'
        win.units = 'height'
    win.mouseVisible = False
    win.hideMessage()
    return win


def setupInputs(expInfo, thisExp, win):
    """
    Setup whatever inputs are available (mouse, keyboard, eyetracker, etc.)
    
    Parameters
    ==========
    expInfo : dict
        Information about this experiment, created by the `setupExpInfo` function.
    thisExp : psychopy.data.ExperimentHandler
        Handler object for this experiment, contains the data to save and information about 
        where to save it to.
    win : psychopy.visual.Window
        Window in which to run this experiment.
    Returns
    ==========
    dict
        Dictionary of input devices by name.
    """
    # --- Setup input devices ---
    inputs = {}
    ioConfig = {}
    
    # Setup iohub keyboard
    ioConfig['Keyboard'] = dict(use_keymap='psychopy')
    
    ioSession = '1'
    if 'session' in expInfo:
        ioSession = str(expInfo['session'])
    ioServer = io.launchHubServer(window=win, **ioConfig)
    eyetracker = None
    
    # create a default keyboard (e.g. to check for escape)
    defaultKeyboard = keyboard.Keyboard(backend='iohub')
    # return inputs dict
    return {
        'ioServer': ioServer,
        'defaultKeyboard': defaultKeyboard,
        'eyetracker': eyetracker,
    }

def pauseExperiment(thisExp, inputs=None, win=None, timers=[], playbackComponents=[]):
    """
    Pause this experiment, preventing the flow from advancing to the next routine until resumed.
    
    Parameters
    ==========
    thisExp : psychopy.data.ExperimentHandler
        Handler object for this experiment, contains the data to save and information about 
        where to save it to.
    inputs : dict
        Dictionary of input devices by name.
    win : psychopy.visual.Window
        Window for this experiment.
    timers : list, tuple
        List of timers to reset once pausing is finished.
    playbackComponents : list, tuple
        List of any components with a `pause` method which need to be paused.
    """
    # if we are not paused, do nothing
    if thisExp.status != PAUSED:
        return
    
    # pause any playback components
    for comp in playbackComponents:
        comp.pause()
    # prevent components from auto-drawing
    win.stashAutoDraw()
    # run a while loop while we wait to unpause
    while thisExp.status == PAUSED:
        # make sure we have a keyboard
        if inputs is None:
            inputs = {
                'defaultKeyboard': keyboard.Keyboard(backend='ioHub')
            }
        # check for quit (typically the Esc key)
        if inputs['defaultKeyboard'].getKeys(keyList=['escape']):
            endExperiment(thisExp, win=win, inputs=inputs)
        # flip the screen
        win.flip()
    # if stop was requested while paused, quit
    if thisExp.status == FINISHED:
        endExperiment(thisExp, inputs=inputs, win=win)
    # resume any playback components
    for comp in playbackComponents:
        comp.play()
    # restore auto-drawn components
    win.retrieveAutoDraw()
    # reset any timers
    for timer in timers:
        timer.reset()


def run(expInfo, thisExp, win, inputs, globalClock=None, thisSession=None):
    """
    Run the experiment flow.
    
    Parameters
    ==========
    expInfo : dict
        Information about this experiment, created by the `setupExpInfo` function.
    thisExp : psychopy.data.ExperimentHandler
        Handler object for this experiment, contains the data to save and information about 
        where to save it to.
    psychopy.visual.Window
        Window in which to run this experiment.
    inputs : dict
        Dictionary of input devices by name.
    globalClock : psychopy.core.clock.Clock or None
        Clock to get global time from - supply None to make a new one.
    thisSession : psychopy.session.Session or None
        Handle of the Session object this experiment is being run from, if any.
    """
    # mark experiment as started
    thisExp.status = STARTED
    # make sure variables created by exec are available globally
    exec = environmenttools.setExecEnvironment(globals())
    # get device handles from dict of input devices
    ioServer = inputs['ioServer']
    defaultKeyboard = inputs['defaultKeyboard']
    eyetracker = inputs['eyetracker']
    # make sure we're running in the directory for this experiment
    os.chdir(_thisDir)
    # get filename from ExperimentHandler for convenience
    filename = thisExp.dataFileName
    frameTolerance = 0.001  # how close to onset before 'same' frame
    endExpNow = False  # flag for 'escape' or other condition => quit the exp
    # get frame duration from frame rate in expInfo
    if 'frameRate' in expInfo and expInfo['frameRate'] is not None:
        frameDur = 1.0 / round(expInfo['frameRate'])
    else:
        frameDur = 1.0 / 60.0  # could not measure, so guess
    
    # Start Code - component code to be run after the window creation
    
    # --- Initialize components for Routine "prepare_0" ---
    text_4 = visual.TextStim(win=win, name='text_4',
        text='第一个任务即将开始\n请您放松身体，保持安静\n\n任务时长：2分钟\n\n如果准备好了，请按空格键',
        font='Open Sans',
        pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0, 
        color=[-1.0000, -1.0000, -1.0000], colorSpace='rgb', opacity=None, 
        languageStyle='LTR',
        depth=0.0);
    key_resp_4 = keyboard.Keyboard()
    sound_1 = sound.Sound('static/audios/准备1_静息.wav', secs=-1, stereo=True, hamming=True,
        name='sound_1')
    sound_1.setVolume(1.0)
    
    # --- Initialize components for Routine "resting" ---
    image_3 = visual.ImageStim(
        win=win,
        name='image_3', units='pix', 
        image='static/images/daily_resting.png', mask=None, anchor='center',
        ori=0.0, pos=(0, 0), size=(662, 500),
        color=[1,1,1], colorSpace='rgb', opacity=None,
        flipHoriz=False, flipVert=False,
        texRes=128.0, interpolate=True, depth=0.0)
    sound_7 = sound.Sound('static/audios/任务1_静息.wav', secs=-1, stereo=True, hamming=True,
        name='sound_7')
    sound_7.setVolume(1.0)
    sound_16 = sound.Sound('static/audios/ding.wav', secs=1.0, stereo=True, hamming=True,
        name='sound_16')
    sound_16.setVolume(1.0)
    
    # --- Initialize components for Routine "prepare_1" ---
    elbow_prepare = visual.TextStim(win=win, name='elbow_prepare',
        text=None,
        font='Open Sans',
        pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0, 
        color=[-1.0000, -1.0000, -1.0000], colorSpace='rgb', opacity=None, 
        languageStyle='LTR',
        depth=0.0);
    key_resp = keyboard.Keyboard()
    sound_2 = sound.Sound('static/audios/准备2_肘部.wav', secs=-1, stereo=True, hamming=True,
        name='sound_2')
    sound_2.setVolume(1.0)
    
    # --- Initialize components for Routine "task_1" ---
    elbow_img = visual.ImageStim(
        win=win,
        name='elbow_img', 
        image=None, mask=None, anchor='center',
        ori=0.0, pos=(0, 0), size=(0.56,0.5),
        color=[1.0000, 1.0000, 1.0000], colorSpace='rgb', opacity=None,
        flipHoriz=False, flipVert=False,
        texRes=128.0, interpolate=True, depth=0.0)
    sound_6 = sound.Sound('static/audios/任务2_肘部.wav', secs=-1, stereo=True, hamming=True,
        name='sound_6')
    sound_6.setVolume(1.0)
    
    # --- Initialize components for Routine "rest_1" ---
    image_2 = visual.ImageStim(
        win=win,
        name='image_2', 
        image='static/images/rest.png', mask=None, anchor='center',
        ori=0.0, pos=(0, 0), size=(0.56,0.5),
        color=[1.0000, 1.0000, 1.0000], colorSpace='rgb', opacity=None,
        flipHoriz=False, flipVert=False,
        texRes=128.0, interpolate=True, depth=0.0)
    sound_8 = sound.Sound('static/audios/ding.wav', secs=1.5, stereo=True, hamming=True,
        name='sound_8')
    sound_8.setVolume(1.0)
    sound_9 = sound.Sound('static/audios/放松.wav', secs=-1, stereo=True, hamming=True,
        name='sound_9')
    sound_9.setVolume(1.0)
    
    # --- Initialize components for Routine "prepare_2" ---
    passive_prepare = visual.TextStim(win=win, name='passive_prepare',
        text=None,
        font='Open Sans',
        pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0, 
        color=[-1.0000, -1.0000, -1.0000], colorSpace='rgb', opacity=None, 
        languageStyle='LTR',
        depth=0.0);
    key_resp_2 = keyboard.Keyboard()
    sound_3 = sound.Sound('static/audios/准备3_被动.wav', secs=-1, stereo=True, hamming=True,
        name='sound_3')
    sound_3.setVolume(1.0)
    
    # --- Initialize components for Routine "task_2" ---
    passive_img = visual.ImageStim(
        win=win,
        name='passive_img', 
        image=None, mask=None, anchor='center',
        ori=0.0, pos=(0, 0), size=(0.56,0.5),
        color=[1,1,1], colorSpace='rgb', opacity=None,
        flipHoriz=False, flipVert=False,
        texRes=128.0, interpolate=True, depth=0.0)
    sound_14 = sound.Sound('static/audios/任务3_被动.wav', secs=-1, stereo=True, hamming=True,
        name='sound_14')
    sound_14.setVolume(1.0)
    
    # --- Initialize components for Routine "rest_2" ---
    image_6 = visual.ImageStim(
        win=win,
        name='image_6', 
        image='static/images/rest.png', mask=None, anchor='center',
        ori=0.0, pos=(0, 0), size=(0.56,0.5),
        color=[1,1,1], colorSpace='rgb', opacity=None,
        flipHoriz=False, flipVert=False,
        texRes=128.0, interpolate=True, depth=0.0)
    sound_10 = sound.Sound('static/audios/ding.wav', secs=1.5, stereo=True, hamming=True,
        name='sound_10')
    sound_10.setVolume(1.0)
    sound_11 = sound.Sound('static/audios/放松.wav', secs=-1, stereo=True, hamming=True,
        name='sound_11')
    sound_11.setVolume(1.0)
    
    # --- Initialize components for Routine "prepare_3" ---
    active_prepare = visual.TextStim(win=win, name='active_prepare',
        text=None,
        font='Open Sans',
        pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0, 
        color=[-1.0000, -1.0000, -1.0000], colorSpace='rgb', opacity=None, 
        languageStyle='LTR',
        depth=0.0);
    key_resp_3 = keyboard.Keyboard()
    sound_4 = sound.Sound('static/audios/准备4_主动.wav', secs=-1, stereo=True, hamming=True,
        name='sound_4')
    sound_4.setVolume(1.0)
    
    # --- Initialize components for Routine "task_3" ---
    active_img = visual.ImageStim(
        win=win,
        name='active_img', 
        image=None, mask=None, anchor='center',
        ori=0.0, pos=(0, 0), size=(0.56,0.5),
        color=[1,1,1], colorSpace='rgb', opacity=None,
        flipHoriz=False, flipVert=False,
        texRes=128.0, interpolate=True, depth=0.0)
    sound_15 = sound.Sound('static/audios/任务4_主动.wav', secs=-1, stereo=True, hamming=True,
        name='sound_15')
    sound_15.setVolume(1.0)
    
    # --- Initialize components for Routine "rest_3" ---
    image_7 = visual.ImageStim(
        win=win,
        name='image_7', 
        image='static/images/rest.png', mask=None, anchor='center',
        ori=0.0, pos=(0, 0), size=(0.56,0.5),
        color=[1,1,1], colorSpace='rgb', opacity=None,
        flipHoriz=False, flipVert=False,
        texRes=128.0, interpolate=True, depth=0.0)
    sound_12 = sound.Sound('static/audios/ding.wav', secs=1.5, stereo=True, hamming=True,
        name='sound_12')
    sound_12.setVolume(1.0)
    sound_13 = sound.Sound('static/audios/放松.wav', secs=-1, stereo=True, hamming=True,
        name='sound_13')
    sound_13.setVolume(1.0)
    
    # --- Initialize components for Routine "done" ---
    end = visual.TextStim(win=win, name='end',
        text='恭喜您完成了所有任务！\n非常感谢您的配合！',
        font='Open Sans',
        pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0, 
        color=[-1.0000, -1.0000, -1.0000], colorSpace='rgb', opacity=None, 
        languageStyle='LTR',
        depth=0.0);
    sound_5 = sound.Sound('static/audios/结束.wav', secs=-1, stereo=True, hamming=True,
        name='sound_5')
    sound_5.setVolume(1.0)
    
    # create some handy timers
    if globalClock is None:
        globalClock = core.Clock()  # to track the time since experiment started
    if ioServer is not None:
        ioServer.syncClock(globalClock)
    logging.setDefaultClock(globalClock)
    routineTimer = core.Clock()  # to track time remaining of each (possibly non-slip) routine
    win.flip()  # flip window to reset last flip timer
    # store the exact time the global clock started
    expInfo['expStart'] = data.getDateStr(format='%Y-%m-%d %Hh%M.%S.%f %z', fractionalSecondDigits=6)
    
    # --- Prepare to start Routine "prepare_0" ---
    continueRoutine = True
    # update component parameters for each repeat
    thisExp.addData('prepare_0.started', globalClock.getTime())
    key_resp_4.keys = []
    key_resp_4.rt = []
    _key_resp_4_allKeys = []
    sound_1.setSound('static/audios/准备1_静息.wav', hamming=True)
    sound_1.setVolume(1.0, log=False)
    sound_1.seek(0)
    # keep track of which components have finished
    prepare_0Components = [text_4, key_resp_4, sound_1]
    for thisComponent in prepare_0Components:
        thisComponent.tStart = None
        thisComponent.tStop = None
        thisComponent.tStartRefresh = None
        thisComponent.tStopRefresh = None
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    # reset timers
    t = 0
    _timeToFirstFrame = win.getFutureFlipTime(clock="now")
    frameN = -1
    
    # --- Run Routine "prepare_0" ---
    routineForceEnded = not continueRoutine
    while continueRoutine:
        # get current time
        t = routineTimer.getTime()
        tThisFlip = win.getFutureFlipTime(clock=routineTimer)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *text_4* updates
        
        # if text_4 is starting this frame...
        if text_4.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
            # keep track of start time/frame for later
            text_4.frameNStart = frameN  # exact frame index
            text_4.tStart = t  # local t and not account for scr refresh
            text_4.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(text_4, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'text_4.started')
            # update status
            text_4.status = STARTED
            text_4.setAutoDraw(True)
        
        # if text_4 is active this frame...
        if text_4.status == STARTED:
            # update params
            pass
        
        # *key_resp_4* updates
        waitOnFlip = False
        
        # if key_resp_4 is starting this frame...
        if key_resp_4.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
            # keep track of start time/frame for later
            key_resp_4.frameNStart = frameN  # exact frame index
            key_resp_4.tStart = t  # local t and not account for scr refresh
            key_resp_4.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(key_resp_4, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'key_resp_4.started')
            # update status
            key_resp_4.status = STARTED
            # keyboard checking is just starting
            waitOnFlip = True
            win.callOnFlip(key_resp_4.clock.reset)  # t=0 on next screen flip
            win.callOnFlip(key_resp_4.clearEvents, eventType='keyboard')  # clear events on next screen flip
        if key_resp_4.status == STARTED and not waitOnFlip:
            theseKeys = key_resp_4.getKeys(keyList=['space'], ignoreKeys=["escape"], waitRelease=False)
            _key_resp_4_allKeys.extend(theseKeys)
            if len(_key_resp_4_allKeys):
                key_resp_4.keys = _key_resp_4_allKeys[-1].name  # just the last key pressed
                key_resp_4.rt = _key_resp_4_allKeys[-1].rt
                key_resp_4.duration = _key_resp_4_allKeys[-1].duration
                # a response ends the routine
                continueRoutine = False
        
        # if sound_1 is starting this frame...
        if sound_1.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            sound_1.frameNStart = frameN  # exact frame index
            sound_1.tStart = t  # local t and not account for scr refresh
            sound_1.tStartRefresh = tThisFlipGlobal  # on global time
            # add timestamp to datafile
            thisExp.addData('sound_1.started', tThisFlipGlobal)
            # update status
            sound_1.status = STARTED
            sound_1.play(when=win)  # sync with win flip
        # update sound_1 status according to whether it's playing
        if sound_1.isPlaying:
            sound_1.status = STARTED
        elif sound_1.isFinished:
            sound_1.status = FINISHED
        
        # check for quit (typically the Esc key)
        if defaultKeyboard.getKeys(keyList=["escape"]):
            thisExp.status = FINISHED
        if thisExp.status == FINISHED or endExpNow:
            endExperiment(thisExp, inputs=inputs, win=win)
            return
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            routineForceEnded = True
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in prepare_0Components:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # --- Ending Routine "prepare_0" ---
    for thisComponent in prepare_0Components:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    thisExp.addData('prepare_0.stopped', globalClock.getTime())
    # check responses
    if key_resp_4.keys in ['', [], None]:  # No response was made
        key_resp_4.keys = None
    thisExp.addData('key_resp_4.keys',key_resp_4.keys)
    if key_resp_4.keys != None:  # we had a response
        thisExp.addData('key_resp_4.rt', key_resp_4.rt)
        thisExp.addData('key_resp_4.duration', key_resp_4.duration)
    thisExp.nextEntry()
    sound_1.pause()  # ensure sound has stopped at end of Routine
    # the Routine "prepare_0" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    
    # --- Prepare to start Routine "resting" ---
    continueRoutine = True
    # update component parameters for each repeat
    thisExp.addData('resting.started', globalClock.getTime())
    # Run 'Begin Routine' code from code_1
    i=0
    sound_7.setSound('static/audios/任务1_静息.wav', secs=5, hamming=True)
    sound_7.setVolume(1.0, log=False)
    sound_7.seek(0)
    sound_16.setSound('static/audios/ding.wav', secs=1.0, hamming=True)
    sound_16.setVolume(1.0, log=False)
    sound_16.seek(0)
    # keep track of which components have finished
    restingComponents = [image_3, sound_7, sound_16]
    for thisComponent in restingComponents:
        thisComponent.tStart = None
        thisComponent.tStop = None
        thisComponent.tStartRefresh = None
        thisComponent.tStopRefresh = None
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    # reset timers
    t = 0
    _timeToFirstFrame = win.getFutureFlipTime(clock="now")
    frameN = -1
    
    # --- Run Routine "resting" ---
    routineForceEnded = not continueRoutine
    while continueRoutine and routineTimer.getTime() < 121.0:
        # get current time
        t = routineTimer.getTime()
        tThisFlip = win.getFutureFlipTime(clock=routineTimer)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *image_3* updates
        
        # if image_3 is starting this frame...
        if image_3.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
            # keep track of start time/frame for later
            image_3.frameNStart = frameN  # exact frame index
            image_3.tStart = t  # local t and not account for scr refresh
            image_3.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(image_3, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'image_3.started')
            # update status
            image_3.status = STARTED
            image_3.setAutoDraw(True)
        
        # if image_3 is active this frame...
        if image_3.status == STARTED:
            # update params
            pass
        
        # if image_3 is stopping this frame...
        if image_3.status == STARTED:
            # is it time to stop? (based on global clock, using actual start)
            if tThisFlipGlobal > image_3.tStartRefresh + 120-frameTolerance:
                # keep track of stop time/frame for later
                image_3.tStop = t  # not accounting for scr refresh
                image_3.frameNStop = frameN  # exact frame index
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'image_3.stopped')
                # update status
                image_3.status = FINISHED
                image_3.setAutoDraw(False)
        # Run 'Each Frame' code from code_1
        if i== 59:
            win.callOnFlip(trigger.send_trigger,0x01)
            i+=1
        else:
            i+=1
        
        # if sound_7 is starting this frame...
        if sound_7.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
            # keep track of start time/frame for later
            sound_7.frameNStart = frameN  # exact frame index
            sound_7.tStart = t  # local t and not account for scr refresh
            sound_7.tStartRefresh = tThisFlipGlobal  # on global time
            # add timestamp to datafile
            thisExp.addData('sound_7.started', tThisFlipGlobal)
            # update status
            sound_7.status = STARTED
            sound_7.play(when=win)  # sync with win flip
        
        # if sound_7 is stopping this frame...
        if sound_7.status == STARTED:
            # is it time to stop? (based on global clock, using actual start)
            if tThisFlipGlobal > sound_7.tStartRefresh + 5-frameTolerance:
                # keep track of stop time/frame for later
                sound_7.tStop = t  # not accounting for scr refresh
                sound_7.frameNStop = frameN  # exact frame index
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'sound_7.stopped')
                # update status
                sound_7.status = FINISHED
                sound_7.stop()
        # update sound_7 status according to whether it's playing
        if sound_7.isPlaying:
            sound_7.status = STARTED
        elif sound_7.isFinished:
            sound_7.status = FINISHED
        
        # if sound_16 is starting this frame...
        if sound_16.status == NOT_STARTED and tThisFlip >= 120-frameTolerance:
            # keep track of start time/frame for later
            sound_16.frameNStart = frameN  # exact frame index
            sound_16.tStart = t  # local t and not account for scr refresh
            sound_16.tStartRefresh = tThisFlipGlobal  # on global time
            # add timestamp to datafile
            thisExp.addData('sound_16.started', tThisFlipGlobal)
            # update status
            sound_16.status = STARTED
            sound_16.play(when=win)  # sync with win flip
        
        # if sound_16 is stopping this frame...
        if sound_16.status == STARTED:
            # is it time to stop? (based on global clock, using actual start)
            if tThisFlipGlobal > sound_16.tStartRefresh + 1.0-frameTolerance:
                # keep track of stop time/frame for later
                sound_16.tStop = t  # not accounting for scr refresh
                sound_16.frameNStop = frameN  # exact frame index
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'sound_16.stopped')
                # update status
                sound_16.status = FINISHED
                sound_16.stop()
        # update sound_16 status according to whether it's playing
        if sound_16.isPlaying:
            sound_16.status = STARTED
        elif sound_16.isFinished:
            sound_16.status = FINISHED
        
        # check for quit (typically the Esc key)
        if defaultKeyboard.getKeys(keyList=["escape"]):
            thisExp.status = FINISHED
        if thisExp.status == FINISHED or endExpNow:
            endExperiment(thisExp, inputs=inputs, win=win)
            return
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            routineForceEnded = True
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in restingComponents:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # --- Ending Routine "resting" ---
    for thisComponent in restingComponents:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    thisExp.addData('resting.stopped', globalClock.getTime())
    sound_7.pause()  # ensure sound has stopped at end of Routine
    sound_16.pause()  # ensure sound has stopped at end of Routine
    # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
    if routineForceEnded:
        routineTimer.reset()
    else:
        routineTimer.addTime(-121.000000)
    
    # --- Prepare to start Routine "prepare_1" ---
    continueRoutine = True
    # update component parameters for each repeat
    thisExp.addData('prepare_1.started', globalClock.getTime())
    key_resp.keys = []
    key_resp.rt = []
    _key_resp_allKeys = []
    sound_2.setSound('static/audios/准备2_肘部.wav', hamming=True)
    sound_2.setVolume(1.0, log=False)
    sound_2.seek(0)
    # Run 'Begin Routine' code from code
    prepare_text1 = "下一个部分是：肘部运动\n\n这个任务需要您根据屏幕提示\n尝试弯曲肘部，然后放下\n您需要完成这个动作"+str(args.trial_num)+"次\n\n如果准备好了，请按空格键"
    elbow_prepare.text = prepare_text1 
    # keep track of which components have finished
    prepare_1Components = [elbow_prepare, key_resp, sound_2]
    for thisComponent in prepare_1Components:
        thisComponent.tStart = None
        thisComponent.tStop = None
        thisComponent.tStartRefresh = None
        thisComponent.tStopRefresh = None
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    # reset timers
    t = 0
    _timeToFirstFrame = win.getFutureFlipTime(clock="now")
    frameN = -1
    
    # --- Run Routine "prepare_1" ---
    routineForceEnded = not continueRoutine
    while continueRoutine:
        # get current time
        t = routineTimer.getTime()
        tThisFlip = win.getFutureFlipTime(clock=routineTimer)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *elbow_prepare* updates
        
        # if elbow_prepare is starting this frame...
        if elbow_prepare.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            elbow_prepare.frameNStart = frameN  # exact frame index
            elbow_prepare.tStart = t  # local t and not account for scr refresh
            elbow_prepare.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(elbow_prepare, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'elbow_prepare.started')
            # update status
            elbow_prepare.status = STARTED
            elbow_prepare.setAutoDraw(True)
        
        # if elbow_prepare is active this frame...
        if elbow_prepare.status == STARTED:
            # update params
            pass
        
        # *key_resp* updates
        waitOnFlip = False
        
        # if key_resp is starting this frame...
        if key_resp.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            key_resp.frameNStart = frameN  # exact frame index
            key_resp.tStart = t  # local t and not account for scr refresh
            key_resp.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(key_resp, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'key_resp.started')
            # update status
            key_resp.status = STARTED
            # keyboard checking is just starting
            waitOnFlip = True
            win.callOnFlip(key_resp.clock.reset)  # t=0 on next screen flip
            win.callOnFlip(key_resp.clearEvents, eventType='keyboard')  # clear events on next screen flip
        if key_resp.status == STARTED and not waitOnFlip:
            theseKeys = key_resp.getKeys(keyList=['space'], ignoreKeys=["escape"], waitRelease=False)
            _key_resp_allKeys.extend(theseKeys)
            if len(_key_resp_allKeys):
                key_resp.keys = _key_resp_allKeys[-1].name  # just the last key pressed
                key_resp.rt = _key_resp_allKeys[-1].rt
                key_resp.duration = _key_resp_allKeys[-1].duration
                # a response ends the routine
                continueRoutine = False
        
        # if sound_2 is starting this frame...
        if sound_2.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
            # keep track of start time/frame for later
            sound_2.frameNStart = frameN  # exact frame index
            sound_2.tStart = t  # local t and not account for scr refresh
            sound_2.tStartRefresh = tThisFlipGlobal  # on global time
            # add timestamp to datafile
            thisExp.addData('sound_2.started', tThisFlipGlobal)
            # update status
            sound_2.status = STARTED
            sound_2.play(when=win)  # sync with win flip
        # update sound_2 status according to whether it's playing
        if sound_2.isPlaying:
            sound_2.status = STARTED
        elif sound_2.isFinished:
            sound_2.status = FINISHED
        
        # check for quit (typically the Esc key)
        if defaultKeyboard.getKeys(keyList=["escape"]):
            thisExp.status = FINISHED
        if thisExp.status == FINISHED or endExpNow:
            endExperiment(thisExp, inputs=inputs, win=win)
            return
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            routineForceEnded = True
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in prepare_1Components:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # --- Ending Routine "prepare_1" ---
    for thisComponent in prepare_1Components:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    thisExp.addData('prepare_1.stopped', globalClock.getTime())
    # check responses
    if key_resp.keys in ['', [], None]:  # No response was made
        key_resp.keys = None
    thisExp.addData('key_resp.keys',key_resp.keys)
    if key_resp.keys != None:  # we had a response
        thisExp.addData('key_resp.rt', key_resp.rt)
        thisExp.addData('key_resp.duration', key_resp.duration)
    thisExp.nextEntry()
    sound_2.pause()  # ensure sound has stopped at end of Routine
    # the Routine "prepare_1" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    
    # set up handler to look after randomisation of conditions etc
    trials = data.TrialHandler(nReps=args.trial_num, method='sequential', 
        extraInfo=expInfo, originPath=-1,
        trialList=[None],
        seed=None, name='trials')
    thisExp.addLoop(trials)  # add the loop to the experiment
    thisTrial = trials.trialList[0]  # so we can initialise stimuli with some values
    # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
    if thisTrial != None:
        for paramName in thisTrial:
            globals()[paramName] = thisTrial[paramName]
    
    for thisTrial in trials:
        currentLoop = trials
        thisExp.timestampOnFlip(win, 'thisRow.t')
        # pause experiment here if requested
        if thisExp.status == PAUSED:
            pauseExperiment(
                thisExp=thisExp, 
                inputs=inputs, 
                win=win, 
                timers=[routineTimer], 
                playbackComponents=[]
        )
        # abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
        if thisTrial != None:
            for paramName in thisTrial:
                globals()[paramName] = thisTrial[paramName]
        
        # --- Prepare to start Routine "task_1" ---
        continueRoutine = True
        # update component parameters for each repeat
        thisExp.addData('task_1.started', globalClock.getTime())
        # Run 'Begin Routine' code from code_2
        i=0
        cnt1 = trials.thisN+1
        if args.side == "right":
            if cnt1 in elbow_opposite:
                elbow_img.image = "static/images/daily_elbow_left.png"
                trigger_elbow = 0x08
                trigger_rest = 0x09
            else:
                elbow_img.image = "static/images/daily_elbow_right.png"
                trigger_elbow = 0x02
                trigger_rest = 0x03
        else:
            if cnt1 in elbow_opposite:
                elbow_img.image = "static/images/daily_elbow_right.png"
                trigger_elbow = 0x02
                trigger_rest = 0x03
            else:
                elbow_img.image = "static/images/daily_elbow_left.png"
                trigger_elbow = 0x08
                trigger_rest = 0x09
        
        sound_6.setSound('static/audios/任务2_肘部.wav', hamming=True)
        sound_6.setVolume(1.0, log=False)
        sound_6.seek(0)
        # keep track of which components have finished
        task_1Components = [elbow_img, sound_6]
        for thisComponent in task_1Components:
            thisComponent.tStart = None
            thisComponent.tStop = None
            thisComponent.tStartRefresh = None
            thisComponent.tStopRefresh = None
            if hasattr(thisComponent, 'status'):
                thisComponent.status = NOT_STARTED
        # reset timers
        t = 0
        _timeToFirstFrame = win.getFutureFlipTime(clock="now")
        frameN = -1
        
        # --- Run Routine "task_1" ---
        routineForceEnded = not continueRoutine
        while continueRoutine:
            # get current time
            t = routineTimer.getTime()
            tThisFlip = win.getFutureFlipTime(clock=routineTimer)
            tThisFlipGlobal = win.getFutureFlipTime(clock=None)
            frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
            # update/draw components on each frame
            
            # *elbow_img* updates
            
            # if elbow_img is starting this frame...
            if elbow_img.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
                # keep track of start time/frame for later
                elbow_img.frameNStart = frameN  # exact frame index
                elbow_img.tStart = t  # local t and not account for scr refresh
                elbow_img.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(elbow_img, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'elbow_img.started')
                # update status
                elbow_img.status = STARTED
                elbow_img.setAutoDraw(True)
            
            # if elbow_img is active this frame...
            if elbow_img.status == STARTED:
                # update params
                pass
            
            # if elbow_img is stopping this frame...
            if elbow_img.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > elbow_img.tStartRefresh + 5-frameTolerance:
                    # keep track of stop time/frame for later
                    elbow_img.tStop = t  # not accounting for scr refresh
                    elbow_img.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'elbow_img.stopped')
                    # update status
                    elbow_img.status = FINISHED
                    elbow_img.setAutoDraw(False)
            # Run 'Each Frame' code from code_2
            if i== 59:
                win.callOnFlip(trigger.send_trigger,trigger_elbow)
                i+=1
            else:
                i+=1
            
            # if sound_6 is starting this frame...
            if sound_6.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
                # keep track of start time/frame for later
                sound_6.frameNStart = frameN  # exact frame index
                sound_6.tStart = t  # local t and not account for scr refresh
                sound_6.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_6.started', tThisFlipGlobal)
                # update status
                sound_6.status = STARTED
                sound_6.play(when=win)  # sync with win flip
            # update sound_6 status according to whether it's playing
            if sound_6.isPlaying:
                sound_6.status = STARTED
            elif sound_6.isFinished:
                sound_6.status = FINISHED
            
            # check for quit (typically the Esc key)
            if defaultKeyboard.getKeys(keyList=["escape"]):
                thisExp.status = FINISHED
            if thisExp.status == FINISHED or endExpNow:
                endExperiment(thisExp, inputs=inputs, win=win)
                return
            
            # check if all components have finished
            if not continueRoutine:  # a component has requested a forced-end of Routine
                routineForceEnded = True
                break
            continueRoutine = False  # will revert to True if at least one component still running
            for thisComponent in task_1Components:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break  # at least one component has not yet finished
            
            # refresh the screen
            if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                win.flip()
        
        # --- Ending Routine "task_1" ---
        for thisComponent in task_1Components:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        thisExp.addData('task_1.stopped', globalClock.getTime())
        sound_6.pause()  # ensure sound has stopped at end of Routine
        # the Routine "task_1" was not non-slip safe, so reset the non-slip timer
        routineTimer.reset()
        
        # --- Prepare to start Routine "rest_1" ---
        continueRoutine = True
        # update component parameters for each repeat
        thisExp.addData('rest_1.started', globalClock.getTime())
        # Run 'Begin Routine' code from code_3
        win.callOnFlip(trigger.send_trigger,trigger_rest)
        sound_8.setSound('static/audios/ding.wav', secs=1.5, hamming=True)
        sound_8.setVolume(1.0, log=False)
        sound_8.seek(0)
        sound_9.setSound('static/audios/放松.wav', secs=3, hamming=True)
        sound_9.setVolume(1.0, log=False)
        sound_9.seek(0)
        # keep track of which components have finished
        rest_1Components = [image_2, sound_8, sound_9]
        for thisComponent in rest_1Components:
            thisComponent.tStart = None
            thisComponent.tStop = None
            thisComponent.tStartRefresh = None
            thisComponent.tStopRefresh = None
            if hasattr(thisComponent, 'status'):
                thisComponent.status = NOT_STARTED
        # reset timers
        t = 0
        _timeToFirstFrame = win.getFutureFlipTime(clock="now")
        frameN = -1
        
        # --- Run Routine "rest_1" ---
        routineForceEnded = not continueRoutine
        while continueRoutine and routineTimer.getTime() < 5.0:
            # get current time
            t = routineTimer.getTime()
            tThisFlip = win.getFutureFlipTime(clock=routineTimer)
            tThisFlipGlobal = win.getFutureFlipTime(clock=None)
            frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
            # update/draw components on each frame
            
            # *image_2* updates
            
            # if image_2 is starting this frame...
            if image_2.status == NOT_STARTED and tThisFlip >= 0-frameTolerance:
                # keep track of start time/frame for later
                image_2.frameNStart = frameN  # exact frame index
                image_2.tStart = t  # local t and not account for scr refresh
                image_2.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(image_2, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'image_2.started')
                # update status
                image_2.status = STARTED
                image_2.setAutoDraw(True)
            
            # if image_2 is active this frame...
            if image_2.status == STARTED:
                # update params
                pass
            
            # if image_2 is stopping this frame...
            if image_2.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > image_2.tStartRefresh + 5-frameTolerance:
                    # keep track of stop time/frame for later
                    image_2.tStop = t  # not accounting for scr refresh
                    image_2.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'image_2.stopped')
                    # update status
                    image_2.status = FINISHED
                    image_2.setAutoDraw(False)
            
            # if sound_8 is starting this frame...
            if sound_8.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                # keep track of start time/frame for later
                sound_8.frameNStart = frameN  # exact frame index
                sound_8.tStart = t  # local t and not account for scr refresh
                sound_8.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_8.started', tThisFlipGlobal)
                # update status
                sound_8.status = STARTED
                sound_8.play(when=win)  # sync with win flip
            
            # if sound_8 is stopping this frame...
            if sound_8.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > sound_8.tStartRefresh + 1.5-frameTolerance:
                    # keep track of stop time/frame for later
                    sound_8.tStop = t  # not accounting for scr refresh
                    sound_8.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'sound_8.stopped')
                    # update status
                    sound_8.status = FINISHED
                    sound_8.stop()
            # update sound_8 status according to whether it's playing
            if sound_8.isPlaying:
                sound_8.status = STARTED
            elif sound_8.isFinished:
                sound_8.status = FINISHED
            
            # if sound_9 is starting this frame...
            if sound_9.status == NOT_STARTED and tThisFlip >= 1.2-frameTolerance:
                # keep track of start time/frame for later
                sound_9.frameNStart = frameN  # exact frame index
                sound_9.tStart = t  # local t and not account for scr refresh
                sound_9.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_9.started', tThisFlipGlobal)
                # update status
                sound_9.status = STARTED
                sound_9.play(when=win)  # sync with win flip
            
            # if sound_9 is stopping this frame...
            if sound_9.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > sound_9.tStartRefresh + 3-frameTolerance:
                    # keep track of stop time/frame for later
                    sound_9.tStop = t  # not accounting for scr refresh
                    sound_9.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'sound_9.stopped')
                    # update status
                    sound_9.status = FINISHED
                    sound_9.stop()
            # update sound_9 status according to whether it's playing
            if sound_9.isPlaying:
                sound_9.status = STARTED
            elif sound_9.isFinished:
                sound_9.status = FINISHED
            
            # check for quit (typically the Esc key)
            if defaultKeyboard.getKeys(keyList=["escape"]):
                thisExp.status = FINISHED
            if thisExp.status == FINISHED or endExpNow:
                endExperiment(thisExp, inputs=inputs, win=win)
                return
            
            # check if all components have finished
            if not continueRoutine:  # a component has requested a forced-end of Routine
                routineForceEnded = True
                break
            continueRoutine = False  # will revert to True if at least one component still running
            for thisComponent in rest_1Components:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break  # at least one component has not yet finished
            
            # refresh the screen
            if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                win.flip()
        
        # --- Ending Routine "rest_1" ---
        for thisComponent in rest_1Components:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        thisExp.addData('rest_1.stopped', globalClock.getTime())
        sound_8.pause()  # ensure sound has stopped at end of Routine
        sound_9.pause()  # ensure sound has stopped at end of Routine
        # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
        if routineForceEnded:
            routineTimer.reset()
        else:
            routineTimer.addTime(-5.000000)
        thisExp.nextEntry()
        
        if thisSession is not None:
            # if running in a Session with a Liaison client, send data up to now
            thisSession.sendExperimentData()
    # completed args.trial_num repeats of 'trials'
    
    
    # --- Prepare to start Routine "prepare_2" ---
    continueRoutine = True
    # update component parameters for each repeat
    thisExp.addData('prepare_2.started', globalClock.getTime())
    key_resp_2.keys = []
    key_resp_2.rt = []
    _key_resp_2_allKeys = []
    sound_3.setSound('static/audios/准备3_被动.wav', hamming=True)
    sound_3.setVolume(1.0, log=False)
    sound_3.seek(0)
    # Run 'Begin Routine' code from code_8
    prepare_text2 = "下一个部分是：感受手部运动\n\n请您感受手部握拳然后保持的过程\n您需要完成这个动作"+str(args.trial_num)+"次,每次5秒\n\n如果准备好了，请按空格键"
    passive_prepare.text = prepare_text2 
    # keep track of which components have finished
    prepare_2Components = [passive_prepare, key_resp_2, sound_3]
    for thisComponent in prepare_2Components:
        thisComponent.tStart = None
        thisComponent.tStop = None
        thisComponent.tStartRefresh = None
        thisComponent.tStopRefresh = None
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    # reset timers
    t = 0
    _timeToFirstFrame = win.getFutureFlipTime(clock="now")
    frameN = -1
    
    # --- Run Routine "prepare_2" ---
    routineForceEnded = not continueRoutine
    while continueRoutine:
        # get current time
        t = routineTimer.getTime()
        tThisFlip = win.getFutureFlipTime(clock=routineTimer)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *passive_prepare* updates
        
        # if passive_prepare is starting this frame...
        if passive_prepare.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            passive_prepare.frameNStart = frameN  # exact frame index
            passive_prepare.tStart = t  # local t and not account for scr refresh
            passive_prepare.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(passive_prepare, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'passive_prepare.started')
            # update status
            passive_prepare.status = STARTED
            passive_prepare.setAutoDraw(True)
        
        # if passive_prepare is active this frame...
        if passive_prepare.status == STARTED:
            # update params
            pass
        
        # *key_resp_2* updates
        waitOnFlip = False
        
        # if key_resp_2 is starting this frame...
        if key_resp_2.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            key_resp_2.frameNStart = frameN  # exact frame index
            key_resp_2.tStart = t  # local t and not account for scr refresh
            key_resp_2.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(key_resp_2, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'key_resp_2.started')
            # update status
            key_resp_2.status = STARTED
            # keyboard checking is just starting
            waitOnFlip = True
            win.callOnFlip(key_resp_2.clock.reset)  # t=0 on next screen flip
            win.callOnFlip(key_resp_2.clearEvents, eventType='keyboard')  # clear events on next screen flip
        if key_resp_2.status == STARTED and not waitOnFlip:
            theseKeys = key_resp_2.getKeys(keyList=['space'], ignoreKeys=["escape"], waitRelease=False)
            _key_resp_2_allKeys.extend(theseKeys)
            if len(_key_resp_2_allKeys):
                key_resp_2.keys = _key_resp_2_allKeys[-1].name  # just the last key pressed
                key_resp_2.rt = _key_resp_2_allKeys[-1].rt
                key_resp_2.duration = _key_resp_2_allKeys[-1].duration
                # a response ends the routine
                continueRoutine = False
        
        # if sound_3 is starting this frame...
        if sound_3.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
            # keep track of start time/frame for later
            sound_3.frameNStart = frameN  # exact frame index
            sound_3.tStart = t  # local t and not account for scr refresh
            sound_3.tStartRefresh = tThisFlipGlobal  # on global time
            # add timestamp to datafile
            thisExp.addData('sound_3.started', tThisFlipGlobal)
            # update status
            sound_3.status = STARTED
            sound_3.play(when=win)  # sync with win flip
        # update sound_3 status according to whether it's playing
        if sound_3.isPlaying:
            sound_3.status = STARTED
        elif sound_3.isFinished:
            sound_3.status = FINISHED
        
        # check for quit (typically the Esc key)
        if defaultKeyboard.getKeys(keyList=["escape"]):
            thisExp.status = FINISHED
        if thisExp.status == FINISHED or endExpNow:
            endExperiment(thisExp, inputs=inputs, win=win)
            return
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            routineForceEnded = True
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in prepare_2Components:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # --- Ending Routine "prepare_2" ---
    for thisComponent in prepare_2Components:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    thisExp.addData('prepare_2.stopped', globalClock.getTime())
    # check responses
    if key_resp_2.keys in ['', [], None]:  # No response was made
        key_resp_2.keys = None
    thisExp.addData('key_resp_2.keys',key_resp_2.keys)
    if key_resp_2.keys != None:  # we had a response
        thisExp.addData('key_resp_2.rt', key_resp_2.rt)
        thisExp.addData('key_resp_2.duration', key_resp_2.duration)
    thisExp.nextEntry()
    sound_3.pause()  # ensure sound has stopped at end of Routine
    # the Routine "prepare_2" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    
    # set up handler to look after randomisation of conditions etc
    trials_2 = data.TrialHandler(nReps=args.trial_num, method='random', 
        extraInfo=expInfo, originPath=-1,
        trialList=[None],
        seed=None, name='trials_2')
    thisExp.addLoop(trials_2)  # add the loop to the experiment
    thisTrial_2 = trials_2.trialList[0]  # so we can initialise stimuli with some values
    # abbreviate parameter names if possible (e.g. rgb = thisTrial_2.rgb)
    if thisTrial_2 != None:
        for paramName in thisTrial_2:
            globals()[paramName] = thisTrial_2[paramName]
    
    for thisTrial_2 in trials_2:
        currentLoop = trials_2
        thisExp.timestampOnFlip(win, 'thisRow.t')
        # pause experiment here if requested
        if thisExp.status == PAUSED:
            pauseExperiment(
                thisExp=thisExp, 
                inputs=inputs, 
                win=win, 
                timers=[routineTimer], 
                playbackComponents=[]
        )
        # abbreviate parameter names if possible (e.g. rgb = thisTrial_2.rgb)
        if thisTrial_2 != None:
            for paramName in thisTrial_2:
                globals()[paramName] = thisTrial_2[paramName]
        
        # --- Prepare to start Routine "task_2" ---
        continueRoutine = True
        # update component parameters for each repeat
        thisExp.addData('task_2.started', globalClock.getTime())
        # Run 'Begin Routine' code from code_4
        i=0
        if args.side == "right":
            passive_img.image = "static/images/daily_passive_right.png"
        else:
            passive_img.image = "static/images/daily_passive_left.png"
        sound_14.setSound('static/audios/任务3_被动.wav', hamming=True)
        sound_14.setVolume(1.0, log=False)
        sound_14.seek(0)
        # keep track of which components have finished
        task_2Components = [passive_img, sound_14]
        for thisComponent in task_2Components:
            thisComponent.tStart = None
            thisComponent.tStop = None
            thisComponent.tStartRefresh = None
            thisComponent.tStopRefresh = None
            if hasattr(thisComponent, 'status'):
                thisComponent.status = NOT_STARTED
        # reset timers
        t = 0
        _timeToFirstFrame = win.getFutureFlipTime(clock="now")
        frameN = -1
        
        # --- Run Routine "task_2" ---
        routineForceEnded = not continueRoutine
        while continueRoutine:
            # get current time
            t = routineTimer.getTime()
            tThisFlip = win.getFutureFlipTime(clock=routineTimer)
            tThisFlipGlobal = win.getFutureFlipTime(clock=None)
            frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
            # update/draw components on each frame
            
            # *passive_img* updates
            
            # if passive_img is starting this frame...
            if passive_img.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
                # keep track of start time/frame for later
                passive_img.frameNStart = frameN  # exact frame index
                passive_img.tStart = t  # local t and not account for scr refresh
                passive_img.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(passive_img, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'passive_img.started')
                # update status
                passive_img.status = STARTED
                passive_img.setAutoDraw(True)
            
            # if passive_img is active this frame...
            if passive_img.status == STARTED:
                # update params
                pass
            
            # if passive_img is stopping this frame...
            if passive_img.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > passive_img.tStartRefresh + 5-frameTolerance:
                    # keep track of stop time/frame for later
                    passive_img.tStop = t  # not accounting for scr refresh
                    passive_img.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'passive_img.stopped')
                    # update status
                    passive_img.status = FINISHED
                    passive_img.setAutoDraw(False)
            # Run 'Each Frame' code from code_4
            if i== 59:
                win.callOnFlip(trigger.send_trigger,0x04)
                i+=1
            else:
                i+=1
            
            # if sound_14 is starting this frame...
            if sound_14.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
                # keep track of start time/frame for later
                sound_14.frameNStart = frameN  # exact frame index
                sound_14.tStart = t  # local t and not account for scr refresh
                sound_14.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_14.started', tThisFlipGlobal)
                # update status
                sound_14.status = STARTED
                sound_14.play(when=win)  # sync with win flip
            # update sound_14 status according to whether it's playing
            if sound_14.isPlaying:
                sound_14.status = STARTED
            elif sound_14.isFinished:
                sound_14.status = FINISHED
            
            # check for quit (typically the Esc key)
            if defaultKeyboard.getKeys(keyList=["escape"]):
                thisExp.status = FINISHED
            if thisExp.status == FINISHED or endExpNow:
                endExperiment(thisExp, inputs=inputs, win=win)
                return
            
            # check if all components have finished
            if not continueRoutine:  # a component has requested a forced-end of Routine
                routineForceEnded = True
                break
            continueRoutine = False  # will revert to True if at least one component still running
            for thisComponent in task_2Components:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break  # at least one component has not yet finished
            
            # refresh the screen
            if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                win.flip()
        
        # --- Ending Routine "task_2" ---
        for thisComponent in task_2Components:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        thisExp.addData('task_2.stopped', globalClock.getTime())
        sound_14.pause()  # ensure sound has stopped at end of Routine
        # the Routine "task_2" was not non-slip safe, so reset the non-slip timer
        routineTimer.reset()
        
        # --- Prepare to start Routine "rest_2" ---
        continueRoutine = True
        # update component parameters for each repeat
        thisExp.addData('rest_2.started', globalClock.getTime())
        # Run 'Begin Routine' code from code_5
        win.callOnFlip(trigger.send_trigger,0x05)
        sound_10.setSound('static/audios/ding.wav', secs=1.5, hamming=True)
        sound_10.setVolume(1.0, log=False)
        sound_10.seek(0)
        sound_11.setSound('static/audios/放松.wav', secs=3, hamming=True)
        sound_11.setVolume(1.0, log=False)
        sound_11.seek(0)
        # keep track of which components have finished
        rest_2Components = [image_6, sound_10, sound_11]
        for thisComponent in rest_2Components:
            thisComponent.tStart = None
            thisComponent.tStop = None
            thisComponent.tStartRefresh = None
            thisComponent.tStopRefresh = None
            if hasattr(thisComponent, 'status'):
                thisComponent.status = NOT_STARTED
        # reset timers
        t = 0
        _timeToFirstFrame = win.getFutureFlipTime(clock="now")
        frameN = -1
        
        # --- Run Routine "rest_2" ---
        routineForceEnded = not continueRoutine
        while continueRoutine and routineTimer.getTime() < 5.0:
            # get current time
            t = routineTimer.getTime()
            tThisFlip = win.getFutureFlipTime(clock=routineTimer)
            tThisFlipGlobal = win.getFutureFlipTime(clock=None)
            frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
            # update/draw components on each frame
            
            # *image_6* updates
            
            # if image_6 is starting this frame...
            if image_6.status == NOT_STARTED and tThisFlip >= 0-frameTolerance:
                # keep track of start time/frame for later
                image_6.frameNStart = frameN  # exact frame index
                image_6.tStart = t  # local t and not account for scr refresh
                image_6.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(image_6, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'image_6.started')
                # update status
                image_6.status = STARTED
                image_6.setAutoDraw(True)
            
            # if image_6 is active this frame...
            if image_6.status == STARTED:
                # update params
                pass
            
            # if image_6 is stopping this frame...
            if image_6.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > image_6.tStartRefresh + 5-frameTolerance:
                    # keep track of stop time/frame for later
                    image_6.tStop = t  # not accounting for scr refresh
                    image_6.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'image_6.stopped')
                    # update status
                    image_6.status = FINISHED
                    image_6.setAutoDraw(False)
            # Run 'Each Frame' code from code_5
            
                
            
            
            # if sound_10 is starting this frame...
            if sound_10.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                # keep track of start time/frame for later
                sound_10.frameNStart = frameN  # exact frame index
                sound_10.tStart = t  # local t and not account for scr refresh
                sound_10.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_10.started', tThisFlipGlobal)
                # update status
                sound_10.status = STARTED
                sound_10.play(when=win)  # sync with win flip
            
            # if sound_10 is stopping this frame...
            if sound_10.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > sound_10.tStartRefresh + 1.5-frameTolerance:
                    # keep track of stop time/frame for later
                    sound_10.tStop = t  # not accounting for scr refresh
                    sound_10.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'sound_10.stopped')
                    # update status
                    sound_10.status = FINISHED
                    sound_10.stop()
            # update sound_10 status according to whether it's playing
            if sound_10.isPlaying:
                sound_10.status = STARTED
            elif sound_10.isFinished:
                sound_10.status = FINISHED
            
            # if sound_11 is starting this frame...
            if sound_11.status == NOT_STARTED and tThisFlip >= 1.2-frameTolerance:
                # keep track of start time/frame for later
                sound_11.frameNStart = frameN  # exact frame index
                sound_11.tStart = t  # local t and not account for scr refresh
                sound_11.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_11.started', tThisFlipGlobal)
                # update status
                sound_11.status = STARTED
                sound_11.play(when=win)  # sync with win flip
            
            # if sound_11 is stopping this frame...
            if sound_11.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > sound_11.tStartRefresh + 3-frameTolerance:
                    # keep track of stop time/frame for later
                    sound_11.tStop = t  # not accounting for scr refresh
                    sound_11.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'sound_11.stopped')
                    # update status
                    sound_11.status = FINISHED
                    sound_11.stop()
            # update sound_11 status according to whether it's playing
            if sound_11.isPlaying:
                sound_11.status = STARTED
            elif sound_11.isFinished:
                sound_11.status = FINISHED
            
            # check for quit (typically the Esc key)
            if defaultKeyboard.getKeys(keyList=["escape"]):
                thisExp.status = FINISHED
            if thisExp.status == FINISHED or endExpNow:
                endExperiment(thisExp, inputs=inputs, win=win)
                return
            
            # check if all components have finished
            if not continueRoutine:  # a component has requested a forced-end of Routine
                routineForceEnded = True
                break
            continueRoutine = False  # will revert to True if at least one component still running
            for thisComponent in rest_2Components:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break  # at least one component has not yet finished
            
            # refresh the screen
            if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                win.flip()
        
        # --- Ending Routine "rest_2" ---
        for thisComponent in rest_2Components:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        thisExp.addData('rest_2.stopped', globalClock.getTime())
        sound_10.pause()  # ensure sound has stopped at end of Routine
        sound_11.pause()  # ensure sound has stopped at end of Routine
        # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
        if routineForceEnded:
            routineTimer.reset()
        else:
            routineTimer.addTime(-5.000000)
        thisExp.nextEntry()
        
        if thisSession is not None:
            # if running in a Session with a Liaison client, send data up to now
            thisSession.sendExperimentData()
    # completed args.trial_num repeats of 'trials_2'
    
    
    # --- Prepare to start Routine "prepare_3" ---
    continueRoutine = True
    # update component parameters for each repeat
    thisExp.addData('prepare_3.started', globalClock.getTime())
    key_resp_3.keys = []
    key_resp_3.rt = []
    _key_resp_3_allKeys = []
    sound_4.setSound('static/audios/准备4_主动.wav', hamming=True)
    sound_4.setVolume(1.0, log=False)
    sound_4.seek(0)
    # Run 'Begin Routine' code from code_9
    
    prepare_text3 = "最后一个部分：尝试握拳运动\n\n请您根据屏幕提示\n尝试握拳，然后尽量保持握拳的姿势\n您需要完成这个动作"+str(args.trial_num)+"次,每次5秒\n\n如果准备好了，请按空格键"
    active_prepare.text = prepare_text3
    # keep track of which components have finished
    prepare_3Components = [active_prepare, key_resp_3, sound_4]
    for thisComponent in prepare_3Components:
        thisComponent.tStart = None
        thisComponent.tStop = None
        thisComponent.tStartRefresh = None
        thisComponent.tStopRefresh = None
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    # reset timers
    t = 0
    _timeToFirstFrame = win.getFutureFlipTime(clock="now")
    frameN = -1
    
    # --- Run Routine "prepare_3" ---
    routineForceEnded = not continueRoutine
    while continueRoutine:
        # get current time
        t = routineTimer.getTime()
        tThisFlip = win.getFutureFlipTime(clock=routineTimer)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *active_prepare* updates
        
        # if active_prepare is starting this frame...
        if active_prepare.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            active_prepare.frameNStart = frameN  # exact frame index
            active_prepare.tStart = t  # local t and not account for scr refresh
            active_prepare.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(active_prepare, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'active_prepare.started')
            # update status
            active_prepare.status = STARTED
            active_prepare.setAutoDraw(True)
        
        # if active_prepare is active this frame...
        if active_prepare.status == STARTED:
            # update params
            pass
        
        # *key_resp_3* updates
        waitOnFlip = False
        
        # if key_resp_3 is starting this frame...
        if key_resp_3.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            key_resp_3.frameNStart = frameN  # exact frame index
            key_resp_3.tStart = t  # local t and not account for scr refresh
            key_resp_3.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(key_resp_3, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'key_resp_3.started')
            # update status
            key_resp_3.status = STARTED
            # keyboard checking is just starting
            waitOnFlip = True
            win.callOnFlip(key_resp_3.clock.reset)  # t=0 on next screen flip
            win.callOnFlip(key_resp_3.clearEvents, eventType='keyboard')  # clear events on next screen flip
        if key_resp_3.status == STARTED and not waitOnFlip:
            theseKeys = key_resp_3.getKeys(keyList=['space'], ignoreKeys=["escape"], waitRelease=False)
            _key_resp_3_allKeys.extend(theseKeys)
            if len(_key_resp_3_allKeys):
                key_resp_3.keys = _key_resp_3_allKeys[-1].name  # just the last key pressed
                key_resp_3.rt = _key_resp_3_allKeys[-1].rt
                key_resp_3.duration = _key_resp_3_allKeys[-1].duration
                # a response ends the routine
                continueRoutine = False
        
        # if sound_4 is starting this frame...
        if sound_4.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
            # keep track of start time/frame for later
            sound_4.frameNStart = frameN  # exact frame index
            sound_4.tStart = t  # local t and not account for scr refresh
            sound_4.tStartRefresh = tThisFlipGlobal  # on global time
            # add timestamp to datafile
            thisExp.addData('sound_4.started', tThisFlipGlobal)
            # update status
            sound_4.status = STARTED
            sound_4.play(when=win)  # sync with win flip
        # update sound_4 status according to whether it's playing
        if sound_4.isPlaying:
            sound_4.status = STARTED
        elif sound_4.isFinished:
            sound_4.status = FINISHED
        
        # check for quit (typically the Esc key)
        if defaultKeyboard.getKeys(keyList=["escape"]):
            thisExp.status = FINISHED
        if thisExp.status == FINISHED or endExpNow:
            endExperiment(thisExp, inputs=inputs, win=win)
            return
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            routineForceEnded = True
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in prepare_3Components:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # --- Ending Routine "prepare_3" ---
    for thisComponent in prepare_3Components:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    thisExp.addData('prepare_3.stopped', globalClock.getTime())
    # check responses
    if key_resp_3.keys in ['', [], None]:  # No response was made
        key_resp_3.keys = None
    thisExp.addData('key_resp_3.keys',key_resp_3.keys)
    if key_resp_3.keys != None:  # we had a response
        thisExp.addData('key_resp_3.rt', key_resp_3.rt)
        thisExp.addData('key_resp_3.duration', key_resp_3.duration)
    thisExp.nextEntry()
    sound_4.pause()  # ensure sound has stopped at end of Routine
    # the Routine "prepare_3" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    
    # set up handler to look after randomisation of conditions etc
    trials_3 = data.TrialHandler(nReps=args.trial_num, method='sequential', 
        extraInfo=expInfo, originPath=-1,
        trialList=[None],
        seed=None, name='trials_3')
    thisExp.addLoop(trials_3)  # add the loop to the experiment
    thisTrial_3 = trials_3.trialList[0]  # so we can initialise stimuli with some values
    # abbreviate parameter names if possible (e.g. rgb = thisTrial_3.rgb)
    if thisTrial_3 != None:
        for paramName in thisTrial_3:
            globals()[paramName] = thisTrial_3[paramName]
    
    for thisTrial_3 in trials_3:
        currentLoop = trials_3
        thisExp.timestampOnFlip(win, 'thisRow.t')
        # pause experiment here if requested
        if thisExp.status == PAUSED:
            pauseExperiment(
                thisExp=thisExp, 
                inputs=inputs, 
                win=win, 
                timers=[routineTimer], 
                playbackComponents=[]
        )
        # abbreviate parameter names if possible (e.g. rgb = thisTrial_3.rgb)
        if thisTrial_3 != None:
            for paramName in thisTrial_3:
                globals()[paramName] = thisTrial_3[paramName]
        
        # --- Prepare to start Routine "task_3" ---
        continueRoutine = True
        # update component parameters for each repeat
        thisExp.addData('task_3.started', globalClock.getTime())
        # Run 'Begin Routine' code from code_6
        i=0
        cnt2 = trials_3.thisN+1
        if args.side == "right":
            if cnt2 in hand_opposite:
                active_img.image = "static/images/daily_active_left.png"
                trigger_active = 0x0A
                trigger_rest = 0x0B
            else:
                active_img.image = "static/images/daily_active_right.png"
                trigger_active = 0x06
                trigger_rest = 0x07
                
        else:
            if cnt2 in hand_opposite:
                active_img.image = "static/images/daily_active_right.png"
                trigger_active = 0x06
                trigger_rest = 0x07
            else:
                active_img.image = "static/images/daily_active_left.png"
                trigger_active = 0x0A
                trigger_rest = 0x0B
                
                
        sound_15.setSound('static/audios/任务4_主动.wav', hamming=True)
        sound_15.setVolume(1.0, log=False)
        sound_15.seek(0)
        # keep track of which components have finished
        task_3Components = [active_img, sound_15]
        for thisComponent in task_3Components:
            thisComponent.tStart = None
            thisComponent.tStop = None
            thisComponent.tStartRefresh = None
            thisComponent.tStopRefresh = None
            if hasattr(thisComponent, 'status'):
                thisComponent.status = NOT_STARTED
        # reset timers
        t = 0
        _timeToFirstFrame = win.getFutureFlipTime(clock="now")
        frameN = -1
        
        # --- Run Routine "task_3" ---
        routineForceEnded = not continueRoutine
        while continueRoutine:
            # get current time
            t = routineTimer.getTime()
            tThisFlip = win.getFutureFlipTime(clock=routineTimer)
            tThisFlipGlobal = win.getFutureFlipTime(clock=None)
            frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
            # update/draw components on each frame
            
            # *active_img* updates
            
            # if active_img is starting this frame...
            if active_img.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
                # keep track of start time/frame for later
                active_img.frameNStart = frameN  # exact frame index
                active_img.tStart = t  # local t and not account for scr refresh
                active_img.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(active_img, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'active_img.started')
                # update status
                active_img.status = STARTED
                active_img.setAutoDraw(True)
            
            # if active_img is active this frame...
            if active_img.status == STARTED:
                # update params
                pass
            
            # if active_img is stopping this frame...
            if active_img.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > active_img.tStartRefresh + 5-frameTolerance:
                    # keep track of stop time/frame for later
                    active_img.tStop = t  # not accounting for scr refresh
                    active_img.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'active_img.stopped')
                    # update status
                    active_img.status = FINISHED
                    active_img.setAutoDraw(False)
            # Run 'Each Frame' code from code_6
            if i== 59:
                win.callOnFlip(trigger.send_trigger,trigger_active)
                i+=1
            else:
                i+=1
            
            # if sound_15 is starting this frame...
            if sound_15.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
                # keep track of start time/frame for later
                sound_15.frameNStart = frameN  # exact frame index
                sound_15.tStart = t  # local t and not account for scr refresh
                sound_15.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_15.started', tThisFlipGlobal)
                # update status
                sound_15.status = STARTED
                sound_15.play(when=win)  # sync with win flip
            # update sound_15 status according to whether it's playing
            if sound_15.isPlaying:
                sound_15.status = STARTED
            elif sound_15.isFinished:
                sound_15.status = FINISHED
            
            # check for quit (typically the Esc key)
            if defaultKeyboard.getKeys(keyList=["escape"]):
                thisExp.status = FINISHED
            if thisExp.status == FINISHED or endExpNow:
                endExperiment(thisExp, inputs=inputs, win=win)
                return
            
            # check if all components have finished
            if not continueRoutine:  # a component has requested a forced-end of Routine
                routineForceEnded = True
                break
            continueRoutine = False  # will revert to True if at least one component still running
            for thisComponent in task_3Components:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break  # at least one component has not yet finished
            
            # refresh the screen
            if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                win.flip()
        
        # --- Ending Routine "task_3" ---
        for thisComponent in task_3Components:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        thisExp.addData('task_3.stopped', globalClock.getTime())
        sound_15.pause()  # ensure sound has stopped at end of Routine
        # the Routine "task_3" was not non-slip safe, so reset the non-slip timer
        routineTimer.reset()
        
        # --- Prepare to start Routine "rest_3" ---
        continueRoutine = True
        # update component parameters for each repeat
        thisExp.addData('rest_3.started', globalClock.getTime())
        # Run 'Begin Routine' code from code_7
        win.callOnFlip(trigger.send_trigger,trigger_rest)
        sound_12.setSound('static/audios/ding.wav', secs=1.5, hamming=True)
        sound_12.setVolume(1.0, log=False)
        sound_12.seek(0)
        sound_13.setSound('static/audios/放松.wav', secs=3, hamming=True)
        sound_13.setVolume(1.0, log=False)
        sound_13.seek(0)
        # keep track of which components have finished
        rest_3Components = [image_7, sound_12, sound_13]
        for thisComponent in rest_3Components:
            thisComponent.tStart = None
            thisComponent.tStop = None
            thisComponent.tStartRefresh = None
            thisComponent.tStopRefresh = None
            if hasattr(thisComponent, 'status'):
                thisComponent.status = NOT_STARTED
        # reset timers
        t = 0
        _timeToFirstFrame = win.getFutureFlipTime(clock="now")
        frameN = -1
        
        # --- Run Routine "rest_3" ---
        routineForceEnded = not continueRoutine
        while continueRoutine and routineTimer.getTime() < 5.0:
            # get current time
            t = routineTimer.getTime()
            tThisFlip = win.getFutureFlipTime(clock=routineTimer)
            tThisFlipGlobal = win.getFutureFlipTime(clock=None)
            frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
            # update/draw components on each frame
            
            # *image_7* updates
            
            # if image_7 is starting this frame...
            if image_7.status == NOT_STARTED and tThisFlip >= 0-frameTolerance:
                # keep track of start time/frame for later
                image_7.frameNStart = frameN  # exact frame index
                image_7.tStart = t  # local t and not account for scr refresh
                image_7.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(image_7, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'image_7.started')
                # update status
                image_7.status = STARTED
                image_7.setAutoDraw(True)
            
            # if image_7 is active this frame...
            if image_7.status == STARTED:
                # update params
                pass
            
            # if image_7 is stopping this frame...
            if image_7.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > image_7.tStartRefresh + 5-frameTolerance:
                    # keep track of stop time/frame for later
                    image_7.tStop = t  # not accounting for scr refresh
                    image_7.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'image_7.stopped')
                    # update status
                    image_7.status = FINISHED
                    image_7.setAutoDraw(False)
            
            # if sound_12 is starting this frame...
            if sound_12.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                # keep track of start time/frame for later
                sound_12.frameNStart = frameN  # exact frame index
                sound_12.tStart = t  # local t and not account for scr refresh
                sound_12.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_12.started', tThisFlipGlobal)
                # update status
                sound_12.status = STARTED
                sound_12.play(when=win)  # sync with win flip
            
            # if sound_12 is stopping this frame...
            if sound_12.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > sound_12.tStartRefresh + 1.5-frameTolerance:
                    # keep track of stop time/frame for later
                    sound_12.tStop = t  # not accounting for scr refresh
                    sound_12.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'sound_12.stopped')
                    # update status
                    sound_12.status = FINISHED
                    sound_12.stop()
            # update sound_12 status according to whether it's playing
            if sound_12.isPlaying:
                sound_12.status = STARTED
            elif sound_12.isFinished:
                sound_12.status = FINISHED
            
            # if sound_13 is starting this frame...
            if sound_13.status == NOT_STARTED and tThisFlip >= 1.2-frameTolerance:
                # keep track of start time/frame for later
                sound_13.frameNStart = frameN  # exact frame index
                sound_13.tStart = t  # local t and not account for scr refresh
                sound_13.tStartRefresh = tThisFlipGlobal  # on global time
                # add timestamp to datafile
                thisExp.addData('sound_13.started', tThisFlipGlobal)
                # update status
                sound_13.status = STARTED
                sound_13.play(when=win)  # sync with win flip
            
            # if sound_13 is stopping this frame...
            if sound_13.status == STARTED:
                # is it time to stop? (based on global clock, using actual start)
                if tThisFlipGlobal > sound_13.tStartRefresh + 3-frameTolerance:
                    # keep track of stop time/frame for later
                    sound_13.tStop = t  # not accounting for scr refresh
                    sound_13.frameNStop = frameN  # exact frame index
                    # add timestamp to datafile
                    thisExp.timestampOnFlip(win, 'sound_13.stopped')
                    # update status
                    sound_13.status = FINISHED
                    sound_13.stop()
            # update sound_13 status according to whether it's playing
            if sound_13.isPlaying:
                sound_13.status = STARTED
            elif sound_13.isFinished:
                sound_13.status = FINISHED
            
            # check for quit (typically the Esc key)
            if defaultKeyboard.getKeys(keyList=["escape"]):
                thisExp.status = FINISHED
            if thisExp.status == FINISHED or endExpNow:
                endExperiment(thisExp, inputs=inputs, win=win)
                return
            
            # check if all components have finished
            if not continueRoutine:  # a component has requested a forced-end of Routine
                routineForceEnded = True
                break
            continueRoutine = False  # will revert to True if at least one component still running
            for thisComponent in rest_3Components:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break  # at least one component has not yet finished
            
            # refresh the screen
            if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                win.flip()
        
        # --- Ending Routine "rest_3" ---
        for thisComponent in rest_3Components:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        thisExp.addData('rest_3.stopped', globalClock.getTime())
        sound_12.pause()  # ensure sound has stopped at end of Routine
        sound_13.pause()  # ensure sound has stopped at end of Routine
        # using non-slip timing so subtract the expected duration of this Routine (unless ended on request)
        if routineForceEnded:
            routineTimer.reset()
        else:
            routineTimer.addTime(-5.000000)
        thisExp.nextEntry()
        
        if thisSession is not None:
            # if running in a Session with a Liaison client, send data up to now
            thisSession.sendExperimentData()
    # completed args.trial_num repeats of 'trials_3'
    
    
    # --- Prepare to start Routine "done" ---
    continueRoutine = True
    # update component parameters for each repeat
    thisExp.addData('done.started', globalClock.getTime())
    sound_5.setSound('static/audios/结束.wav', hamming=True)
    sound_5.setVolume(1.0, log=False)
    sound_5.seek(0)
    # keep track of which components have finished
    doneComponents = [end, sound_5]
    for thisComponent in doneComponents:
        thisComponent.tStart = None
        thisComponent.tStop = None
        thisComponent.tStartRefresh = None
        thisComponent.tStopRefresh = None
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    # reset timers
    t = 0
    _timeToFirstFrame = win.getFutureFlipTime(clock="now")
    frameN = -1
    
    # --- Run Routine "done" ---
    routineForceEnded = not continueRoutine
    while continueRoutine:
        # get current time
        t = routineTimer.getTime()
        tThisFlip = win.getFutureFlipTime(clock=routineTimer)
        tThisFlipGlobal = win.getFutureFlipTime(clock=None)
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *end* updates
        
        # if end is starting this frame...
        if end.status == NOT_STARTED and tThisFlip >= 0.5-frameTolerance:
            # keep track of start time/frame for later
            end.frameNStart = frameN  # exact frame index
            end.tStart = t  # local t and not account for scr refresh
            end.tStartRefresh = tThisFlipGlobal  # on global time
            win.timeOnFlip(end, 'tStartRefresh')  # time at next scr refresh
            # add timestamp to datafile
            thisExp.timestampOnFlip(win, 'end.started')
            # update status
            end.status = STARTED
            end.setAutoDraw(True)
        
        # if end is active this frame...
        if end.status == STARTED:
            # update params
            pass
        
        # if end is stopping this frame...
        if end.status == STARTED:
            # is it time to stop? (based on global clock, using actual start)
            if tThisFlipGlobal > end.tStartRefresh + 8-frameTolerance:
                # keep track of stop time/frame for later
                end.tStop = t  # not accounting for scr refresh
                end.frameNStop = frameN  # exact frame index
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'end.stopped')
                # update status
                end.status = FINISHED
                end.setAutoDraw(False)
        
        # if sound_5 is starting this frame...
        if sound_5.status == NOT_STARTED and tThisFlip >= 1-frameTolerance:
            # keep track of start time/frame for later
            sound_5.frameNStart = frameN  # exact frame index
            sound_5.tStart = t  # local t and not account for scr refresh
            sound_5.tStartRefresh = tThisFlipGlobal  # on global time
            # add timestamp to datafile
            thisExp.addData('sound_5.started', tThisFlipGlobal)
            # update status
            sound_5.status = STARTED
            sound_5.play(when=win)  # sync with win flip
        # update sound_5 status according to whether it's playing
        if sound_5.isPlaying:
            sound_5.status = STARTED
        elif sound_5.isFinished:
            sound_5.status = FINISHED
        
        # check for quit (typically the Esc key)
        if defaultKeyboard.getKeys(keyList=["escape"]):
            thisExp.status = FINISHED
        if thisExp.status == FINISHED or endExpNow:
            endExperiment(thisExp, inputs=inputs, win=win)
            return
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            routineForceEnded = True
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in doneComponents:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # --- Ending Routine "done" ---
    for thisComponent in doneComponents:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    thisExp.addData('done.stopped', globalClock.getTime())
    sound_5.pause()  # ensure sound has stopped at end of Routine
    # the Routine "done" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    
    # mark experiment as finished
    endExperiment(thisExp, win=win, inputs=inputs)


def saveData(thisExp):
    """
    Save data from this experiment
    
    Parameters
    ==========
    thisExp : psychopy.data.ExperimentHandler
        Handler object for this experiment, contains the data to save and information about 
        where to save it to.
    """
    filename = thisExp.dataFileName
    # these shouldn't be strictly necessary (should auto-save)
    thisExp.saveAsWideText(filename + '.csv', delim='auto')
    thisExp.saveAsPickle(filename)


def endExperiment(thisExp, inputs=None, win=None):
    """
    End this experiment, performing final shut down operations.
    
    This function does NOT close the window or end the Python process - use `quit` for this.
    
    Parameters
    ==========
    thisExp : psychopy.data.ExperimentHandler
        Handler object for this experiment, contains the data to save and information about 
        where to save it to.
    inputs : dict
        Dictionary of input devices by name.
    win : psychopy.visual.Window
        Window for this experiment.
    """
    if win is not None:
        # remove autodraw from all current components
        win.clearAutoDraw()
        # Flip one final time so any remaining win.callOnFlip() 
        # and win.timeOnFlip() tasks get executed
        win.flip()
    # mark experiment handler as finished
    thisExp.status = FINISHED
    # shut down eyetracker, if there is one
    if inputs is not None:
        if 'eyetracker' in inputs and inputs['eyetracker'] is not None:
            inputs['eyetracker'].setConnectionState(False)
    logging.flush()


def quit(thisExp, win=None, inputs=None, thisSession=None):
    """
    Fully quit, closing the window and ending the Python process.
    
    Parameters
    ==========
    win : psychopy.visual.Window
        Window to close.
    inputs : dict
        Dictionary of input devices by name.
    thisSession : psychopy.session.Session or None
        Handle of the Session object this experiment is being run from, if any.
    """
    thisExp.abort()  # or data files will save again on exit
    # make sure everything is closed down
    if win is not None:
        # Flip one final time so any remaining win.callOnFlip() 
        # and win.timeOnFlip() tasks get executed before quitting
        win.flip()
        win.close()
    if inputs is not None:
        if 'eyetracker' in inputs and inputs['eyetracker'] is not None:
            inputs['eyetracker'].setConnectionState(False)
    logging.flush()
    if thisSession is not None:
        thisSession.stop()
    # terminate Python process
    core.quit()


# if running this experiment as a script...
if __name__ == '__main__':
    # call all functions in order
    expInfo = showExpInfoDlg(expInfo=expInfo)
    thisExp = setupData(expInfo=expInfo)
    logFile = setupLogging(filename=thisExp.dataFileName)
    win = setupWindow(expInfo=expInfo)
    inputs = setupInputs(expInfo=expInfo, thisExp=thisExp, win=win)
    run(
        expInfo=expInfo, 
        thisExp=thisExp, 
        win=win, 
        inputs=inputs
    )
    saveData(thisExp=thisExp)
    quit(thisExp=thisExp, win=win, inputs=inputs)
