예제 #1
0
    def test_single_stroke_in_char_with_space_ending_previous_char(self):

        chars = create_chars(['PS', 'SPS', 'PS'])
        #  Deleting this:             ^
        #  Expected result: merge with the preceding&following space

        new_chars, err_msg = delete_stroke(chars, DummySelectionHandler(chars, 1, 1))

        self.assertEquals(2, len(new_chars))
        if len(new_chars) != 2:
            return

        c0, c1 = chars

        self.assertEquals('PS', char_strokes(c0))
        self.assertEquals('PS', char_strokes(c1))

        self._validate_char_and_stroke_nums(chars)

        self.assertEquals(1, len(c0.strokes[0].trajectory))
        self.assertEquals(4, len(c0.strokes[1].trajectory))
예제 #2
0
    def test_delete_first_stroke_in_2nd_char(self):

        chars = create_chars(['PSPS', 'PSP', 'PS'])
        #  Deleting this:              ^
        #  Expected result: merge with the following space, and with the space at the end of the previous character

        new_chars, err_msg = delete_stroke(chars, DummySelectionHandler(chars, 1, 0))

        self.assertEquals(3, len(new_chars))
        if len(new_chars) != 3:
            return

        c0, c1, c2 = chars

        self.assertEquals('PSPS', char_strokes(c0))
        self.assertEquals('P', char_strokes(c1))
        self.assertEquals('PS', char_strokes(c2))

        self._validate_char_and_stroke_nums(chars)

        self.assertEquals(3, len(c0.strokes[3].trajectory))
예제 #3
0
    def test_delete_last_stroke_in_char_before_space(self):

        chars = create_chars(['PSPS', 'PSP', 'PS'])
        #  Deleting this:        ^
        #  Expected result: merge with the preceding space

        new_chars, err_msg = delete_stroke(chars, DummySelectionHandler(chars, 0, 2))

        self.assertEquals(3, len(new_chars))
        if len(new_chars) != 3:
            return

        c0, c1, c2 = chars

        self.assertEquals('PS', char_strokes(c0))
        self.assertEquals('PSP', char_strokes(c1))
        self.assertEquals('PS', char_strokes(c2))

        self._validate_char_and_stroke_nums(chars)

        self.assertEquals(1, len(c0.strokes[0].trajectory))
        self.assertEquals(3, len(c0.strokes[1].trajectory))
예제 #4
0
    def test_single_stroke_in_char(self):

        chars = create_chars(['PSP', 'SPS', 'PS'])
        #  Deleting this:              ^
        #  Expected result: character deleted

        new_chars, err_msg = delete_stroke(chars, DummySelectionHandler(chars, 1, 1))

        self.assertEquals(2, len(new_chars))

        if len(new_chars) != 2:
            return

        c0, c1 = chars

        self.assertEquals('PSPS', char_strokes(c0))
        self.assertEquals('PS', char_strokes(c1))

        self._validate_char_and_stroke_nums(chars)

        self.assertEquals(1, len(c0.strokes[0].trajectory))
        self.assertEquals(1, len(c0.strokes[1].trajectory))
        self.assertEquals(1, len(c0.strokes[2].trajectory))
        self.assertEquals(3, len(c0.strokes[3].trajectory))
예제 #5
0
def _try_encode_trial(trial, characters, sub_trial_num, out_dir, screen_size,
                      margin, response):
    """"
    returns in this order: rc, characters, extra_info
    """
    strokes = [s for c in characters for s in c.on_paper_strokes]
    all_markup_dots = [dot for c in characters for dot in c.on_paper_dots]

    #-- Skipping empty trials
    if len(strokes) == 0:
        dataio.save_trial(trial, '', 'empty', characters, sub_trial_num,
                          out_dir)
        trial.processed = True
        return 'next_trial', None, None

    on_paper_chars = [c for c in characters if len(c.trajectory) > 0]
    on_paper_strokes = [s for s in strokes if len(s.trajectory) > 0]

    expand_ratio, offset, screen_size = _get_expand_ratio(
        all_markup_dots, screen_size, margin)

    title = 'Trial #{}, target={} ({} characters, {} strokes) '\
        .format(trial.trial_id, trial.stimulus, len(on_paper_chars), len(on_paper_strokes))

    window = _create_window_for_markup(screen_size, title, response or '')

    if len(on_paper_chars) < 2:
        window['merge_chars'].update(disabled=True)
        window['split_trial'].update(disabled=True)

    window['accept_error'].update(disabled=True)

    graph = window.Element('graph')
    instructions = window.Element('instructions')

    _plot_dots_for_markup(characters, graph, screen_size, expand_ratio, offset,
                          margin)

    selection_handler = None
    current_command = None

    while True:

        cleanup_selection_handler = False

        event, values = window.Read()

        m = re.match('.+:(\\d+)', event)
        if m is not None:
            event = int(m.group(1))

        #-- Window was closed: reset the trial
        if event is None:
            return 'reset_trial', None, None

        #-- Reset the trial
        elif event in ('r', 'R', 'reset_trial', 82, 'ר'):
            answer = sg.Popup(
                'Reset trial',
                'Are you sure you want to reset the current trial?',
                button_type=1)
            if answer == "Yes":
                window.Close()
                return 'reset_trial', None, None

        #-- Quit the app
        elif event in ('q', 'Q', 'quit', '/'):
            answer = sg.Popup('Quit',
                              'Are you sure you want to quit WEncoder?',
                              button_type=1)
            if answer == "Yes":
                window.Close()
                return 'quit', None, None

        #-- Select trial
        elif event in ('g', 'G', 'choose_trial', 71, 'ע'):
            window.Close()
            return 'choose_trial', None, None

        #-- Open settings window
        elif event in ('e', 'E', 'settings', 69, 'ק'):
            window.Close()
            return 'settings', None, None

        #-- OK - Accept current coding
        if event in ('a', 'A', 'accept', 65, 'ש'):
            resp_optional = app_config[
                'response_mandatory'] == ResponseMandatory.Optional
            if not resp_optional:
                response = get_valid_user_response(response,
                                                   on_paper_chars,
                                                   trial.stimulus,
                                                   get_if_already_exists=False)

            if resp_optional or response is not None:
                if sub_trial_num == 1:
                    dataio.delete_trial(out_dir, trial.trial_id)
                dataio.save_trial(trial, response, "OK", characters,
                                  sub_trial_num, out_dir)
                trial.processed = True
                window.Close()
                return 'next_trial', None, None

        #-- Clicked on DropDown error
        elif event == 'error_code':
            if values['error_code'] in app_config["error_codes"]:
                window['accept_error'].update(disabled=False)
                #window['accept'].update(disabled=True)

            # else:
            #     window['accept_error'].update(disabled=True)

        #-- Error - Accept current coding, set trial as error
        elif event in ('o', 'O', 'accept_error', 79, 'ם'):
            resp_optional = app_config[
                'response_mandatory'] != ResponseMandatory.MandatoryForAll
            if not resp_optional:
                response = get_valid_user_response(response,
                                                   on_paper_chars,
                                                   trial.stimulus,
                                                   get_if_already_exists=False)

            if resp_optional or response is not None:
                if sub_trial_num == 1:
                    dataio.delete_trial(out_dir, trial.trial_id)
                dataio.save_trial(trial, response, values['error_code'],
                                  characters, sub_trial_num, out_dir)
                trial.processed = True
                window.Close()
                return 'next_trial', None, None

        #-- Skip this trial
        elif event in ('k', 'K', 'skip_trial', 75, 'ל'):
            window.Close()
            return 'next_trial', None, None

        #-- Return to previous trial
        elif event in ('p', 'P', 'prev_trial', 80, 'פ'):
            window.Close()
            return 'prev_trial', None, None

        #-- Merge 2 characters
        elif event in ('m', 'M', 'merge_chars', 77, 'צ'):
            if current_command is None and len(characters) > 1:
                instructions.Update(
                    'Select the characters to merge. ENTER=confirm, ESC=abort')
                current_command = 'merge_chars'
                selection_handler = _CharsSelectorConsecutivePair(
                    graph, characters)

        #-- Split a stroke into 2 characters
        elif event in ('s', 'S', 'split_stroke', 83, 'ד'):
            if current_command is None:
                instructions.Update(
                    'Select a stroke to split. ENTER=confirm, ESC=abort')
                current_command = 'split_stroke'
                selection_handler = _SingleStrokeSelector(graph, strokes)

        #-- Split a character
        elif event in ('c', 'C', 'split_char', 67, 'ב'):
            if current_command is None:
                instructions.Update(
                    'Select a character to split to 2 different characters. ENTER=confirm, ESC=abort'
                )
                current_command = 'split_char'
                selection_handler = _MultiStrokeSelector(
                    graph, characters, 'before')

        #-- Split the trial into 2 trials
        elif event in ('t', 'T', 'split_trial', 84, 'א'):
            if current_command is None:
                instructions.Update(
                    'Select the last character of trial#1. ENTER=confirm, ESC=abort'
                )
                current_command = 'split_trial'
                selection_handler = _CharSeriesSelector(graph, characters)

        #-- Self correction
        elif event in ('x', 'X', 'set_extending_chars', 'ס'):
            if current_command is None:
                instructions.Update(
                    'Select 2 characters to connect as extending, or 1 char to un-extend. ENTER=confirm, ESC=abort'
                )
                current_command = 'set_extending_chars'
                selection_handler = _CharSelectorAnyPair(graph, characters)

        # -- Show Self correction
        elif event == 'show_extending':
            app_config['show_extending'] = values['show_extending']
            window.Close()
            return 'rerun', characters, None

        elif event in ('d', 'D', 'delete_stroke', 68, 'ג'):
            if current_command is None:
                instructions.Update(
                    'Select a stroke to delete. ENTER=confirm, ESC=abort')
                current_command = 'delete_stroke'
                selection_handler = _SingleStrokeSelector(graph, strokes)

        elif event == 'enter_response':
            response = get_valid_user_response(response,
                                               on_paper_chars,
                                               trial.stimulus,
                                               get_if_already_exists=True)
            window.Close()
            return 'rerun', characters, response

        #-- Mouse click
        elif event == 'graph':
            if selection_handler is not None:
                selection_handler.clicked(values)

        #-- ENTER clicked: end the currently-running command

        elif current_command is not None and not isinstance(
                event, int) and len(event) == 1 and ord(event) == 13:
            if current_command == 'split_char':
                characters = manip.split_character(
                    characters, selection_handler.selected_char,
                    selection_handler.selected_stroke)
                window.Close()
                return 'continue', characters, None

            elif current_command == 'merge_chars':
                characters = manip.merge_characters(characters,
                                                    selection_handler.selected)
                window.Close()
                return 'continue', characters, None

            elif current_command == 'split_stroke':
                if selection_handler.selected is None:
                    return 'continue', characters, None
                window.Close()
                return 'split_stroke', characters, selection_handler.selected

            elif current_command == 'split_trial':
                if selection_handler.selected is None:
                    return 'continue', characters, None
                chars1, chars2 = manip.split_into_2_trials(
                    characters, selection_handler.selected)
                window.Close()
                return 'split_trial', chars1, chars2

            elif current_command == 'set_extending_chars':
                if len(selection_handler.selected_chars) == 0:
                    return 'continue', characters, None
                _set_extending_characters(characters, selection_handler)
                window.Close()
                return 'rerun', characters, None

            elif current_command == 'delete_stroke':
                window.Close()
                try:
                    characters, err_msg = manip.delete_stroke(
                        characters, selection_handler)
                    if err_msg is not None:
                        messagebox.showerror('Invalid deletion attempt',
                                             err_msg)
                    return 'rerun', characters, None
                except Exception as e:
                    messagebox.showerror(
                        'Error in WEncoder',
                        'Error when trying to delete a character: {}'.format(
                            e))
                    return 'rerun', characters, None

            else:
                messagebox.showerror('Error in WEncoder',
                                     'General error (ENC-GEN-01)\nQuitting')
                return 'quit', None, None

        #-- ESC clicked: cancel the currently-running command
        #elif len(event) == 1 and ord(event) == 27:                         #Original line!!!

        else:
            if isinstance(event, str) and len(event) == 1:
                print("Clicked [{}] (#{})".format(event, ord(event)))
            else:
                print("Clicked [{}]".format(event))
            instructions.Update('UNKNOWN COMMAND')

        if current_command is not None and (
                event == 27 or
            (isinstance(event, str) and len(event) == 1 and ord(event) == 27)):
            cleanup_selection_handler = True

        if cleanup_selection_handler:
            instructions.Update('')
            current_command = None
            #if selection_handler is not None:
            selection_handler.cleanup()
            selection_handler = None