Example #1
0
 def on_enter(self):
     if isinstance(director.scene, TransitionScene): return
     
     super(Task, self).on_enter()
     
     header = []
     
     if director.settings['mode'] == 'Experiment':
         header += ["datestamp", "encrypted_rin"]
         
     header += ["system_time", "mode", "trial", "state", "event_source", "event_type",
                "event_id", "screen_width", "screen_height", "mouse_x", "mouse_y",
                "study_time", "search_time"]
     
     if director.settings['eyetracker'] and self.client:
         self.smi_spl_header = ["smi_time", "smi_type",
                                "smi_sxl", "smi_sxr", "smi_syl", "smi_syr",
                                "smi_dxl", "smi_dxr", "smi_dyl", "smi_dyr",
                                "smi_exl", "smi_exr", "smi_eyl", "smi_eyr", "smi_ezl", "smi_ezr"]
         header += self.smi_spl_header + ["smi_fx", "smi_fy"]
         
     self.logger = Logger(header)
     self.tarfile = tarfile.open('data/%s.tar.gz' % director.settings['filebase'], mode='w:gz')
           
     self.position = ((self.screen[0] - self.screen[1]) / 2, 0)
     self.cm = CollisionManagerBruteForce()
     self.mono = font.load("Mono", 32)
     self.shapes = {"oval":"F",
                    # "diamond":"T",
                    "crescent":"Q",
                    "cross":"Y",
                    "star":"C"}
     # star 83x79       1.05     2581/6557  .39
     # oval 55x83        .66     3427/4565  .75
     # crescent 51x77    .66     1580/3927  .40
     # cross 61x62       .98     1783/3782  .47
     # rect 46x73.       .63     3358/3358  1
     # cross2 57x84      .67     1532/4788  .31
     self.shape_mod = {"oval":[1.0, 1.0, 1.0],
                       # "diamond":"T",
                       "crescent":[1.07, 1.07, 1.07],
                       "cross":[1.15, 1.15, 1.15],
                       "star":[1.0, 1.0, 1.0]} 
     self.font = font.load('Cut Outs for 3D FX', 128)
     for shape in self.shapes:
         self.shapes[shape] = self.font.get_glyphs(self.shapes[shape])[0].get_texture(True)
     s = 50
     v = 100
     self.colors = {"red": hsv_to_rgb(0, s, v),
                    "yellow": hsv_to_rgb(72, s, v),
                    "green": hsv_to_rgb(144, s, v),
                    # "purple": hsv_to_rgb(288, s, v),
                    "blue": hsv_to_rgb(216, s, v)}
     self.side = self.screen[1] / 11
     self.ratio = self.side / 128
     self.scales = [self.ratio * 2, self.ratio * 1.25, self.ratio * .5]
     self.sizes = ["large", "medium", "small"]
     self.ready_label = Label("Click mouse when ready!",
                              position=(self.width / 2, self.height / 2),
                              font_name='Pipe Dream', font_size=24,
                              color=(0, 0, 0, 255), anchor_x='center', anchor_y='center')
     
     self.gaze = Label('G',font_name='Cut Outs for 3D FX', font_size=48,
                       position=(self.width / 2, self.height / 2),
                       color=(255, 0, 0, 192), anchor_x='center', anchor_y='center')
     self.attention = Label('G',font_name='Cut Outs for 3D FX', font_size=48,
                            position=(self.width / 2, self.height / 2),
                            color=(0, 0, 255, 192), anchor_x='center', anchor_y='center')
             
     self.reset_state()
     
     if director.settings['player'] == "ACT-R":
         self.add(self.gaze, z=99)
         self.add(self.attention, z=99)
         self.client_actr.addDispatcher(self.actr_d)            
         self.state = self.STATE_WAIT_ACTR_CONNECTION
         self.dispatch_event("actr_wait_connection")
     elif director.settings['eyetracker']:
         self.state = self.STATE_CALIBRATE
         self.dispatch_event("start_calibration", self.calibration_ok, self.calibration_bad)
     else:
         self.next_trial()
Example #2
0
class Task(ColorLayer, pyglet.event.EventDispatcher):
    
    d = Dispatcher()
    actr_d = JNI_Dispatcher()
    
    states = ["INIT", "WAIT_ACTR_CONNECTION", "WAIT_ACTR_MODEL", "CALIBRATE", 
              "IGNORE_INPUT", "WAIT", "STUDY", "SEARCH", "RESULTS"]
    STATE_INIT = 0
    STATE_CALIBRATE = 1
    STATE_IGNORE_INPUT = 2
    STATE_WAIT_ACTR_CONNECTION = 3
    STATE_WAIT_ACTR_MODEL = 4
    STATE_WAIT = 5
    STATE_STUDY = 6
    STATE_SEARCH = 7
    STATE_RESULTS = 8
    
    is_event_handler = True
    
    def __init__(self, client, actr):
        self.screen = director.get_window_size()
        super(Task, self).__init__(168, 168, 168, 255, self.screen[1], self.screen[1])
        self.state = self.STATE_INIT
        self.client = client
        self.client_actr = actr
        self.circles = []
        self.trial_complete = False
        
    def on_enter(self):
        if isinstance(director.scene, TransitionScene): return
        
        super(Task, self).on_enter()
        
        header = []
        
        if director.settings['mode'] == 'Experiment':
            header += ["datestamp", "encrypted_rin"]
            
        header += ["system_time", "mode", "trial", "state", "event_source", "event_type",
                   "event_id", "screen_width", "screen_height", "mouse_x", "mouse_y",
                   "study_time", "search_time"]
        
        if director.settings['eyetracker'] and self.client:
            self.smi_spl_header = ["smi_time", "smi_type",
                                   "smi_sxl", "smi_sxr", "smi_syl", "smi_syr",
                                   "smi_dxl", "smi_dxr", "smi_dyl", "smi_dyr",
                                   "smi_exl", "smi_exr", "smi_eyl", "smi_eyr", "smi_ezl", "smi_ezr"]
            header += self.smi_spl_header + ["smi_fx", "smi_fy"]
            
        self.logger = Logger(header)
        self.tarfile = tarfile.open('data/%s.tar.gz' % director.settings['filebase'], mode='w:gz')
              
        self.position = ((self.screen[0] - self.screen[1]) / 2, 0)
        self.cm = CollisionManagerBruteForce()
        self.mono = font.load("Mono", 32)
        self.shapes = {"oval":"F",
                       # "diamond":"T",
                       "crescent":"Q",
                       "cross":"Y",
                       "star":"C"}
        # star 83x79       1.05     2581/6557  .39
        # oval 55x83        .66     3427/4565  .75
        # crescent 51x77    .66     1580/3927  .40
        # cross 61x62       .98     1783/3782  .47
        # rect 46x73.       .63     3358/3358  1
        # cross2 57x84      .67     1532/4788  .31
        self.shape_mod = {"oval":[1.0, 1.0, 1.0],
                          # "diamond":"T",
                          "crescent":[1.07, 1.07, 1.07],
                          "cross":[1.15, 1.15, 1.15],
                          "star":[1.0, 1.0, 1.0]} 
        self.font = font.load('Cut Outs for 3D FX', 128)
        for shape in self.shapes:
            self.shapes[shape] = self.font.get_glyphs(self.shapes[shape])[0].get_texture(True)
        s = 50
        v = 100
        self.colors = {"red": hsv_to_rgb(0, s, v),
                       "yellow": hsv_to_rgb(72, s, v),
                       "green": hsv_to_rgb(144, s, v),
                       # "purple": hsv_to_rgb(288, s, v),
                       "blue": hsv_to_rgb(216, s, v)}
        self.side = self.screen[1] / 11
        self.ratio = self.side / 128
        self.scales = [self.ratio * 2, self.ratio * 1.25, self.ratio * .5]
        self.sizes = ["large", "medium", "small"]
        self.ready_label = Label("Click mouse when ready!",
                                 position=(self.width / 2, self.height / 2),
                                 font_name='Pipe Dream', font_size=24,
                                 color=(0, 0, 0, 255), anchor_x='center', anchor_y='center')
        
        self.gaze = Label('G',font_name='Cut Outs for 3D FX', font_size=48,
                          position=(self.width / 2, self.height / 2),
                          color=(255, 0, 0, 192), anchor_x='center', anchor_y='center')
        self.attention = Label('G',font_name='Cut Outs for 3D FX', font_size=48,
                               position=(self.width / 2, self.height / 2),
                               color=(0, 0, 255, 192), anchor_x='center', anchor_y='center')
                
        self.reset_state()
        
        if director.settings['player'] == "ACT-R":
            self.add(self.gaze, z=99)
            self.add(self.attention, z=99)
            self.client_actr.addDispatcher(self.actr_d)            
            self.state = self.STATE_WAIT_ACTR_CONNECTION
            self.dispatch_event("actr_wait_connection")
        elif director.settings['eyetracker']:
            self.state = self.STATE_CALIBRATE
            self.dispatch_event("start_calibration", self.calibration_ok, self.calibration_bad)
        else:
            self.next_trial()

    def reset_state(self):
        s = int(director.settings['seed'])
        if s > 0:
            seed(s)
        self.current_trial = 0
        self.total_trials = None
        if director.settings['mode'] == 'Experiment':
            self.gen_trials()
        self.fake_cursor = (self.screen[0] / 2, self.screen[1] / 2)
            
    def calibration_ok(self):
        self.dispatch_event("stop_calibration")
        self.next_trial()
        
    def calibration_bad(self):
        self.dispatch_event("stop_calibration")
        self.logger.close(True)
        self.tarfile.close()
        director.scene.dispatch_event("show_intro_scene")
        
    def on_exit(self):
        if isinstance(director.scene, TransitionScene): return
        if self.client_actr:
            self.client_actr.removeDispatcher(self.actr_d)
            self.client_actr.disconnect()
        super(Task, self).on_exit()
        for c in self.get_children():
            if c != self.gaze and c != self.attention: self.remove(c)
    
    def next_trial(self):
        self.trial_complete = False
        if self.current_trial == self.total_trials:
            self.logger.close(True)
            self.tarfile.close()
            director.scene.dispatch_event("show_intro_scene")
        else:
            self.search_time = -1
            self.study_time = -1
            director.window.set_mouse_visible(False)
            self.clear_shapes()
            self.log_extra = {'screen_width':self.screen[0],
                              'screen_height': self.screen[1]}
            if director.settings['player'] == 'Human' and director.settings['mode'] == 'Experiment':
                self.log_extra['datestamp'] = director.settings['si']['timestamp']
                self.log_extra['encrypted_rin'] = director.settings['si']['encrypted_rin']
            self.state = self.STATE_WAIT
            self.current_trial += 1
            self.gen_combos()
            self.add(self.ready_label)
            
            self.logger.open(StringIO())
            self.logger.write(system_time=get_time(), mode=director.settings['mode'], trial=self.current_trial,
                              event_source="TASK", event_type=self.states[self.state], state=self.states[self.state],
                              event_id="START", **self.log_extra)
            self.dispatch_event("new_trial", self.current_trial, self.total_trials)
            if self.client:
                self.dispatch_event("show_headposition")
                
            if director.settings['player'] == 'ACT-R':
                X = VisualChunk(None, "text", self.screen[0] / 2, self.screen[1] / 2, value="Click mouse when ready!", width=self.ready_label.element.content_width, height=self.ready_label.element.content_height)
                self.client_actr.update_display([X], clear=True)
    
    def trial_done(self):
        self.trial_complete = True
        t = get_time()
        self.search_time = t - self.start_time
        self.logger.write(system_time=t, mode=director.settings['mode'], trial=self.current_trial,
                          event_source="TASK", event_type=self.states[self.state], state=self.states[self.state],
                          event_id="END", **self.log_extra)
        self.state = self.STATE_RESULTS
        self.logger.write(system_time=t, mode=director.settings['mode'], trial=self.current_trial,
                          event_source="TASK", event_type=self.states[self.state], state=self.states[self.state],
                          study_time=self.study_time, search_time=self.search_time, **self.log_extra)
        
        tmp = self.logger.file.getvalue()
        data = tarfile.TarInfo("%s/trial-%02d.txt" % (director.settings['filebase'], self.current_trial))
        data.size = len(tmp)
        self.tarfile.addfile(data, StringIO(tmp))
        
        tmp = StringIO()
        screenshot().save(tmp, "png")
        data = tarfile.TarInfo("%s/trial-%02d.png" % (director.settings['filebase'], self.current_trial))
        data.size = len(tmp.getvalue())
        tmp.seek(0)
        self.tarfile.addfile(data, tmp)
        
        self.logger.close()
        if director.settings['eyetracker'] and self.client:
            self.client.removeDispatcher(self.d)
            self.client.stopFixationProcessing()
        
        if director.settings['player'] == 'ACT-R' and director.settings['mode'] != 'Experiment':
            self.client_actr.trigger_event(":trial-complete")
        else:
            self.next_trial()
        
    def gen_trials(self):
        self.trials = []
        for scale in self.sizes:
            for color in self.colors:
                for shape in self.shapes:
                    for c in range(0, 8):
                        self.trials.append([shape, color, scale, c])
        self.total_trials = len(self.trials)
        shuffle(self.trials)
        
    def gen_combos(self):
        ids = range(1, len(self.sizes) * len(self.colors) * len(self.shapes) + 1)
        shuffle(ids)
        self.combos = []
        for scale in self.sizes:
            for color in self.colors:
                for shape in self.shapes:
                    self.combos.append([shape, color, scale, ids.pop()])
        
    def gen_probe(self):
        for c in self.get_children():
            if c != self.gaze and c != self.attention: self.remove(c)
        s = 0
        if director.settings['mode'] == 'Experiment':
            trial = self.trials.pop()
            for c in self.combos:
                if c[0] == trial[0] and c[1] == trial[1] and c[2] == trial[2]:
                    chunk = c
                    s = trial[3]
                    break
        else:
            if director.settings['mode'] == 'Moderate':
                s = choice(range(0, 4))
            elif director.settings['mode'] == 'Hard':
                s = choice(range(0, 7))
            elif director.settings['mode'] == 'Insane':
                s = choice(range(0, 8))
            chunk = choice(self.combos)
        self.probe = Probe(chunk, s, self.side, (self.screen[1] / 2, self.screen[1] / 2), 14 * self.ratio)
        self.add(self.probe)
        
    def clear_shapes(self):
        self.circles = []
        self.cm.clear()
        for c in self.get_children():
            if c != self.gaze and c != self.attention: self.remove(c)
        self.batch = BatchNode()
        self.id_batch = BatchNode()
    
    def show_shapes(self):
        self.cm.add(self.probe)
        ratio = self.side / 128
        self.circles = []
        shapeinfo = {}
        shapeinfo['probe'] = {"id": self.probe.chunk[3],
                              "color": self.probe.color_visible,
                              "shape": self.probe.shape_visible,
                              "size": self.probe.size_visible}
        actr_chunks = self.probe.actr_chunks
        for c in self.combos:
            img = self.shapes[c[0]]
            img.anchor_x = 'center'
            img.anchor_y = 'center'
            sprite = Shape(img, chunk=c, rotation=randrange(0, 365), color=self.colors[c[1]], scale=self.shape_mod[c[0]][self.sizes.index(c[2])] * self.scales[self.sizes.index(c[2])])
            pad = sprite.radius
            sprite.set_position(uniform(pad, self.screen[1] - pad), uniform(pad, self.screen[1] - pad))
            while self.cm.objs_colliding(sprite):
                sprite.set_position(uniform(pad, self.screen[1] - pad), uniform(pad, self.screen[1] - pad))
            fs = 14 * ratio
            text.Label("%02d" % c[3], font_size=fs,
                       x=sprite.position[0], y=sprite.position[1],
                       font_name="Monospace", color=(32, 32, 32, 255),
                       anchor_x='center', anchor_y='center', batch=self.id_batch.batch)
            shapeinfo[c[3]] = {'shape':c[0], 'color':c[1], 'size':c[2], 'id': c[3],
                               'radius':sprite.cshape.r, 'x':sprite.position[0], 'y':sprite.position[1]}
            self.circles.append(Circle(sprite.position[0] + (self.screen[0] - self.screen[1]) / 2, sprite.position[1], width=2 * sprite.cshape.r))
            self.cm.add(sprite)
            self.batch.add(sprite)
            actr_chunks.append(PAAVChunk(None, "visual-object", 
                                         sprite.position[0] + (self.screen[0] - self.screen[1]) / 2,
                                         sprite.position[1],
                                         width = 2 * sprite.cshape.r,
                                         height = 2 * sprite.cshape.r,
                                         fshape = ":w67-%s" % c[0],
                                         fcolor = ":w67-%s" % c[1],
                                         fsize = ":w67-%s" % c[2]))
            actr_chunks.append(VisualChunk(None, "text", 
                                           sprite.position[0] + (self.screen[0] - self.screen[1]) / 2,
                                           sprite.position[1],
                                           width = 2 * fs,
                                           height = fs,
                                           value = "%02d" % c[3]))
        if director.settings['player'] == 'ACT-R' and actr_chunks:
            self.client_actr.update_display(actr_chunks, clear=False)
        self.circles.append(Circle(self.probe.position[0] + (self.screen[0] - self.screen[1]) / 2, self.probe.position[1], width=2 * self.probe.cshape.r))
        self.add(self.batch, z=1)
        self.add(self.id_batch, z=2)
        s = StringIO(json.dumps(shapeinfo, sort_keys=True, indent=4))
        data = tarfile.TarInfo("%s/trial-%02d.json" % (director.settings['filebase'], self.current_trial))
        data.size = len(s.getvalue())
        s.seek(0)
        self.tarfile.addfile(data, s)
        
    if ACTR6:
        @actr_d.listen('connectionMade')
        def ACTR6_JNI_Event(self, model, params):
            print "ACT-R Connection Made"
            self.state = self.STATE_WAIT_ACTR_MODEL
            self.dispatch_event("actr_wait_model")
            self.client_actr.setup(self.screen[1], self.screen[1])
            
        @actr_d.listen('connectionLost')
        def ACTR6_JNI_Event(self, model, params):
            print "ACT-R Connection Lost"
            self.state = self.STATE_WAIT_ACTR_CONNECTION
            self.dispatch_event("actr_wait_connection")
            
        @actr_d.listen('reset')
        def ACTR6_JNI_Event(self, model, params):
            print "ACT-R Reset"
            self.state = self.STATE_WAIT_ACTR_MODEL
            self.dispatch_event("actr_wait_model")
            self.reset_state()
            
        @actr_d.listen('model-run')
        def ACTR6_JNI_Event(self, model, params):
            print "ACT-R Model Run"
            self.dispatch_event("actr_running")
            if params['resume']:
                if self.trial_complete:
                    self.next_trial()
            else:
                self.reset_state()
                self.next_trial()
            
        @actr_d.listen('model-stop')
        def ACTR6_JNI_Event(self, model, params):
            print "ACT-R Model Stop"

        @actr_d.listen('gaze-loc')
        def ACTR6_JNI_Event(self, model, params):
            if params['loc']:
                params['loc'][0] -= (self.screen[0] - self.screen[1]) / 2
                print "ACT-R Gaze: ",
                print params['loc']
                self.gaze.position = params['loc']
                self.gaze.visible = True
            else:
                self.gaze.visible = False
            
        @actr_d.listen('attention-loc')
        def ACTR6_JNI_Event(self, model, params):
            if params['loc']:
                params['loc'][0] -= (self.screen[0] - self.screen[1]) / 2
                print "ACT-R Attention: ",
                print params['loc']
                self.attention.position = params['loc']
                self.attention.visible = True
            else:
                self.attention.visible = False

        @actr_d.listen('keypress')
        def ACTR6_JNI_Event(self, model, params):
            print "ACT-R Keypress: %s" % chr(params['keycode'])
            self.on_key_press(params['keycode'], None)

        @actr_d.listen('mousemotion')
        def ACTR6_JNI_Event(self, model, params):
            # Store "ACT-R" cursor in variable since we are 
            # not going to move the real mouse
            print "ACT-R Mousemotion: ",
            print params
            self.fake_cursor = params['loc']
            self.on_mouse_motion(self.fake_cursor[0], self.fake_cursor[1], None, None)

        @actr_d.listen('mouseclick')
        def ACTR6_JNI_Event(self, model, params):
            # Simulate a button press using the "ACT-R" cursor loc
            print "ACT-R Mouseclick"
            self.on_mouse_press(self.fake_cursor[0], self.fake_cursor[1], 1, None)
    
    if eyetracking:
        @d.listen('ET_FIX')
        def iViewXEvent(self, inResponse):
            eyedata = {}
            eyedata.update(self.log_extra)
            eyedata["smi_type"] = inResponse[0]
            eyedata["smi_time"] = inResponse[1]
            eyedata["smi_fx"] = inResponse[2]
            eyedata["smi_fy"] = inResponse[3]
            self.logger.write(system_time=get_time(), mode=director.settings['mode'], state=self.states[self.state], 
                              trial=self.current_trial, event_source="SMI", event_type="ET_FIX", **eyedata)
            
        @d.listen('ET_SPL')
        def iViewXEvent(self, inResponse):
            eyedata = {}
            eyedata.update(self.log_extra)
            for i, _ in enumerate(self.smi_spl_header):
                eyedata[self.smi_spl_header[i]] = inResponse[i]
            self.logger.write(system_time=get_time(), mode=director.settings['mode'], state=self.states[self.state], 
                              trial=self.current_trial, event_source="SMI", event_type="ET_SPL", **eyedata)
    # def draw(self):
    #    super(Task, self).draw()
    #    for c in self.circles: c.render()
        
    def on_mouse_press(self, x, y, buttons, modifiers):
        if self.state < self.STATE_IGNORE_INPUT: return
        if self.state == self.STATE_WAIT:
            self.logger.write(system_time=get_time(), mode=director.settings['mode'], trial=self.current_trial,
                              event_source="TASK", event_type=self.states[self.state], state=self.states[self.state],
                              event_id="END", **self.log_extra)
            self.gen_probe()
            self.state = self.STATE_STUDY
            if director.settings['player'] == 'ACT-R':
                self.client_actr.update_display(self.probe.actr_chunks, clear=True)
            t = get_time()
            self.start_time = t
            self.logger.write(system_time=t, mode=director.settings['mode'], trial=self.current_trial,
                              event_source="TASK", event_type=self.states[self.state], state=self.states[self.state], 
                              event_id="START", **self.log_extra)
            if director.settings['eyetracker'] and self.client:
                self.dispatch_event("hide_headposition")
                self.client.addDispatcher(self.d)
                self.client.startFixationProcessing()
        elif self.state == self.STATE_SEARCH:
            self.logger.write(system_time=get_time(), mode=director.settings['mode'], trial=self.current_trial,
                              event_source="USER", event_type=self.states[self.state], state=self.states[self.state], 
                              event_id="MOUSE_PRESS", mouse_x=x, mouse_y=y, **self.log_extra)
            if director.settings['player'] != "ACT-R":
                x, y = director.get_virtual_coordinates(x, y)
            for obj in self.cm.objs_touching_point(x - (self.screen[0] - self.screen[1]) / 2, y):
                if obj != self.probe and obj.chunk == self.probe.chunk:
                    self.trial_done()
        else:
            t = get_time()
            self.study_time = t - self.start_time
            self.logger.write(system_time=t, mode=director.settings['mode'], trial=self.current_trial,
                              event_source="TASK", event_type=self.states[self.state], state=self.states[self.state], 
                              event_id="END", **self.log_extra)
            self.show_shapes()
            window = director.window.get_size()
            nx = int(window[0] / 2)
            ny = int(window[1] / 2 - self.probe.cshape.r * .75 * (window[1] / self.screen[1]))
            t = get_time()
            self.start_time = t
            self.state = self.STATE_SEARCH
            self.logger.write(system_time=t, mode=director.settings['mode'], trial=self.current_trial,
                              event_source="TASK", event_type=self.states[self.state], state=self.states[self.state], 
                              event_id="START", **self.log_extra)
            self.logger.write(system_time=t, mode=director.settings['mode'], trial=self.current_trial,
                              event_source="TASK", event_type=self.states[self.state], state=self.states[self.state], 
                              event_id="MOUSE_RESET", mouse_x=nx, mouse_y=ny, **self.log_extra)
            if director.settings['player'] == "ACT-R":
                self.client_actr.set_cursor_location([nx, ny])
            else:
                director.window.set_mouse_position(nx, ny)
            director.window.set_mouse_visible(True)

    def on_mouse_motion(self, x, y, dx, dy):
        if self.state < self.STATE_IGNORE_INPUT: return
        if self.state == self.STATE_SEARCH:
            self.logger.write(system_time=get_time(), mode=director.settings['mode'], trial=self.current_trial,
                              event_source="USER", event_type=self.states[self.state], state=self.states[self.state], 
                              event_id="MOUSE_MOTION", mouse_x=x, mouse_y=y, **self.log_extra)
        
    def on_key_press(self, symbol, modifiers):
        if self.state <= self.STATE_IGNORE_INPUT: return
        if symbol == key.W and (modifiers & key.MOD_ACCEL):
            self.logger.close(True)
            self.tarfile.close()
            director.scene.dispatch_event("show_intro_scene")
            True
        elif symbol == key.ESCAPE and director.settings['player'] == "ACT-R":
            if self.state == self.STATE_WAIT_ACTR_CONNECTION:
                director.scene.dispatch_event("show_intro_scene")
                True
            elif self.state > self.STATE_WAIT_ACTR_MODEL:
                self.client_actr.trigger_event(":break")
                True