Exemple #1
0
    def str_from_md(md_lines):
        st = StepString()
        md_part = []

        WRDs = OneOrMore(WRD)
        ans_template = 'ANSWER:' + WRDs

        for line in md_lines:
            ans = None

            if line.startswith('SUBSTR:'):
                st.match_substring = bool_check('SUBSTR', line)
                continue

            if line.startswith('CASESENSE:'):
                st.case_sensitive = bool_check('CASESENSE', line)
                continue

            if line.startswith('USE_RE:'):
                st.use_re = bool_check('USE_RE', line)
                continue

            if line.startswith('ANSWER:'):
                ans = ans_template.parseString(line)
                st.pattern = ' '.join(ans[1:])

            if ans is not None:
                st.text = html(md_part)
                return st
            else:
                # continue a question or answer
                md_part.append(line)

        return st
Exemple #2
0
def from_lines(lines, task_root=None):
    """Create Step object from lines of markdown text, first line has
    ## [QUIZ] text
    return Step object
    """
    lines[0] = lines[0].strip()
    # ## text | ## long text | ## QUIZ text
    h2, stype, *a = lines[0].split()
    if h2 != '##':
        logger.error('Expected step header format "## [QUIZ] text"')
        logger.error(f"now: {lines[0]}")
        return None

    if stype == 'QUIZ':
        st = StepMultipleChoice.from_aiken(lines[1:])
    elif stype == 'NUMBER':
        st = StepNumber.num_from_md(lines[1:])
    elif stype == 'STRING':
        st = StepString.str_from_md(lines[1:])
    elif stype == 'TASK':
        st = StepTask.task_from_md(lines[1:], task_root)
    else:  # Text
        st = Step()
        st.text = html(lines)
    return st
Exemple #3
0
    def num_from_md(md_lines):
        st = StepNumber()

        class Status(Enum):
            QUESTION = 0
            ANSWER = 1

        md_part = []
        status = Status.QUESTION

        for line in md_lines:
            m = re.match(r"\s*ANSWER[:]*\s*(\d+)\s*\+?-?\s*(\d*)\s*", line)
            if m:
                exp = int(m.group(1))
                var = int(m.group(2)) if m.group(2) != '' else 0

                if status == Status.QUESTION:
                    # first answer begin, question end
                    status = Status.ANSWER
                    st.text = html(md_part)
                    st.add_answer(exp, var)
                elif status == Status.ANSWER:
                    # next variant, commit previous variant
                    st.add_answer(exp, var)
            else:
                m_answer = re.match(r'\s*END\s*', line)
                if m_answer and status == Status.ANSWER:
                    # end of question
                    return st
                else:
                    # continue a question or answer
                    md_part.append(line)

        return st
Exemple #4
0
def from_lines(lines, param_dict):
    """Create Step object from lines of markdown text, first line has
    ## [QUIZ] text
    return Step object
    """

    lines[0] = lines[0].strip()
    # ## text | ## long text | ## QUIZ text
    h2, stype, *a = lines[0].split()
    if h2 != '##':
        logger.error('Expected step header format "## [QUIZ] text"')
        logger.error(f"now: {lines[0]}")
        return None
        
    text_lines = [h2 + ' ' + ' '.join(a) + '\n' ] + lines[1:]

    if stype == 'QUIZ':
        st = StepMultipleChoice.from_aiken(text_lines)
    elif stype == 'NUMBER':
        st = StepNumber.num_from_md(text_lines)
    elif stype == 'STRING':
        st = StepString.str_from_md(text_lines)
    elif stype == 'TASK':
        st = StepTask.task_from_md(text_lines, param_dict)
    elif stype == 'TASKINLINE':
        st = StepTaskInline.task_from_md(text_lines, param_dict)
    elif stype == 'TASKTEXT':
        st = StepFreeResp.str_from_md(text_lines)
    elif stype == 'SKIP':
        st = StepSkip.str_from_md([])
    else:  # Text
        st = Step()
        st.text = html(lines)
    return st
Exemple #5
0
 def add_option(self, variant_md):
     """
     Add 1 answer variant; correct=False by default
     :param variant_md: - 1 answer variant without leading A) in markdown format
     """
     op = dict(StepMultipleChoice.OPTION_TEMPLATE)
     op['text'] = html(variant_md)
     self.options.append(op)
Exemple #6
0
    def from_aiken(md_lines):
        st = StepMultipleChoice()

        class Status(Enum):
            QUESTION = 0
            VARIANT = 1
            ANSWER = 3

        letter_seq = []  # letter sequence from aiken variant, A, B, C, D, etc
        md_part = []
        status = Status.QUESTION
        for line in md_lines:
            # Is it SHUFFLE option?
            m = re.match(r'SHUFFLE:\s*(\w+).*', line)
            if m:
                if m.group(1).lower() == 'true':
                    st.preserve_order = False
                elif m.group(1).lower() == 'false':
                    st.preserve_order = True
                else:
                    logger.warning(f'Unknown value SHUFFLE: [{m.group(1)}]')
                continue

            # variant begin by A) or A.
            m = re.match(r'(\s*)([A-Z])([.)])(.*)', line)
            if m:
                letter = m.group(2)
                # sep = m.group(3)
                txt = m.group(4) + '\n'

                if status == Status.QUESTION:
                    # first answer begin, question end
                    status = Status.VARIANT
                    st.text = html(md_part)
                elif status == Status.VARIANT:
                    # next variant, commit previous variant
                    st.add_option(md_part)
                md_part = [txt]
                letter_seq.append(letter)
            else:
                m_answer = re.match(r'\s*ANSWER[:]*\s*([A-Z, ]+)\s*', line)
                if m_answer and status == Status.VARIANT:
                    # end of question
                    st.add_option(md_part)
                    logger.debug(f'group1 = {m_answer.group(1)}')
                    letters = [s.strip() for s in m_answer.group(1).split(',')]
                    logger.debug(f'letters={letters}')
                    st.is_multiple_choice = len(letters) > 1
                    for letter in letters:
                        ind = letter_seq.index(letter)
                        st.options[ind]['is_correct'] = True
                    return st
                else:
                    # continue a question or answer
                    md_part.append(line)
Exemple #7
0
 def end_state(self, mode, text):
     print(f'end state mode={mode}')
     if mode == InputState.Statement:
         self.text = html(text)
     elif mode == InputState.TestIn :
         self.test_input = text
     elif mode == InputState.TestOut :
         self.add_sample(to_text(self.test_input), to_text(text))
         print(f'tests = {self.test_cases}')
     elif mode == InputState.Header :
         self.header = to_text(text)
     elif mode == InputState.Footer :
         self.footer = to_text(text)
     elif mode == InputState.Code :
         self.template = to_text(text)
         print(f'template = {self.template}')
     else:
         logger.warning(f'Unexpected inline task state={mode}')
Exemple #8
0
    def from_aiken(md_lines):
        st = StepMultipleChoice()

        WRDs = ZeroOrMore(WRD)

        opt_template = Char(alphas) + (Char(')') ^ Char('.')) + WRDs
        ans_template = 'ANSWER:' + OneOrMore(Char(alphas) + Char(',')[0, 1])

        class Status(Enum):
            QUESTION = 0
            VARIANT = 1
            ANSWER = 3

        letter_seq = []  # letter sequence from aiken variant, A, B, C, D, etc
        md_part = []
        status = Status.QUESTION
        for line in md_lines:
            # Is it SHUFFLE option?
            """if line.startswith('SHUFFLE:'):
                sh = ('SHUFFLE:' + WRD).parseString(line)

                if sh[1].lower() == 'true':
                    st.preserve_order = False
                elif sh[1].lower() == 'false':
                    st.preserve_order = True
                else:
                    logger.warning(f'Unknown value SHUFFLE: [{sh[1]}]')
                continue"""

            if line.startswith('SHUFFLE:'):
                st.preserve_order = not bool_check(
                    'SHUFFLE', line
                )  # единсвенная проблема в том, что при неправильном написании true или false будет автоматом ставиться true
                continue

            # variant begin by A) or A.
            if line == opt_template:
                opt = opt_template.parseString(line)

                letter = opt[0]
                txt = ' '.join(opt[2:])

                if status == Status.QUESTION:
                    # first answer begin, question end
                    status = Status.VARIANT
                    st.text = html(md_part)
                elif status == Status.VARIANT:
                    # next variant, commit previous variant
                    st.add_option(md_part)
                md_part = [txt]
                letter_seq.append(letter)
            elif line == ans_template and status == Status.VARIANT:
                # end of question
                st.add_option(md_part)

                ans = ans_template.parseString(line)
                ans_str = " ".join(ans[1:])

                logger.debug(f'group1 = {ans_str}')
                letters = [s.strip() for s in ans_str.split(',')]
                logger.debug(f'letters={letters}')
                st.is_multiple_choice = len(letters) > 1
                for letter in letters:
                    ind = letter_seq.index(letter)
                    st.options[ind]['is_correct'] = True
                return st
            else:
                # continue a question or answer
                md_part.append(line)
Exemple #9
0
 def str_from_md(md_lines):
     st = StepFreeResp()
     st.text = html(md_lines)
     return st