Пример #1
0
    def run(self):
        super(Quizly, self).run()
        print('DEBUG; Quizly.run()') if DEBUG else None

        addQuestionToDB(self)  # Not sure whether this works?
        document = self.state.document
        rel_filename, filename = document.settings.env.relfn2path(
            self.arguments[0])

        pathDepth = rel_filename.count("/")
        self.options["quizlyHomePrefix"] = "./" * pathDepth

        plstart = len(self.content)
        if self.content:
            self.options["controls"] = self.content[:plstart]

        quizly_node = QuizlyNode()
        quizly_node["runestone_options"] = self.options
        quizly_node["quizname"] = str(self.options['controls'][0])
        quizly_node["quizname"] = str.strip(quizly_node["quizname"][10:])
        quizly_node["template"] = QUIZLY_TEMPLATE.replace(
            '###', quizly_node["quizname"])

        quizly_node["source"], quizly_node[
            "line"] = self.state_machine.get_source_and_line(self.lineno)
        print('DEBUG: run() self.content = ' +
              str(self.content)) if DEBUG else None
        print('DEBUG: run() quizly_node = ' +
              str(quizly_node)) if DEBUG else None
        return [quizly_node]
    def run(self):
        """
            process the multiplechoice directive and generate html for output.

            :param self:
            :return: An MChoiceNode.
            """

        super(MChoice, self).run()

        TEMPLATE_START = '''
            <div class="%(divclass)s">
            <ul data-component="multiplechoice" data-multipleanswers="%(multipleAnswers)s" %(random)s id="%(divid)s">
            '''

        OPTION = '''
            <li data-component="answer" %(is_correct)s id="%(divid)s_opt_%(alabel)s">%(atext)s</li><li data-component="feedback" id="%(divid)s_opt_%(alabel)s">%(feedtext)s</li>
            '''

        TEMPLATE_END = '''

            </ul>
            </div>
            '''
        addQuestionToDB(self)
Пример #3
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. dragndrop:: identifier
                :feedback: Feedback that is displayed if things are incorrectly matched--is optional
                :match_1: Draggable element text|||Dropzone to be matched with text
                :match_2: Drag to Answer B|||Answer B
                :match_3: Draggable text|||Text of dropzone
                ...etc...(up to 20 matches)

                The question goes here.
        """
        addQuestionToDB(self)

        self.options['divid'] = self.arguments[0]

        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'

        self.options['question'] = source


        dndNode = DragNDropNode(self.options)
        dndNode.template_start = TEMPLATE_START
        dndNode.template_option = TEMPLATE_OPTION
        dndNode.template_end = TEMPLATE_END

        return [dndNode]
Пример #4
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. poll:: identifier
                :scale: Mode 1--Implements the "On a scale of 1 to x" type method of poll--x is provided by author
                :allowcomment: Boolean--provides comment box
                :option_1: Mode 2--Implements the "Choose one of these options" type method of poll.
                :option_2: Option 2
                :option_3: Option 3
                ...etc...(Up to 10 options in mode 2)
        """
        super(Poll, self).run()
        addQuestionToDB(self)

        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'
        self.options['question'] = source

        if not "scale" in self.options:
            self.options["scale"] = ""
        if "allowcomment" in self.options:
            self.options["comment"] = "data-comment"
        else:
            self.options["comment"] = ""

        env = self.state.document.settings.env
        self.options['divclass'] = env.config.poll_div_class

        poll_node = PollNode(self.options, rawsource=self.block_text)
        poll_node.source, poll_node.line = self.state_machine.get_source_and_line(self.lineno)
        return [poll_node]
Пример #5
0
    def run(self):
        """
            process the fillintheblank directive and generate html for output.
            :param self:
            :return:
            .. fillintheblank:: qname
            :iscode: boolean
            :casei: Case insensitive boolean
            ...
            """

        TEMPLATE_START = '''
        <p data-component="fillintheblank" data-casei="%(casei)s" id="%(divid)s">
            '''

        TEMPLATE_END = '''
        </p>
            '''

        addQuestionToDB(self)

        self.options['divid'] = self.arguments[0]

        fitbNode = FITBNode(self.options)
        fitbNode.template_start = TEMPLATE_START
        fitbNode.template_end = TEMPLATE_END

        self.state.nested_parse(self.content, self.content_offset, fitbNode)

        return [fitbNode]
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. dragndrop:: identifier
                :feedback: Feedback that is displayed if things are incorrectly matched--is optional
                :match_1: Draggable element text|||Dropzone to be matched with text
                :match_2: Drag to Answer B|||Answer B
                :match_3: Draggable text|||Text of dropzone
                ...etc...(up to 20 matches)

                The question goes here.
        """
        super(DragNDrop, self).run()
        addQuestionToDB(self)

        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'

        self.options['question'] = source
        env = self.state.document.settings.env
        self.options['divclass'] = env.config.dragndrop_div_class

        dndNode = DragNDropNode(self.options, rawsource=self.block_text)
        dndNode.source, dndNode.line = self.state_machine.get_source_and_line(self.lineno)
        dndNode.template_start = TEMPLATE_START
        dndNode.template_option = TEMPLATE_OPTION
        dndNode.template_end = TEMPLATE_END

        return [dndNode]
Пример #7
0
    def run(self):
        """
            process the fillintheblank directive and generate html for output.
            :param self:
            :return:
            .. fillintheblank:: qname
            :iscode: boolean
            :casei: Case insensitive boolean
            ...
            """

        TEMPLATE_START = '''
            <div class="course-box course-box-question">
                <div class="course-content">
        <p data-component="fillintheblank" data-casei="%(casei)s" id="%(divid)s">
            '''

        TEMPLATE_END = '''
            </p></div></div>
            '''

        addQuestionToDB(self)

        self.options['divid'] = self.arguments[0]

        fitbNode = FITBNode(self.options)
        fitbNode.template_start = TEMPLATE_START
        fitbNode.template_end = TEMPLATE_END

        self.state.nested_parse(self.content, self.content_offset, fitbNode)

        return [fitbNode]
Пример #8
0
    def run(self):
        """
        process the video directive and generate html for output.
        :param self:
        :return:
        """
        addQuestionToDB(self)

        mimeMap = {'mov':'mp4','webm':'webm', 'm4v':'m4v'}

        sources = [SOURCE % (directives.uri(line),mimeMap[line[line.rindex(".")+1:]]) for line in self.content]
        self.options['divid'] = self.arguments[0]
        if 'controls' in self.options:
            self.options['controls'] = 'controls'
        if 'loop' in self.options:
            self.options['loop'] = 'loop'
        else:
            self.options['loop'] = ''

        if 'preload' in self.options:
            self.options['preload'] = 'preload="auto"'
        else:
            self.options['preload'] = 'preload="none"'

        self.options['sources'] = "\n    ".join(sources)
        res = CODE % self.options
        if 'popup' in self.options:
            res += POPUP % self.options
        else:
            res += INLINE % self.options
        return [nodes.raw('',res , format='html')]
Пример #9
0
    def run(self):
        super(Khanex, self).run()
        print('DEBUG; Khanex.run()') if DEBUG else None

        addQuestionToDB(self)  # Not sure whether this works?
        document = self.state.document
        rel_filename, filename = document.settings.env.relfn2path(
            self.arguments[0])

        pathDepth = rel_filename.count("/")
        self.options["khanexHomePrefix"] = "./" * pathDepth

        plstart = len(self.content)
        if self.content:
            self.options["controls"] = self.content[:plstart]

        khanex_node = KhanexNode()
        khanex_node["runestone_options"] = self.options
        khanex_node["exername"] = str(self.options['controls'][0])
        khanex_node["exername"] = str.strip(khanex_node["exername"][10:])
        khanex_node["template"] = KHANEX_TEMPLATE.replace(
            '###', khanex_node["exername"])

        khanex_node["source"], khanex_node[
            "line"] = self.state_machine.get_source_and_line(self.lineno)
        return [khanex_node]
Пример #10
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. dragndrop:: identifier
                :feedback: Feedback that is displayed if things are incorrectly matched--is optional
                :match_1: Draggable element text|||Dropzone to be matched with text
                :match_2: Drag to Answer B|||Answer B
                :match_3: Draggable text|||Text of dropzone
                ...etc...(up to 20 matches)

                The question goes here.
        """
        addQuestionToDB(self)

        self.options['divid'] = self.arguments[0]

        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'

        self.options['question'] = source


        dndNode = DragNDropNode(self.options)
        dndNode.template_start = TEMPLATE_START
        dndNode.template_option = TEMPLATE_OPTION
        dndNode.template_end = TEMPLATE_END

        return [dndNode]
Пример #11
0
    def run(self):
        super(JournalDirective, self).run()
        addQuestionToDB(self)
        # Raise an error if the directive does not have contents.
        self.assert_has_content()

        self.options[
            "optional"] = "data-optional" if "optional" in self.options else ""
        self.options[
            "mathjax"] = "data-mathjax" if "mathjax" in self.options else ""

        journal_node = JournalNode(self.options, rawsource=self.block_text)
        journal_node.source, journal_node.line = self.state_machine.get_source_and_line(
            self.lineno)

        self.updateContent()

        self.state.nested_parse(self.content, self.content_offset,
                                journal_node)

        env = self.state.document.settings.env
        if self.options["optional"]:
            self.options[
                "divclass"] = env.config.shortanswer_optional_div_class
        else:
            self.options["divclass"] = env.config.shortanswer_div_class

        return [journal_node]
Пример #12
0
    def run(self):
        super(HParsonsDirective, self).run()
        addQuestionToDB(self)

        env = self.state.document.settings.env

        if "language" in self.options:
            self.options["language"] = "data-language='{}'".format(self.options["language"])
        else:
            self.options["language"] = ""

        if "reuse" in self.options:
            self.options['reuse'] = ' data-reuse="true"'
        else:
            self.options['reuse'] = ''

        if "randomize" in self.options:
            self.options['randomize'] = ' data-randomize="true"'
        else:
            self.options['randomize'] = ''

        if "blockanswer" in self.options:
            self.options["blockanswer"] = "data-blockanswer='{}'".format(self.options["blockanswer"])
        else:
            self.options['blockanswer'] = ''

        explain_text = None
        if self.content:
            if "~~~~" in self.content:
                idx = self.content.index("~~~~")
                explain_text = self.content[:idx]
                self.content = self.content[idx + 1 :]
            source = "\n".join(self.content)
        else:
            source = "\n"

        self.explain_text = explain_text or ["Not an Exercise"]

        self.options["initialsetting"] = source

        # SQL Options
        if "dburl" in self.options:
            self.options["dburl"] = "data-dburl='{}'".format(self.options["dburl"])
        else:
            self.options["dburl"] = ""

        course_name = env.config.html_context["course_id"]
        divid = self.options["divid"]

        hpnode = HParsonsNode()
        hpnode["runestone_options"] = self.options
        hpnode["source"], hpnode["line"] = self.state_machine.get_source_and_line(self.lineno)
        self.add_name(hpnode)  # make this divid available as a target for :ref:

        maybeAddToAssignment(self)
        if explain_text:
            self.updateContent()
            self.state.nested_parse(explain_text, self.content_offset, hpnode)

        return [hpnode]
Пример #13
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. poll:: identifier
                :scale: Mode 1--Implements the "On a scale of 1 to x" type method of poll--x is provided by author
                :allowcomment: Boolean--provides comment box
                :option_1: Mode 2--Implements the "Choose one of these options" type method of poll.
                :option_2: Option 2
                :option_3: Option 3
                ...etc...(Up to 10 options in mode 2)
        """
        addQuestionToDB(self)

        self.options['divid'] = self.arguments[0]
        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'
        self.options['question'] = source

        if not "scale" in self.options:
            self.options["scale"] = ""
        if "allowcomment" in self.options:
            self.options["comment"] = "data-comment"
        else:
            self.options["comment"] = ""


        return [PollNode(self.options)]
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. dragndrop:: identifier
                :feedback: Feedback that is displayed if things are incorrectly matched--is optional
                :match_1: Draggable element text|||Dropzone to be matched with text
                :match_2: Drag to Answer B|||Answer B
                :match_3: Draggable text|||Text of dropzone
                ...etc...(up to 20 matches)

                The question goes here.
        """
        super(DragNDrop, self).run()
        addQuestionToDB(self)

        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'

        self.options['question'] = source
        env = self.state.document.settings.env
        self.options['divclass'] = env.config.dragndrop_div_class

        dndNode = DragNDropNode(self.options, rawsource=self.block_text)
        dndNode.source, dndNode.line = self.state_machine.get_source_and_line(
            self.lineno)
        dndNode.template_start = TEMPLATE_START
        dndNode.template_option = TEMPLATE_OPTION
        dndNode.template_end = TEMPLATE_END

        return [dndNode]
Пример #15
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. poll:: identifier
                :scale: Mode 1--Implements the "On a scale of 1 to x" type method of poll--x is provided by author
                :allowcomment: Boolean--provides comment box
                :option_1: Mode 2--Implements the "Choose one of these options" type method of poll.
                :option_2: Option 2
                :option_3: Option 3
                ...etc...(Up to 10 options in mode 2)
        """
        addQuestionToDB(self)

        self.options['divid'] = self.arguments[0]
        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'
        self.options['question'] = source

        if not "scale" in self.options:
            self.options["scale"] = ""
        if "allowcomment" in self.options:
            self.options["comment"] = "data-comment"
        else:
            self.options["comment"] = ""

        poll_node = PollNode(self.options, rawsource=self.block_text)
        poll_node.source, poll_node.line = self.state_machine.get_source_and_line(
            self.lineno)
        return [poll_node]
Пример #16
0
    def run(self):
        """
        process the video directive and generate html for output.
        :param self:
        :return:
        """
        addQuestionToDB(self)

        mimeMap = {'mov': 'mp4', 'webm': 'webm', 'm4v': 'm4v'}

        sources = [
            SOURCE %
            (directives.uri(line), mimeMap[line[line.rindex(".") + 1:]])
            for line in self.content
        ]
        self.options['divid'] = self.arguments[0]
        if 'controls' in self.options:
            self.options['controls'] = 'controls'
        if 'loop' in self.options:
            self.options['loop'] = 'loop'
        else:
            self.options['loop'] = ''

        if 'preload' in self.options:
            self.options['preload'] = 'preload="auto"'
        else:
            self.options['preload'] = 'preload="none"'

        self.options['sources'] = "\n    ".join(sources)
        res = CODE % self.options
        if 'popup' in self.options:
            res += POPUP % self.options
        else:
            res += INLINE % self.options
        return [nodes.raw('', res, format='html')]
Пример #17
0
    def run(self):

        addQuestionToDB(self)

        self.JS_VARNAME = ""
        self.JS_VARVAL = ""

        def raw_dict(input_code, output_trace):
            ret = dict(code=input_code, trace=output_trace)
            return ret

        def js_var_finalizer(input_code, output_trace):
            global JS_VARNAME
            ret = dict(code=input_code, trace=output_trace)
            json_output = json.dumps(ret, indent=None)
            return "var %s = %s;" % (self.JS_VARNAME, json_output)

        self.options['divid'] = self.arguments[0]
        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'

        CUMULATIVE_MODE = False
        self.JS_VARNAME = self.options['divid'] + '_trace'
        if 'showoutput' not in self.options:
            self.options['embedded'] = 'true'  # to set embeddedmode to true
        else:
            self.options['embedded'] = 'false'

        if 'python' not in self.options:
            if six.PY2:
                self.options['python'] = 'py2'
            else:
                self.options['python'] = 'py3'

        if 'question' in self.options:
            curTrace = exec_script_str_local(source, None, CUMULATIVE_MODE, None, raw_dict)
            self.inject_questions(curTrace)
            json_output = json.dumps(curTrace, indent=None)
            self.options['tracedata'] = "var %s = %s;" % (self.JS_VARNAME, json_output)
        else:
            self.options['tracedata'] = exec_script_str_local(source, None,
                                                              CUMULATIVE_MODE,
                                                              None, js_var_finalizer)

        res = VIS
        if 'caption' not in self.options:
            self.options['caption'] = ''
        if 'question' in self.options:
            res += QUESTION
        if 'tracedata' in self.options:
            res += DATA
        else:
            res += '</div>'
        addHTMLToDB(self.options['divid'], self.options['basecourse'], res % self.options)
        raw_node = nodes.raw(self.block_text, res % self.options, format='html')
        raw_node.source, raw_node.line = self.state_machine.get_source_and_line(self.lineno)
        return [raw_node]
    def run(self):
        """
        All prerequisite information that should be displayed above the directive,
        such as variable declaration, are separated from the step strings by "-----".

        The step animations follow the "-----" and are written one per line. Use
        "{{" and "}}" braces to surround the part of the line that should be replaced,
        followed by the replacement text also in "{{" and "}}". If you would like to add
        a comment that will appear in a div beside the animation, denote that at the end
        of the step where you would like it to appear with "##".

    Example:

    .. showeval:: showEval_0
       :trace_mode: false

       eggs = ['dogs', 'cats', 'moose']
       ~~~~

       ''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
       {{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)  ##I want to put a comment here!
       {{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
       'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
       {{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}

        """

        # Raise an error if the directive does not have contents.
        super(ShowEval, self).run()
        addQuestionToDB(self)

        self.options["trace_mode"] = self.options["trace_mode"].lower()
        self.options["preReqLines"] = ""
        self.options["steps"] = []

        env = self.state.document.settings.env
        self.options["divclass"] = env.config.showeval_div_class

        is_dynamic = env.config.html_context.get("dynamic_pages", False)
        is_dynamic = True if is_dynamic == "True" else False
        step = False
        count = 0
        for line in self.content:
            if step == True:
                if line != "":
                    if is_dynamic:
                        esc_line = str(line).replace("{", r"\{")
                    else:
                        esc_line = str(line)
                    self.options["steps"].append(esc_line)
            elif "~~~~" in line:
                step = True
            else:
                self.options["preReqLines"] += line + "<br />\n"

        res = CODE % self.options

        addHTMLToDB(self.options["divid"], self.options["basecourse"], res)
        return [nodes.raw(self.block_text, res, format="html")]
Пример #19
0
    def run(self):
        if not self.options.get("start"):
            self.options["start"] = 0

        if not self.options.get("end"):
            self.options["end"] = -1

        raw_node = super(Youtube, self).run()
        addQuestionToDB(self)
        return raw_node
 def run(self):
     if not self.options.get('start'):
         self.options['start'] = 0
         
     if not self.options.get('end'):
         self.options['end'] = -1
         
     raw_node = super(Youtube, self).run()
     addQuestionToDB(self)
     return raw_node
Пример #21
0
    def run(self):
        if not self.options.get('start'):
            self.options['start'] = 0

        if not self.options.get('end'):
            self.options['end'] = -1

        raw_node = super(Youtube, self).run()
        addQuestionToDB(self)
        return raw_node
Пример #22
0
    def run(self):
        """
        All prerequisite information that should be displayed above the directive,
        such as variable declaration, are separated from the step strings by "-----".

        The step animations follow the "-----" and are written one per line. Use
        "{{" and "}}" braces to surround the part of the line that should be replaced,
        followed by the replacement text also in "{{" and "}}". If you would like to add
        a comment that will appear in a div beside the animation, denote that at the end
        of the step where you would like it to appear with "##".

    Example:

    .. showeval:: showEval_0
       :trace_mode: false

       eggs = ['dogs', 'cats', 'moose']
       ~~~~

       ''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
       {{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)  ##I want to put a comment here!
       {{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
       'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
       {{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}

        """

        # Raise an error if the directive does not have contents.
        super(ShowEval, self).run()
        addQuestionToDB(self)

        self.options['trace_mode'] = self.options['trace_mode'].lower()
        self.options['preReqLines'] = ''
        self.options['steps'] = []

        env = self.state.document.settings.env
        self.options['divclass'] = env.config.showeval_div_class

        step = False
        count = 0
        for line in self.content:
            if step == True:
                if line != '':
                    self.options['steps'].append(str(line))
            elif '~~~~' in line:
                step = True
            else:
                self.options['preReqLines'] += line + '<br />\n'


        res = (CODE + SCRIPT) % self.options

        addHTMLToDB(self.options['divid'], self.options['basecourse'], res)
        return [nodes.raw(self.block_text, res, format='html')]
Пример #23
0
    def run(self):

        addQuestionToDB(self)

        self.JS_VARNAME = ""
        self.JS_VARVAL = ""

        def raw_dict(input_code, output_trace):
            ret = dict(code=input_code, trace=output_trace)
            return ret

        def js_var_finalizer(input_code, output_trace):
            global JS_VARNAME
            ret = dict(code=input_code, trace=output_trace)
            json_output = json.dumps(ret, indent=None)
            return "var %s = %s;" % (self.JS_VARNAME, json_output)

        self.options['divid'] = self.arguments[0]
        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'

        CUMULATIVE_MODE = False
        self.JS_VARNAME = self.options['divid'] + '_trace'
        if 'showoutput' not in self.options:
            self.options['embedded'] = 'true'  # to set embeddedmode to true
        else:
            self.options['embedded'] = 'false'

        if 'python' not in self.options:
            if six.PY2:
                self.options['python'] = 'py2'
            else:
                self.options['python'] = 'py3'

        if 'question' in self.options:
            curTrace = exec_script_str_local(source, None, CUMULATIVE_MODE, None, raw_dict)
            self.inject_questions(curTrace)
            json_output = json.dumps(curTrace, indent=None)
            self.options['tracedata'] = "var %s = %s;" % (self.JS_VARNAME, json_output)
        else:
            self.options['tracedata'] = exec_script_str_local(source, None,
                                                              CUMULATIVE_MODE,
                                                              None, js_var_finalizer)

        res = VIS
        if 'caption' not in self.options:
            self.options['caption'] = ''
        if 'question' in self.options:
            res += QUESTION
        if 'tracedata' in self.options:
            res += DATA
        return [nodes.raw('', res % self.options, format='html')]
    def run(self):
        """
        All prerequisite information that should be displayed above the directive,
        such as variable declaration, are separated from the step strings by "-----".

        The step animations follow the "-----" and are written one per line. Use
        "{{" and "}}" braces to surround the part of the line that should be replaced,
        followed by the replacement text also in "{{" and "}}". If you would like to add
        a comment that will appear in a div beside the animation, denote that at the end
        of the step where you would like it to appear with "##".

    Example:

    .. showeval:: showEval_0
       :trace_mode: false

       eggs = ['dogs', 'cats', 'moose']
       ~~~~

       ''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
       {{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)  ##I want to put a comment here!
       {{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
       'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
       {{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}

        """

        # Raise an error if the directive does not have contents.
        super(ShowEval, self).run()
        addQuestionToDB(self)

        self.options['trace_mode'] = self.options['trace_mode'].lower()
        self.options['preReqLines'] = ''
        self.options['steps'] = []

        env = self.state.document.settings.env
        self.options['divclass'] = env.config.showeval_div_class

        step = False
        count = 0
        for line in self.content:
            if step == True:
                if line != '':
                    self.options['steps'].append(str(line))
            elif '~~~~' in line:
                step = True
            else:
                self.options['preReqLines'] += line + '<br />\n'

        res = (CODE + SCRIPT) % self.options

        addHTMLToDB(self.options['divid'], self.options['basecourse'], res)
        return [nodes.raw(self.block_text, res, format='html')]
Пример #25
0
    def run(self):
        """
            process the clickablearea directive and generate html for output.
            :param self:
            :return:
            .. clickablearea:: identifier
                :question: Question text
                :feedback: Optional feedback for incorrect answer
                :iscode: Boolean that if present will put the content into a <pre>
                :table: Boolean that indicates that the content is a table.
                :correct: An array of the indices of the correct elements, separated by semicolons--if this is a table, each item in the array is a tuple
                with the first number being the row and the second number being the column--use a column number of 0 to make the whole row correct (ex: 1,2;3,0 makes the 2nd data cell in the first row correct as well as the entire 3rd row)
                :incorrect: An array of the indices of the incorrect elements--same format as the correct elements.
                --Content--
        """
        super(ClickableArea, self).run()
        self.explain_text = [self.options["question"]]
        addQuestionToDB(self)

        self.assert_has_content()
        if "iscode" in self.options:
            source = "\n".join(self.content)
            source = source.replace(":click-correct:", "<span data-correct>")
            source = source.replace(":click-incorrect:",
                                    "<span data-incorrect>")
            source = source.replace(":endclick:", "</span>")
            source = "<pre>" + source + "</pre>"
            self.options["clickcode"] = source
            self.options["raw_source"] = self.content
        else:
            self.options["clickcode"] = ""
        clickNode = ClickableAreaNode()
        clickNode["runestone_options"] = self.options
        clickNode["source"], clickNode[
            "line"] = self.state_machine.get_source_and_line(self.lineno)
        clickNode["template_start"] = TEMPLATE

        if "table" in self.options:
            self.options["table"] = "data-table"
        else:
            self.options["table"] = ""

        if "iscode" not in self.options:
            self.state.nested_parse(self.content, self.content_offset,
                                    clickNode)

        env = self.state.document.settings.env
        self.options["divclass"] = env.config.clickable_div_class

        maybeAddToAssignment(self)

        return [clickNode]
Пример #26
0
    def run(self):
        # Raise an error if the directive does not have contents.

        addQuestionToDB(self)

        self.assert_has_content()

        self.options['optional'] = 'data-optional' if 'optional' in self.options else ''
        self.options['divid'] = self.arguments[0]
        self.options['content'] = "<p>".join(self.content)
        self.options['qnum'] = self.getNumber()
        journal_node = JournalNode(self.options)

        return [journal_node]
Пример #27
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. mchoice:: qname
            :multiple_answers: boolean
            :random: boolean
            :answer_a: possible answer  -- what follows _ is label
            :answer_b: possible answer
            ...
            :answer_e: possible answer
            :correct: letter of correct answer or list of correct answer letters (in case of multiple answers)
            :feedback_a: displayed if a is picked
            :feedback_b: displayed if b is picked
            :feedback_c: displayed if c is picked
            :feedback_d: displayed if d is picked
            :feedback_e: displayed if e is picked

            Question text
            ...
            """

        TEMPLATE_START = '''
            <div id="%(divid)s" class="course-box course-box-question">
                <div class="course-content">
                    <p>
            <ul data-component="multiplechoice" data-multipleanswers="%(multipleAnswers)s" %(random)s id="%(divid)s">
            '''

        OPTION = '''
            <li data-component="answer" %(is_correct)s id="%(divid)s_opt_%(alabel)s">%(atext)s</li><li data-component="feedback" id="%(divid)s_opt_%(alabel)s">%(feedtext)s</li>
            '''

        TEMPLATE_END = '''

            </ul>
            </p></div></div>
            '''
        addQuestionToDB(self)
        super(MChoice, self).run()

        mcNode = MChoiceNode(self.options)
        mcNode.template_start = TEMPLATE_START
        mcNode.template_option = OPTION
        mcNode.template_end = TEMPLATE_END

        self.state.nested_parse(self.content, self.content_offset, mcNode)
        return [mcNode]
Пример #28
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. mchoice:: qname
            :multiple_answers: boolean
            :random: boolean
            :answer_a: possible answer  -- what follows _ is label
            :answer_b: possible answer
            ...
            :answer_e: possible answer
            :correct: letter of correct answer or list of correct answer letters (in case of multiple answers)
            :feedback_a: displayed if a is picked
            :feedback_b: displayed if b is picked
            :feedback_c: displayed if c is picked
            :feedback_d: displayed if d is picked
            :feedback_e: displayed if e is picked

            Question text
            ...
            """

        TEMPLATE_START = '''
            <ul data-component="multiplechoice" data-multipleanswers="%(multipleAnswers)s" %(random)s id="%(divid)s">
            '''

        OPTION = '''
            <li data-component="answer" %(is_correct)s id="%(divid)s_opt_%(alabel)s">%(atext)s</li><li data-component="feedback" id="%(divid)s_opt_%(alabel)s">%(feedtext)s</li>
            '''


        TEMPLATE_END = '''

            </ul>
            '''
        addQuestionToDB(self)
        super(MChoice,self).run()




        mcNode = MChoiceNode(self.options)
        mcNode.template_start = TEMPLATE_START
        mcNode.template_option = OPTION
        mcNode.template_end = TEMPLATE_END

        self.state.nested_parse(self.content, self.content_offset, mcNode)
        return [mcNode]
Пример #29
0
    def run(self):
        super(ExternalDirective, self).run()
        addQuestionToDB(self)

        self.assert_has_content()  # make sure activity has something in it

        self.options['name'] = self.arguments[0].strip()

        external_node = ExternalNode(self.options, rawsource=self.block_text)
        external_node.source, external_node.line = self.state_machine.get_source_and_line(self.lineno)
        self.add_name(external_node)

        self.state.nested_parse(self.content, self.content_offset, external_node)

        return [external_node]
Пример #30
0
    def run(self):
        super(JournalDirective, self).run()
        addQuestionToDB(self)
        # Raise an error if the directive does not have contents.
        self.assert_has_content()

        self.options[
            'optional'] = 'data-optional' if 'optional' in self.options else ''
        self.options['content'] = "<p>".join(self.content)
        self.options['qnum'] = self.getNumber()
        journal_node = JournalNode(self.options, rawsource=self.block_text)
        journal_node.source, journal_node.line = self.state_machine.get_source_and_line(
            self.lineno)

        return [journal_node]
Пример #31
0
    def run(self):
        # Raise an error if the directive does not have contents.

        addQuestionToDB(self)

        self.assert_has_content()

        self.options[
            'optional'] = 'data-optional' if 'optional' in self.options else ''
        self.options['divid'] = self.arguments[0]
        self.options['content'] = "<p>".join(self.content)
        self.options['qnum'] = self.getNumber()
        journal_node = JournalNode(self.options)

        return [journal_node]
Пример #32
0
    def run(self):
        """
        All prerequisite information that should be displayed above the directive,
        such as variable declaration, are separated from the step strings by "-----".

        The step animations follow the "-----" and are written one per line. Use
        "{{" and "}}" braces to surround the part of the line that should be replaced,
        followed by the replacement text also in "{{" and "}}".

    Example:

    .. showeval:: showEval_0
       :trace_mode: false

       eggs = ['dogs', 'cats', 'moose']
       ~~~~

       ''.join({{eggs}}{{['dogs', 'cats', 'moose']}}).upper().join(eggs)
       {{''.join(['dogs', 'cats', 'moose'])}}{{'dogscatsmoose'}}.upper().join(eggs)
       {{'dogscatsmoose'.upper()}}{{'DOGSCATSMOOSE'}}.join(eggs)
       'DOGSCATSMOOSE'.join({{eggs}}{{['dogs', 'cats', 'moose']}})
       {{'DOGSCATSMOOSE'.join(['dogs', 'cats', 'moose'])}}{{'dogsDOGSCATSMOOSEcatsDOGSCATSMOOSEmoose'}}

        """

        addQuestionToDB(self)

        self.options['divid'] = self.arguments[0]
        self.options['trace_mode'] = self.options['trace_mode'].lower()
        self.options['preReqLines'] = ''
        self.options['steps'] = []

        step = False
        count = 0
        for line in self.content:
            if step == True:
                if line != '':
                    self.options['steps'].append(str(line))
            elif '~~~~' in line:
                step = True
            else:
                self.options['preReqLines'] += line + '<br />\n'

        res = (CODE + SCRIPT) % self.options

        addHTMLToDB(self.options['divid'], self.options['basecourse'], res)
        return [nodes.raw(self.block_text, res, format='html')]
Пример #33
0
    def run(self):
        """
            process the clickablearea directive and generate html for output.
            :param self:
            :return:
            .. clickablearea:: identifier
                :question: Question text
                :feedback: Optional feedback for incorrect answer
                :iscode: Boolean that if present will put the content into a <pre>
                :table: Boolean that indicates that the content is a table.
                :correct: An array of the indices of the correct elements, separated by semicolons--if this is a table, each item in the array is a tuple
                with the first number being the row and the second number being the column--use a column number of 0 to make the whole row correct (ex: 1,2;3,0 makes the 2nd data cell in the first row correct as well as the entire 3rd row)
                :incorrect: An array of the indices of the incorrect elements--same format as the correct elements.
                --Content--
        """
        super(ClickableArea, self).run()
        addQuestionToDB(self)

        self.assert_has_content()
        if "iscode" in self.options:
            source = "\n".join(self.content)
            source = source.replace(":click-correct:", "<span data-correct>")
            source = source.replace(":click-incorrect:", "<span data-incorrect>")
            source = source.replace(":endclick:", "</span>")
            source = "<pre>" + source + "</pre>"
            self.options['clickcode'] = source
        else:
            self.options['clickcode'] = ''
        clickNode = ClickableAreaNode(self.options, rawsource=self.block_text)
        clickNode.source, clickNode.line = self.state_machine.get_source_and_line(self.lineno)
        clickNode.template_start = TEMPLATE

        if "table" in self.options:
            self.options["table"] = "data-table"
        else:
            self.options["table"] = ""

        if "iscode" not in self.options:
            self.state.nested_parse(self.content, self.content_offset, clickNode)

        
        env = self.state.document.settings.env
        self.options['divclass'] = env.config.clickable_div_class

        return [clickNode]
Пример #34
0
    def run(self):
        super(JournalDirective, self).run()
        addQuestionToDB(self)
        # Raise an error if the directive does not have contents.
        self.assert_has_content()

        self.options['optional'] = 'data-optional' if 'optional' in self.options else ''
        self.options['content'] = "<p>".join(self.content)
        journal_node = JournalNode(self.options, rawsource=self.block_text)
        journal_node.source, journal_node.line = self.state_machine.get_source_and_line(self.lineno)

        env = self.state.document.settings.env
        if self.options['optional']:
            self.options['divclass'] = env.config.shortanswer_optional_div_class
        else:
            self.options['divclass'] = env.config.shortanswer_div_class

        return [journal_node]
Пример #35
0
    def run(self):
        addQuestionToDB(self)

        self.assert_has_content()  # make sure activity has something in it
        self.options['divid'] = self.arguments[0]
        self.options[
            'basecourse'] = self.state.document.settings.env.config.html_context.get(
                'basecourse', "unknown")

        self.options['name'] = self.arguments[0].strip()

        external_node = ExternalNode(self.options)
        self.add_name(external_node)

        self.state.nested_parse(self.content, self.content_offset,
                                external_node)

        return [external_node]
Пример #36
0
    def run(self):
        """
            process the clickablearea directive and generate html for output.
            :param self:
            :return:
            .. clickablearea:: identifier
                :question: Question text
                :feedback: Optional feedback for incorrect answer
                :iscode: Boolean that if present will put the content into a <pre>
                :table: Boolean that indicates that the content is a table.
                :correct: An array of the indices of the correct elements, separated by semicolons--if this is a table, each item in the array is a tuple
                with the first number being the row and the second number being the column--use a column number of 0 to make the whole row correct (ex: 1,2;3,0 makes the 2nd data cell in the first row correct as well as the entire 3rd row)
                :incorrect: An array of the indices of the incorrect elements--same format as the correct elements.
                --Content--
        """
        addQuestionToDB(self)

        self.assert_has_content()
        self.options['divid'] = self.arguments[0]
        if "iscode" in self.options:
            source = "\n".join(self.content)
            source = source.replace(":click-correct:", "<span data-correct>")
            source = source.replace(":click-incorrect:",
                                    "<span data-incorrect>")
            source = source.replace(":endclick:", "</span>")
            source = "<pre>" + source + "</pre>"
            self.options['clickcode'] = source
        else:
            self.options['clickcode'] = ''
        clickNode = ClickableAreaNode(self.options, rawsource=self.block_text)
        clickNode.source, clickNode.line = self.state_machine.get_source_and_line(
            self.lineno)
        clickNode.template_start = TEMPLATE

        if "table" in self.options:
            self.options["table"] = "data-table"
        else:
            self.options["table"] = ""

        if "iscode" not in self.options:
            self.state.nested_parse(self.content, self.content_offset,
                                    clickNode)

        return [clickNode]
Пример #37
0
    def run(self):
        super(JournalDirective, self).run()
        addQuestionToDB(self)
        # Raise an error if the directive does not have contents.
        self.assert_has_content()

        self.options[
            'optional'] = 'data-optional' if 'optional' in self.options else ''
        self.options['content'] = "<p>".join(self.content)
        journal_node = JournalNode(self.options, rawsource=self.block_text)
        journal_node.source, journal_node.line = self.state_machine.get_source_and_line(
            self.lineno)

        env = self.state.document.settings.env
        if self.options['optional']:
            self.options[
                'divclass'] = env.config.shortanswer_optional_div_class
        else:
            self.options['divclass'] = env.config.shortanswer_div_class

        return [journal_node]
Пример #38
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.
            :param self:
            :return:
            .. poll:: id
                :scale: <X>  Setting the scale creates an "On a scale of 1 to <X>" type of question
                :allowcomment: Boolean--provides comment box
                :option_1: Providing Question text for each option creates a "Choose one of these options" type of poll.
                :option_2: Option 2
                :option_3: Option 3    ...etc...(Up to 10 options in mode 2)
                :results: One of all, instructor, superuser - who should see results?
        """
        super(Poll, self).run()
        addQuestionToDB(self)

        if self.content:
            source = "\n".join(self.content)
        else:
            source = "\n"
        self.options["question"] = source

        if not "scale" in self.options:
            self.options["scale"] = ""
        if "allowcomment" in self.options:
            self.options["comment"] = "data-comment"
        else:
            self.options["comment"] = ""

        if not "results" in self.options:
            self.options["results"] = "instructor"

        env = self.state.document.settings.env
        self.options["divclass"] = env.config.poll_div_class

        poll_node = PollNode()
        poll_node["runestone_options"] = self.options
        poll_node["source"], poll_node[
            "line"] = self.state_machine.get_source_and_line(self.lineno)
        return [poll_node]
Пример #39
0
    def run(self):
        super(Khanex, self).run()
        print('DEBUG; Khanex.run()') if DEBUG else None

        addQuestionToDB(self)   # Not sure whether this works?
        document = self.state.document
        rel_filename, filename = document.settings.env.relfn2path(self.arguments[0])

        pathDepth = rel_filename.count("/")
        self.options["khanexHomePrefix"] = "./" * pathDepth

        plstart = len(self.content)
        if self.content:
            self.options["controls"] = self.content[:plstart]

        khanex_node = KhanexNode(self.options, rawsource=self.block_text)
        khanex_node.source, khanex_node.line = self.state_machine.get_source_and_line(
            self.lineno
        )
        print('DEBUG: run() self.content = ' + str(self.content)) if DEBUG else None
        print('DEBUG: run() khanex_node = ' + str(khanex_node)) if DEBUG else None
        return [khanex_node]
Пример #40
0
    def run(self):
        """
        process the video directive and generate html for output.
        :param self:
        :return:
        """
        super(Video, self).run()
        addQuestionToDB(self)

        mimeMap = {"mov": "mp4", "webm": "webm", "m4v": "m4v"}

        sources = [
            SOURCE %
            (directives.uri(line), mimeMap[line[line.rindex(".") + 1:]])
            for line in self.content
        ]
        if "controls" in self.options:
            self.options["controls"] = "controls"
        if "loop" in self.options:
            self.options["loop"] = "loop"
        else:
            self.options["loop"] = ""

        if "preload" in self.options:
            self.options["preload"] = 'preload="auto"'
        else:
            self.options["preload"] = 'preload="none"'

        self.options["sources"] = "\n    ".join(sources)
        res = CODE % self.options
        if "popup" in self.options:
            res += POPUP % self.options
        else:
            res += INLINE % self.options

        addHTMLToDB(self.options["divid"], self.options["basecourse"], res)
        return [nodes.raw(self.block_text, res, format="html")]
Пример #41
0
    def run(self):
        """
            process the fillintheblank directive and generate html for output.
            :param self:
            :return: Nodes resulting from this directive.
            ...
            """

        super(FillInTheBlank, self).run()

        TEMPLATE_START = '''
        <div class="%(divclass)s">
        <div data-component="fillintheblank" id="%(divid)s">
            '''

        TEMPLATE_END = '''
        <script type="application/json">
            %(json)s
        </script>

        </div>
        </div>
            '''

        addQuestionToDB(self)

        fitbNode = FITBNode(self.options, rawsource=self.block_text)
        fitbNode.source, fitbNode.line = self.state_machine.get_source_and_line(self.lineno)
        fitbNode.template_start = TEMPLATE_START
        fitbNode.template_end = TEMPLATE_END

        self.updateContent()

        self.state.nested_parse(self.content, self.content_offset, fitbNode)
        env = self.state.document.settings.env
        self.options['divclass'] = env.config.fitb_div_class

        # Expected _`structure`, with assigned variable names and transformations made:
        #
        # .. code-block::
        #   :number-lines:
        #
        #   fitbNode = FITBNode()
        #       Item 1 of problem text
        #       ...
        #       Item n of problem text
        #       feedback_bullet_list = bullet_list()  <-- The last element in fitbNode.
        #           feedback_list_item = list_item()   <-- Feedback for the first blank.
        #               feedback_field_list = field_list()
        #                   feedback_field = field()
        #                       feedback_field_name = field_name()  <-- Contains an answer.
        #                       feedback_field_body = field_body()  <-- Contains feedback for this answer.
        #                   feedback_field = field()  <-- Another answer/feedback pair.
        #           feedback_list_item = bullet_item()  <-- Feedback for the second blank.
        #               ...etc. ...
        #
        # This becomes a data structure:
        #
        # .. code-block::
        #   :number-lines:
        #
        #   self.feedbackArray = [
        #       [   # blankArray
        #           { # blankFeedbackDict: feedback 1
        #               "regex" : feedback_field_name   # (An answer, as a regex;
        #               "regexFlags" : "x"              # "i" if ``:casei:`` was specified, otherwise "".) OR
        #               "number" : [min, max]           # a range of correct numeric answers.
        #               "feedback": feedback_field_body (after being rendered as HTML)  # Provides feedback for this answer.
        #           },
        #           { # Feedback 2
        #               Same as above.
        #           }
        #       ],
        #       [  # Blank 2, same as above.
        #       ]
        #   ]
        #
        # ...and a transformed node structure:
        #
        # .. code-block::
        #   :number-lines:
        #
        #   fitbNode = FITBNode()
        #       Item 1 of problem text
        #       ...
        #       Item n of problem text
        #       FITBFeedbackNode(), which contains all the nodes in blank 1's feedback_field_body
        #       ...
        #       FITBFeedbackNode(), which contains all the nodes in blank n's feedback_field_body
        #
        self.assert_has_content()
        feedback_bullet_list = fitbNode.pop()
        if not isinstance(feedback_bullet_list, nodes.bullet_list):
            raise self.error('On line {}, the last item in a fill-in-the-blank question must be a bulleted list.'.format(get_node_line(feedback_bullet_list)))
        for feedback_list_item in feedback_bullet_list.children:
            assert isinstance(feedback_list_item, nodes.list_item)
            feedback_field_list = feedback_list_item[0]
            if len(feedback_list_item) != 1 or not isinstance(feedback_field_list, nodes.field_list):
                raise self.error('On line {}, each list item in a fill-in-the-blank problems must contain only one item, a field list.'.format(get_node_line(feedback_list_item)))
            blankArray = []
            for feedback_field in feedback_field_list:
                assert isinstance(feedback_field, nodes.field)

                feedback_field_name = feedback_field[0]
                assert isinstance(feedback_field_name, nodes.field_name)
                feedback_field_name_raw = feedback_field_name.rawsource
                # See if this is a number, optinonally followed by a tolerance.
                try:
                    # Parse the number. In Python 3 syntax, this would be ``str_num, *list_tol = feedback_field_name_raw.split()``.
                    tmp = feedback_field_name_raw.split()
                    str_num = tmp[0]
                    list_tol = tmp[1:]
                    num = ast.literal_eval(str_num)
                    assert isinstance(num, Number)
                    # If no tolerance is given, use a tolarance of 0.
                    if len(list_tol) == 0:
                        tol = 0
                    else:
                        assert len(list_tol) == 1
                        tol = ast.literal_eval(list_tol[0])
                        assert isinstance(tol, Number)
                    # We have the number and a tolerance. Save that.
                    blankFeedbackDict = {"number": [num - tol, num + tol]}
                except (SyntaxError, ValueError, AssertionError):
                    # We can't parse this as a number, so assume it's a regex.
                    blankFeedbackDict = {
                        'regex':
                            # The given regex must match the entire string, from the beginning (which may be preceeded by spaces) ...
                            '^ *' +
                            # ... to the contents (where a single space in the provided pattern is treated as one or more spaces in the student's anwer) ...
                            feedback_field_name.rawsource.replace(' ', ' +')
                            # ... to the end (also with optional whitespace).
                            + ' *$',
                        'regexFlags':
                            'i' if 'casei' in self.options else '',
                    }
                blankArray.append(blankFeedbackDict)

                feedback_field_body = feedback_field[1]
                assert isinstance(feedback_field_body, nodes.field_body)
                # Append feedback for this asnwer to the end of the fitbNode.
                ffn = FITBFeedbackNode(feedback_field_body.rawsource, *feedback_field_body.children, **feedback_field_body.attributes)
                ffn.blankFeedbackDict = blankFeedbackDict
                fitbNode += ffn

            # Add all the feedback for this blank to the feedbackArray.
            fitbNode.feedbackArray.append(blankArray)

        return [fitbNode]
Пример #42
0
    def run(self):
        super(Codelens, self).run()

        addQuestionToDB(self)

        self.JS_VARNAME = ""
        self.JS_VARVAL = ""

        def raw_dict(input_code, output_trace):
            ret = dict(code=input_code, trace=output_trace)
            return ret

        def js_var_finalizer(input_code, output_trace):
            ret = dict(code=input_code, trace=output_trace)
            json_output = json.dumps(ret, indent=None)
            return json_output

        if self.content:
            source = "\n".join(self.content)
        else:
            source = "\n"

        CUMULATIVE_MODE = False
        self.JS_VARNAME = self.options["divid"] + "_trace"
        env = self.state.document.settings.env
        self.options["divclass"] = env.config.codelens_div_class

        if "showoutput" not in self.options:
            self.options["embedded"] = "true"  # to set embeddedmode to true
        else:
            self.options["embedded"] = "false"

        if "language" not in self.options:
            self.options["language"] = "python"

        if "python" not in self.options:
            if six.PY2:
                self.options["python"] = "py2"
            else:
                self.options["python"] = "py3"

        if "tracedata" not in self.options:
            if "question" in self.options:
                curTrace = exec_script_str_local(source, None, CUMULATIVE_MODE,
                                                 None, raw_dict)
                self.inject_questions(curTrace)
                json_output = json.dumps(curTrace, indent=None)
                self.options["tracedata"] = json_output
            else:
                if self.options["language"] == "python":
                    self.options["tracedata"] = exec_script_str_local(
                        source, None, CUMULATIVE_MODE, None, js_var_finalizer)
                elif self.options["language"] == "java":
                    self.options["tracedata"] = self.get_trace(source, "java")
                elif self.options["language"] == "cpp":
                    self.options["tracedata"] = self.get_trace(source, "cpp")
                elif self.options["language"] == "c":
                    self.options["tracedata"] = self.get_trace(source, "c")
                else:
                    raise ValueError("language not supported")

        res = VIS
        if "caption" not in self.options:
            self.options["caption"] = ""
        if "tracedata" in self.options:
            res += DATA
        else:
            res += "</div>"
        addHTMLToDB(self.options["divid"], self.options["basecourse"],
                    res % self.options)
        raw_node = nodes.raw(self.block_text,
                             res % self.options,
                             format="html")
        raw_node.source, raw_node.line = self.state_machine.get_source_and_line(
            self.lineno)
        return [raw_node]
Пример #43
0
    def run(self):
        """

   Instructions for solving the problem should be written and then a line with -----
   signals the beginning of the code.  If you want more than one line in a single
   code block, seperate your code blocks with =====.

   Both the instructions sections and code blocks are optional. If you don't include any
   =====, the code will assume you want each line to be its own code block.

Example:

.. parsonsprob:: unqiue_problem_id_here

   Solve my really cool parsons problem...if you can.
   -----
   def findmax(alist):
   =====
      if len(alist) == 0:
         return None
   =====
      curmax = alist[0]
      for item in alist:
   =====
         if item &gt; curmax:
   =====
            curmax = item
   =====
      return curmax


        """

        super(ParsonsProblem, self).run()
        addQuestionToDB(self)

        env = self.state.document.settings.env
        self.options['qnumber'] = self.getNumber()
        self.options['instructions'] = ""
        self.options['code'] = self.content
        self.options['divclass'] = env.config.parsons_div_class

        if 'numbered' in self.options:
            self.options['numbered'] = ' data-numbered="' + self.options['numbered'] + '"' #' data-numbered="true"'
        else:
            self.options['numbered'] = ''

        if 'maxdist' in self.options:
            self.options['maxdist'] = ' data-maxdist="' + self.options['maxdist'] + '"'
        else:
            self.options['maxdist'] = ''
        if 'order' in self.options:
            self.options['order'] = ' data-order="' + self.options['order'] + '"'
        else:
            self.options['order'] = ''
        if 'noindent' in self.options:
            self.options['noindent'] = ' data-noindent="true"'
        else:
            self.options['noindent'] = ''
        if 'adaptive' in self.options:
            self.options['adaptive'] = ' data-adaptive="true"'
        else:
            self.options['adaptive'] = ''
        if 'language' in self.options:
            self.options['language'] = ' data-language="' + self.options['language'] + '"'
        else:
            self.options['language'] = ''


        if '-----' in self.content:
            index = self.content.index('-----')
            self.options['instructions'] = "\n".join(self.content[:index])
            self.options['code'] = self.content[index + 1:]

        if '=====' in self.options['code']:
            self.options['code'] = "\n".join(self.options['code'])

            self.options['code'] = self.options['code'].replace('=====', '---')
        else:
            self.options['code'] = "\n".join(self.options['code'])

        self.assert_has_content()

        parsons_node = ParsonsNode(self.options, rawsource=self.block_text)
        parsons_node.source, parsons_node.line = self.state_machine.get_source_and_line(self.lineno)
        return [parsons_node]
Пример #44
0
    def run(self):
        """
            process the multiplechoice directive and generate html for output.

            :param self:
            :return: An MChoiceNode.
            """

        super(MChoice, self).run()

        TEMPLATE_START = """
            <div class="%(divclass)s">
            <ul data-component="multiplechoice" data-question_label="%(question_label)s" data-multipleanswers="%(multipleAnswers)s" %(random)s id="%(divid)s" %(optional)s>
            """

        OPTION = """
            <li data-component="answer" %(is_correct)s id="%(divid)s_opt_%(alabel)s">%(atext)s</li><li data-component="feedback">%(feedtext)s</li>
            """

        TEMPLATE_END = """

            </ul>
            </div>
            """
        addQuestionToDB(self)

        mcNode = MChoiceNode(self.options, rawsource=self.block_text)
        mcNode.source, mcNode.line = self.state_machine.get_source_and_line(
            self.lineno)
        mcNode.template_start = TEMPLATE_START
        mcNode.template_option = OPTION
        mcNode.template_end = TEMPLATE_END

        # For MChoice its better to insert the qnum into the content before further processing.
        self.updateContent()

        self.state.nested_parse(self.content, self.content_offset, mcNode)
        env = self.state.document.settings.env
        self.options["divclass"] = env.config.mchoice_div_class
        # Expected _`structure`, with assigned variable names and transformations made:
        #
        # .. code-block::
        #   :number-lines:
        #
        #   mcNode = MChoiceNode()
        #       Item 1 of problem text
        #       ...
        #       Item n of problem text
        #       answers_bullet_list = bullet_list() -> AnswersBulletList() <-- last item of mcNode may be a bulleted list of answers and feedback.
        #           answer_list_item = list_item() -> AnswerListItem()
        #               Item 1 of text for answer A
        #               ...
        #               Item n of text for answer A
        #               feedback_bullet_list = bullet_list() -> FeedbackBulletList() <-- last item must be a bulleted list containing feedback.
        #                   feedback_list_item = list_item() -> FeedbackListItem()   <-- A single item in the list, which contains the feedback.
        #           answer_list_item = list_item() -> AnswerListItem()
        #               Item 1 of text for answer B
        #               ...and so on...
        #
        # See if the last item is a list. If so, and questions/answers weren't specified as options, assume it contains questions and answers.
        answers_bullet_list = mcNode[-1] if len(mcNode) else None
        if isinstance(answers_bullet_list,
                      nodes.bullet_list) and ("answer_a" not in self.options
                                              and
                                              ("correct" not in self.options)):
            # Accumulate the correct answers.
            correct_answers = []

            # Walk it, processing each answer and its associated feedback.
            for answer_list_item in answers_bullet_list:
                assert isinstance(answer_list_item, nodes.list_item)

                # Look for the feedback for this answer -- the last child of this answer list item.
                feedback_bullet_list = answer_list_item[-1]
                if (not isinstance(feedback_bullet_list, nodes.bullet_list) or
                        # It should have just one item (the feedback itself).
                    (len(feedback_bullet_list) != 1)):
                    raise self.error(
                        "On line {}, a single-item list must be nested under each answer."
                        .format(get_node_line(feedback_bullet_list)))

                # Check for a correct answer.
                feedback_list_item = feedback_bullet_list[0]
                assert isinstance(feedback_list_item, nodes.list_item)
                if feedback_bullet_list["bullet"] == "+":
                    correct_answers.append(
                        chr(
                            answer_list_item.parent.index(answer_list_item) +
                            ord("a")))

                # Change the feedback list item (which is currently a generic list_item) to our special node class (a FeedbackListItem).
                feedback_list_item.replace_self(
                    FeedbackListItem(feedback_list_item.rawsource,
                                     *feedback_list_item.children,
                                     **feedback_list_item.attributes))

                # Change the feedback bulleted list (currently a bullet_list) to our class (a FeedbackBulletList).
                feedback_bullet_list.replace_self(
                    FeedbackBulletList(feedback_bullet_list.rawsource,
                                       *feedback_bullet_list.children,
                                       **feedback_bullet_list.attributes))

                # Change the answer list item (currently a list_item) to an AnswerListItem.
                answer_list_item.replace_self(
                    AnswerListItem(answer_list_item.rawsource,
                                   *answer_list_item.children,
                                   **answer_list_item.attributes))

            # Change the answer bulleted list (currently a bullet_list) to an AnswersBulletList.
            answers_bullet_list.replace_self(
                AnswersBulletList(answers_bullet_list.rawsource,
                                  *answers_bullet_list.children,
                                  **answers_bullet_list.attributes))
            # Store the correct answers.
            self.options["correct"] = ",".join(correct_answers)

        maybeAddToAssignment(self)
        # Check that a correct answer was provided.
        if not self.options.get("correct"):
            raise self.error("No correct answer specified.")
        return [mcNode]
Пример #45
0
    def run(self):

        addQuestionToDB(self)

        env = self.state.document.settings.env
        # keep track of how many activecodes we have.... could be used to automatically make a unique id for them.
        if not hasattr(env, 'activecodecounter'):
            env.activecodecounter = 0
        env.activecodecounter += 1
        self.options['name'] = self.arguments[0].strip()

        self.options['divid'] = self.arguments[0]
        if not self.options['divid']:
            raise Exception("No divid for ..activecode or ..actex in activecode.py")

        explain_text = None
        if self.content:
            if '~~~~' in self.content:
                idx = self.content.index('~~~~')
                explain_text = self.content[:idx]
                self.content = self.content[idx+1:]
            source = "\n".join(self.content)
        else:
            source = '\n'

        self.options['initialcode'] = source
        str = source.replace("\n", "*nline*")
        str0 = str.replace("\"", "*doubleq*")
        str1 = str0.replace("(", "*open*")
        str2 = str1.replace(")", "*close*")
        str3 = str2.replace("'", "*singleq*")
        self.options['argu'] = str3

        complete = ""
        no_of_buttons = 0
        okeys = list(self.options.keys())
        for k in okeys:
            if '_' in k:
                x, label = k.split('_')
                no_of_buttons = no_of_buttons + 1
                complete = complete + self.options[k] + "*atype*"

        newcomplete = complete.replace("\"", "*doubleq*")
        self.options['ctext'] = newcomplete
        self.options['no_of_buttons'] = no_of_buttons

        if 'caption' not in self.options:
            self.options['caption'] = ''
        else:
            self.options['caption'] = "data-caption='%s'" % self.options['caption']

        if 'include' not in self.options:
            self.options['include'] = ''
        else:
            lst = self.options['include'].split(',')
            lst = [x.strip() for x in lst]
            self.options['include'] = 'data-include=' + " ".join(lst)

        if 'hidecode' in self.options:
            self.options['hidecode'] = 'data-hidecode="true"'
        else:
            self.options['hidecode'] = ''

        if 'language' not in self.options:
            self.options['language'] = 'python'

        if self.options['language'] == 'html':
            self.options['language'] = 'htmlmixed'
            self.options['initialcode'] = escape(self.options['initialcode'])

        if 'nocodelens' in self.options or self.options['language'] != 'python':
            self.options['codelens'] = ''
        else:
            self.options['codelens'] = 'data-codelens="true"'

        if 'timelimit' not in self.options:
            self.options['timelimit'] = 'data-timelimit=25000'
        else:
            self.options['timelimit'] = 'data-timelimit=%s' % self.options['timelimit']

        if 'autorun' not in self.options:
            self.options['autorun'] = ''
        else:
            self.options['autorun'] = 'data-autorun="true"'

        if 'coach' in self.options:
            self.options['coach'] = 'data-coach="true"'
        else:
            self.options['coach'] = ''

        # livecode options
        if 'stdin' in self.options:
            self.options['stdin'] = "data-stdin='%s'" % self.options['stdin']
        else:
            self.options['stdin'] = ""

        if 'datafile' not in self.options:
            self.options['datafile'] = ""
        else:
            self.options['datafile'] = "data-datafile='%s'" % self.options['datafile']

        if 'sourcefile' not in self.options:
            self.options['sourcefile'] = ""
        else:
            self.options['sourcefile'] = "data-sourcefile='%s'" % self.options['sourcefile']

        if 'gradebutton' not in self.options:
            self.options['gradebutton'] = ''
        else:
            self.options['gradebutton'] = "data-gradebutton=true"

        if self.content:
            if '====' in self.content:
                idx = self.content.index('====')
                source = "\n".join(self.content[:idx])
                suffix = "\n".join(self.content[idx+1:])
            else:
                source = "\n".join(self.content)
                suffix = "\n"
        else:
            source = '\n'
            suffix = '\n'
        try:
            engine = create_engine(get_dburl(locals()))
            meta = MetaData()
            course_name = env.config.html_context['course_id']
            Source_code = Table('source_code', meta, autoload=True, autoload_with=engine)
            divid = self.options['divid']

            engine.execute(Source_code.delete().where(Source_code.c.acid == divid).where(Source_code.c.course_id == course_name))
            engine.execute(Source_code.insert().values(
                acid = divid,
                course_id = course_name,
                main_code= source,
                suffix_code = suffix,
                includes = self.options['include'],
                available_files = self.options.get('available_files', "")
            ))
            try:
                ch, sub_ch = env.docname.split('/')
            except:
                ch, sub_ch = (env.docname, 'null subchapter')
            Div = Table('div_ids', meta, autoload=True, autoload_with=engine)
            engine.execute(Div.delete()\
                           .where(Div.c.course_name == course_name)\
                           .where(Div.c.chapter == ch)\
                           .where(Div.c.subchapter==sub_ch)\
                           .where(Div.c.div_id==divid))
            engine.execute(Div.insert().values(
                course_name = course_name,
                chapter = ch,
                subchapter = sub_ch,
                div_id = divid,
                div_type = 'activecode'
            ))


        except Exception as e:
            import traceback
            print("The exception is ", e)
            traceback.print_exc()
            print(env.config.html_context['course_id'])
            print("Unable to save to source_code table in activecode.py. Possible problems:")
            print("  1. dburl or course_id are not set in conf.py for your book")
            print("  2. unable to connect to the database using dburl")
            print("")
            print("This should only affect the grading interface. Everything else should be fine.")


        acnode = ActivcodeNode(self.options)
        self.add_name(acnode)    # make this divid available as a target for :ref:

        if explain_text:
            self.state.nested_parse(explain_text, self.content_offset, acnode)

        return [acnode]
Пример #46
0
 def run(self):
     raw_node = super(Youtube, self).run()
     addQuestionToDB(self)
     return raw_node
Пример #47
0
    def run(self):

        addQuestionToDB(self)

        env = self.state.document.settings.env
        # keep track of how many activecodes we have.... could be used to automatically make a unique id for them.
        if not hasattr(env, 'activecodecounter'):
            env.activecodecounter = 0
        env.activecodecounter += 1
        self.options['name'] = self.arguments[0].strip()

        self.options['divid'] = self.arguments[0]
        if not self.options['divid']:
            raise Exception("No divid for ..activecode or ..actex in activecode.py")

        explain_text = None
        if self.content:
            if '~~~~' in self.content:
                idx = self.content.index('~~~~')
                explain_text = self.content[:idx]
                self.content = self.content[idx+1:]
            source = "\n".join(self.content)
        else:
            source = '\n'

        self.options['initialcode'] = source
        str = source.replace("\n", "*nline*")
        str0 = str.replace("\"", "*doubleq*")
        str1 = str0.replace("(", "*open*")
        str2 = str1.replace(")", "*close*")
        str3 = str2.replace("'", "*singleq*")
        self.options['argu'] = str3

        complete = ""
        no_of_buttons = 0
        okeys = list(self.options.keys())
        for k in okeys:
            if '_' in k:
                x, label = k.split('_')
                no_of_buttons = no_of_buttons + 1
                complete = complete + self.options[k] + "*atype*"

        newcomplete = complete.replace("\"", "*doubleq*")
        self.options['ctext'] = newcomplete
        self.options['no_of_buttons'] = no_of_buttons

        if 'caption' not in self.options:
            self.options['caption'] = ''
        else:
            self.options['caption'] = "data-caption='%s'" % self.options['caption']

        if 'include' not in self.options:
            self.options['include'] = ''
        else:
            lst = self.options['include'].split(',')
            lst = [x.strip() for x in lst]
            self.options['include'] = 'data-include=' + " ".join(lst)

        if 'hidecode' in self.options:
            self.options['hidecode'] = 'data-hidecode="true"'
        else:
            self.options['hidecode'] = ''

        if 'language' not in self.options:
            self.options['language'] = 'python'

        if self.options['language'] == 'html':
            self.options['language'] = 'htmlmixed'
            self.options['initialcode'] = escape(self.options['initialcode'])

        if 'nocodelens' in self.options or self.options['language'] != 'python':
            self.options['codelens'] = ''
        else:
            self.options['codelens'] = 'data-codelens="true"'

        if 'timelimit' not in self.options:
            self.options['timelimit'] = 'data-timelimit=25000'
        else:
            self.options['timelimit'] = 'data-timelimit=%s' % self.options['timelimit']

        if 'autorun' not in self.options:
            self.options['autorun'] = ''
        else:
            self.options['autorun'] = 'data-autorun="true"'

        if 'coach' in self.options:
            self.options['coach'] = 'data-coach="true"'
        else:
            self.options['coach'] = ''

        # livecode options
        if 'stdin' in self.options:
            self.options['stdin'] = "data-stdin='%s'" % self.options['stdin']
        else:
            self.options['stdin'] = ""

        if 'datafile' not in self.options:
            self.options['datafile'] = ""
        else:
            self.options['datafile'] = "data-datafile='%s'" % self.options['datafile']

        if 'sourcefile' not in self.options:
            self.options['sourcefile'] = ""
        else:
            self.options['sourcefile'] = "data-sourcefile='%s'" % self.options['sourcefile']

        if 'gradebutton' not in self.options:
            self.options['gradebutton'] = ''

        if self.content:
            if '====' in self.content:
                idx = self.content.index('====')
                source = "\n".join(self.content[:idx])
                suffix = "\n".join(self.content[idx+1:])
            else:
                source = "\n".join(self.content)
                suffix = "\n"
        else:
            source = '\n'
            suffix = '\n'
        try:
            engine = create_engine(get_dburl(locals()))
            meta = MetaData()
            course_name = env.config.html_context['course_id']
            Source_code = Table('source_code', meta, autoload=True, autoload_with=engine)
            divid = self.options['divid']

            engine.execute(Source_code.delete().where(Source_code.c.acid == divid).where(Source_code.c.course_id == course_name))
            engine.execute(Source_code.insert().values(
                acid = divid,
                course_id = course_name,
                main_code= source,
                suffix_code = suffix,
                includes = self.options['include'],
                available_files = self.options.get('available_files', "")
            ))
            try:
                ch, sub_ch = env.docname.split('/')
            except:
                ch, sub_ch = (env.docname, 'null subchapter')
            Div = Table('div_ids', meta, autoload=True, autoload_with=engine)
            engine.execute(Div.delete()\
                           .where(Div.c.course_name == course_name)\
                           .where(Div.c.chapter == ch)\
                           .where(Div.c.subchapter==sub_ch)\
                           .where(Div.c.div_id==divid))
            engine.execute(Div.insert().values(
                course_name = course_name,
                chapter = ch,
                subchapter = sub_ch,
                div_id = divid,
                div_type = 'activecode'
            ))


        except Exception as e:
            import traceback
            print("The exception is ", e)
            traceback.print_exc()
            print(env.config.html_context['course_id'])
            print("Unable to save to source_code table in activecode.py. Possible problems:")
            print("  1. dburl or course_id are not set in conf.py for your book")
            print("  2. unable to connect to the database using dburl")
            print("")
            print("This should only affect the grading interface. Everything else should be fine.")


        acnode = ActivcodeNode(self.options)
        self.add_name(acnode)    # make this divid available as a target for :ref:

        if explain_text:
            self.state.nested_parse(explain_text, self.content_offset, acnode)

        return [acnode]
Пример #48
0
    def run(self):
        """

   Instructions for solving the problem should be written and then a line with -----
   signals the beginning of the code.  If you want more than one line in a single
   code block, seperate your code blocks with =====.

   Both the instructions sections and code blocks are optional. If you don't include any
   =====, the code will assume you want each line to be its own code block.

Example:

.. parsonsprob:: unqiue_problem_id_here

   Solve my really cool parsons problem...if you can.
   -----
   def findmax(alist):
   =====
      if len(alist) == 0:
         return None
   =====
      curmax = alist[0]
      for item in alist:
   =====
         if item &gt; curmax:
   =====
            curmax = item
   =====
      return curmax


        """

        addQuestionToDB(self)

        TEMPLATE = '''
    <pre data-component="parsons" id="%(divid)s"%(maxdist)s%(order)s%(noindent)s%(language)s>
        <span data-question>%(qnumber)s: %(instructions)s</span>%(code)s</pre>
    '''
        self.options['divid'] = self.arguments[0]
        self.options['qnumber'] = self.getNumber()
        self.options['instructions'] = ""
        self.options['code'] = self.content
        
        if 'maxdist' in self.options:
            self.options['maxdist'] = ' data-maxdist="' + self.options['maxdist'] + '"'
        else:
            self.options['maxdist'] = ''
        if 'order' in self.options:
            self.options['order'] = ' data-order="' + self.options['order'] + '"'
        else:
            self.options['order'] = ''
        if 'noindent' in self.options:
            self.options['noindent'] = ' data-noindent="true"'
        else:
            self.options['noindent'] = ''
        if 'language' in self.options:
            self.options['language'] = ' data-language="' + self.options['language'] + '"'
        else:
            self.options['language'] = ''
         
          
        if '-----' in self.content:
            index = self.content.index('-----')
            self.options['instructions'] = "\n".join(self.content[:index])
            self.options['code'] = self.content[index + 1:]

        if '=====' in self.options['code']:
            self.options['code'] = "\n".join(self.options['code'])

            self.options['code'] = self.options['code'].replace('=====', '---')
        else:
            self.options['code'] = "\n".join(self.options['code'])

        self.options['divid'] = self.arguments[0]

        self.assert_has_content()
        return [nodes.raw('', TEMPLATE % self.options, format='html')]
Пример #49
0
    def run(self):
        super(ActiveCode, self).run()

        addQuestionToDB(self)

        env = self.state.document.settings.env
        # keep track of how many activecodes we have....
        # could be used to automatically make a unique id for them.
        if not hasattr(env, 'activecodecounter'):
            env.activecodecounter = 0
        env.activecodecounter += 1
        self.options['name'] = self.arguments[0].strip()

        explain_text = None
        if self.content:
            if '~~~~' in self.content:
                idx = self.content.index('~~~~')
                explain_text = self.content[:idx]
                self.content = self.content[idx+1:]
            source = "\n".join(self.content)
        else:
            source = '\n'

        self.options['initialcode'] = source
        str = source.replace("\n", "*nline*")
        str0 = str.replace("\"", "*doubleq*")
        str1 = str0.replace("(", "*open*")
        str2 = str1.replace(")", "*close*")
        str3 = str2.replace("'", "*singleq*")
        self.options['argu'] = str3

        complete = ""
        no_of_buttons = 0
        okeys = list(self.options.keys())
        for k in okeys:
            if '_' in k:
                x, label = k.split('_')
                no_of_buttons = no_of_buttons + 1
                complete = complete + self.options[k] + "*atype*"

        newcomplete = complete.replace("\"", "*doubleq*")
        self.options['ctext'] = newcomplete
        self.options['no_of_buttons'] = no_of_buttons

        if 'caption' not in self.options:
            self.options['caption'] = ''
        else:
            self.options['caption'] = "data-caption='%s'" % self.options['caption']

        if 'include' not in self.options:
            self.options['include'] = ''
        else:
            lst = self.options['include'].split(',')
            lst = [x.strip() for x in lst]
            self.options['include'] = 'data-include="' + " ".join(lst) + '"'

        if 'hidecode' in self.options:
            self.options['hidecode'] = 'data-hidecode="true"'
        else:
            self.options['hidecode'] = ''

        if 'enabledownload' in self.options:
            self.options['enabledownload'] = 'data-enabledownload="true"'
        else:
            self.options['enabledownload'] = ''

        if 'chatcodes' in self.options:
            self.options['chatcodes'] = 'data-chatcodes="true"'
        else:
            self.options['chatcodes'] = ''

        if 'language' not in self.options:
            self.options['language'] = 'python'

        if self.options['language'] == 'html':
            self.options['language'] = 'htmlmixed'
            self.options['initialcode'] = escape(self.options['initialcode'])

        if 'nocodelens' in self.options or self.options['language'] != 'python':
            self.options['codelens'] = ''
        else:
            self.options['codelens'] = 'data-codelens="true"'

        if 'timelimit' not in self.options:
            self.options['timelimit'] = 'data-timelimit=25000'
        else:
            self.options['timelimit'] = 'data-timelimit=%s' % self.options['timelimit']

        if 'autorun' not in self.options:
            self.options['autorun'] = ''
        else:
            self.options['autorun'] = 'data-autorun="true"'

        if 'coach' in self.options:
            self.options['coach'] = 'data-coach="true"'
        else:
            self.options['coach'] = ''

        # livecode options
        if 'stdin' in self.options:
            self.options['stdin'] = "data-stdin='%s'" % self.options['stdin']
        else:
            self.options['stdin'] = ""

        if 'datafile' not in self.options:
            self.options['datafile'] = ""
        else:
            self.options['datafile'] = "data-datafile='%s'" % self.options['datafile']

        if 'sourcefile' not in self.options:
            self.options['sourcefile'] = ""
        else:
            self.options['sourcefile'] = "data-sourcefile='%s'" % self.options['sourcefile']

        for opt,tp in [('compileargs','cargs'),('linkargs','largs'),('runargs','rargs'),('interpreterargs','iargs')]:
            if opt in self.options:
                self.options[tp] = 'data-{}="{}"'.format(opt, escape(self.options[opt]))
            else:
                self.options[tp] = ""

        if 'gradebutton' not in self.options:
            self.options['gradebutton'] = ''
        else:
            self.options['gradebutton'] = "data-gradebutton=true"

        self.options['divclass'] = env.config.activecode_div_class
        if env.config.activecode_hide_load_history:
            self.options['hidehistory'] = 'data-hidehistory=true'
        else:
            self.options['hidehistory'] = ''

        if self.content:
            if '====' in self.content:
                idx = self.content.index('====')
                source = "\n".join(self.content[:idx])
                suffix = "\n".join(self.content[idx+1:])
            else:
                source = "\n".join(self.content)
                suffix = "\n"
        else:
            source = '\n'
            suffix = '\n'


        course_name = env.config.html_context['course_id']
        divid = self.options['divid']

        if engine:
            engine.execute(Source_code.delete().where(Source_code.c.acid == divid).where(Source_code.c.course_id == course_name))
            engine.execute(Source_code.insert().values(
                acid = divid,
                course_id = course_name,
                main_code= source,
                suffix_code = suffix,
                includes = self.options['include'],
                available_files = self.options.get('available_files', "")
            ))
        else:
            if not hasattr(env, 'dberr_activecode_reported') or not env.dberr_activecode_reported:
                env.dberr_activecode_reported = True
                print("Unable to save to source_code table in activecode.py. Possible problems:")
                print("  1. dburl or course_id are not set in conf.py for your book")
                print("  2. unable to connect to the database using dburl")
                print("")
                print("This should only affect the grading interface. Everything else should be fine.")


        acnode = ActivcodeNode(self.options, rawsource=self.block_text)
        acnode.source, acnode.line = self.state_machine.get_source_and_line(self.lineno)
        self.add_name(acnode)    # make this divid available as a target for :ref:

        if explain_text:
            self.state.nested_parse(explain_text, self.content_offset, acnode)

        return [acnode]
    def run(self):
        """
            process the multiplechoice directive and generate html for output.

            :param self:
            :return: An MChoiceNode.
            """

        super(MChoice, self).run()

        TEMPLATE_START = '''
            <div class="%(divclass)s">
            <ul data-component="multiplechoice" data-multipleanswers="%(multipleAnswers)s" %(random)s id="%(divid)s">
            '''

        OPTION = '''
            <li data-component="answer" %(is_correct)s id="%(divid)s_opt_%(alabel)s">%(atext)s</li><li data-component="feedback" id="%(divid)s_opt_%(alabel)s">%(feedtext)s</li>
            '''

        TEMPLATE_END = '''

            </ul>
            </div>
            '''
        addQuestionToDB(self)

        mcNode = MChoiceNode(self.options, rawsource=self.block_text)
        mcNode.source, mcNode.line = self.state_machine.get_source_and_line(self.lineno)
        mcNode.template_start = TEMPLATE_START
        mcNode.template_option = OPTION
        mcNode.template_end = TEMPLATE_END

        self.state.nested_parse(self.content, self.content_offset, mcNode)
        env = self.state.document.settings.env
        self.options['divclass'] = env.config.mchoice_div_class
        # Expected _`structure`, with assigned variable names and transformations made:
        #
        # .. code-block::
        #   :number-lines:
        #
        #   mcNode = MChoiceNode()
        #       Item 1 of problem text
        #       ...
        #       Item n of problem text
        #       answers_bullet_list = bullet_list() -> AnswersBulletList() <-- last item of mcNode may be a bulleted list of answers and feedback.
        #           answer_list_item = list_item() -> AnswerListItem()
        #               Item 1 of text for answer A
        #               ...
        #               Item n of text for answer A
        #               feedback_bullet_list = bullet_list() -> FeedbackBulletList() <-- last item must be a bulleted list containing feedback.
        #                   feedback_list_item = list_item() -> FeedbackListItem()   <-- A single item in the list, which contains the feedback.
        #           answer_list_item = list_item() -> AnswerListItem()
        #               Item 1 of text for answer B
        #               ...and so on...
        #
        # See if the last item is a list. If so, and questions/answers weren't specified as options, assume it contains questions and answers.
        answers_bullet_list = mcNode[-1] if len(mcNode) else None
        if isinstance(answers_bullet_list, nodes.bullet_list) and ('answer_a' not in self.options and ('correct' not in self.options)):
            # Accumulate the correct answers.
            correct_answers = []

            # Walk it, processing each answer and its associated feedback.
            for answer_list_item in answers_bullet_list:
                assert isinstance(answer_list_item, nodes.list_item)

                # Look for the feedback for this answer -- the last child of this answer list item.
                feedback_bullet_list = answer_list_item[-1]
                if ((not isinstance(feedback_bullet_list, nodes.bullet_list) or
                  # It should have just one item (the feedback itself).
                  (len(feedback_bullet_list) != 1))):
                    raise self.error('On line {}, a single-item list must be nested under each answer.'.format(get_node_line(feedback_bullet_list)))

                # Check for a correct answer.
                feedback_list_item = feedback_bullet_list[0]
                assert isinstance(feedback_list_item, nodes.list_item)
                if feedback_bullet_list['bullet'] == '+':
                    correct_answers.append(chr(answer_list_item.parent.index(answer_list_item) + ord('a')))

                # Change the feedback list item (which is currently a generic list_item) to our special node class (a FeedbackListItem).
                feedback_list_item.replace_self(FeedbackListItem(feedback_list_item.rawsource, *feedback_list_item.children, **feedback_list_item.attributes))

                # Change the feedback bulleted list (currently a bullet_list) to our class (a FeedbackBulletList).
                feedback_bullet_list.replace_self(FeedbackBulletList(feedback_bullet_list.rawsource, *feedback_bullet_list.children, **feedback_bullet_list.attributes))

                # Change the answer list item (currently a list_item) to an AnswerListItem.
                answer_list_item.replace_self(AnswerListItem(answer_list_item.rawsource, *answer_list_item.children, **answer_list_item.attributes))

            # Change the answer bulleted list (currently a bullet_list) to an AnswersBulletList.
            answers_bullet_list.replace_self(AnswersBulletList(answers_bullet_list.rawsource, *answers_bullet_list.children, **answers_bullet_list.attributes))
            # Store the correct answers.
            self.options['correct'] = ','.join(correct_answers)

        # Check that a correct answer was provided.
        if not self.options.get('correct'):
            raise self.error('No correct answer specified.')
        return [mcNode]
Пример #51
0
    def run(self):
        super(Codelens, self).run()

        addQuestionToDB(self)

        self.JS_VARNAME = ""
        self.JS_VARVAL = ""

        def raw_dict(input_code, output_trace):
            ret = dict(code=input_code, trace=output_trace)
            return ret

        def js_var_finalizer(input_code, output_trace):
            global JS_VARNAME
            ret = dict(code=input_code, trace=output_trace)
            json_output = json.dumps(ret, indent=None)
            return "var %s = %s;" % (self.JS_VARNAME, json_output)

        if self.content:
            source = "\n".join(self.content)
        else:
            source = '\n'

        CUMULATIVE_MODE = False
        self.JS_VARNAME = self.options['divid'] + '_trace'
        env = self.state.document.settings.env
        self.options['divclass'] = env.config.codelens_div_class

        if 'showoutput' not in self.options:
            self.options['embedded'] = 'true'  # to set embeddedmode to true
        else:
            self.options['embedded'] = 'false'

        if 'python' not in self.options:
            if six.PY2:
                self.options['python'] = 'py2'
            else:
                self.options['python'] = 'py3'

        if 'question' in self.options:
            curTrace = exec_script_str_local(source, None, CUMULATIVE_MODE, None, raw_dict)
            self.inject_questions(curTrace)
            json_output = json.dumps(curTrace, indent=None)
            self.options['tracedata'] = "var %s = %s;" % (self.JS_VARNAME, json_output)
        else:
            self.options['tracedata'] = exec_script_str_local(source, None,
                                                              CUMULATIVE_MODE,
                                                              None, js_var_finalizer)

        res = VIS
        if 'caption' not in self.options:
            self.options['caption'] = ''
        if 'question' in self.options:
            res += QUESTION
        if 'tracedata' in self.options:
            res += DATA
        else:
            res += '</div>'
        addHTMLToDB(self.options['divid'], self.options['basecourse'], res % self.options)
        raw_node = nodes.raw(self.block_text, res % self.options, format='html')
        raw_node.source, raw_node.line = self.state_machine.get_source_and_line(self.lineno)
        return [raw_node]