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)
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]
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]
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]
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]
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')]
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]
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]
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]
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]
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]
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')]
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")]
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
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')]
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): """ 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]
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]
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]
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]
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]
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]
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]
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')]
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]
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]
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]
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]
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]
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]
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]
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")]
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]
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]
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 > 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]
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]
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]
def run(self): raw_node = super(Youtube, self).run() addQuestionToDB(self) return raw_node
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]
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 > 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')]
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]
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]