Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit f62760d

Browse files
committed
improved feedback processing
1 parent 411aef3 commit f62760d

File tree

1 file changed

+90
-4
lines changed

1 file changed

+90
-4
lines changed

runestone/fitb/fitb.py

Lines changed: 90 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import ast
2424
from numbers import Number
2525
import re
26+
import pdb
2627

2728
from docutils import nodes
2829
from docutils.parsers.rst import directives
@@ -42,14 +43,19 @@
4243
from runestone.common.xmlcommon import substitute_departure, substitute_visitor
4344

4445

46+
def noop(self, node):
47+
pass
48+
49+
4550
def setup(app):
4651
app.add_directive("fillintheblank", FillInTheBlank)
4752
app.add_role("blank", BlankRole)
48-
app.add_node(FITBNode, html=(visit_fitb_html, depart_fitb_html))
53+
app.add_node(FITBNode, html=(visit_fitb_html, depart_fitb_html),
54+
xml=(visit_fitb_xml, depart_fitb_xml))
4955
app.add_node(BlankNode, html=(visit_blank_html, depart_blank_html))
5056
app.add_node(
5157
FITBFeedbackNode, html=(visit_fitb_feedback_html, depart_fitb_feedback_html),
52-
xml=(substitute_visitor, substitute_departure)
58+
xml=(noop, noop)
5359
)
5460

5561
app.add_config_value("fitb_div_class", "runestone", "html")
@@ -110,6 +116,80 @@ def depart_fitb_html(self, node):
110116

111117
self.body.remove(node["delimiter"])
112118

119+
# <exercise>
120+
# <title>Fill-In, Integer Answer</title>
121+
122+
# <statement>
123+
# <p>The game of bowling uses <var/> pins that you try to knock down.</p>
124+
# </statement>
125+
# <setup>
126+
# <var>
127+
# <condition number="10">
128+
# <feedback>
129+
# <p>Arranged in a triangle, there are <m>1+2+3+4 = 10</m> pins, a so-called <term>triangular</term> number.</p>
130+
# </feedback>
131+
# </condition>
132+
# <condition number="16">
133+
# <feedback>
134+
# <p><em>Close</em>! You may have used hexadecimal notation, when you did not really mean to.</p>
135+
# </feedback>
136+
# </condition>
137+
# <condition string=".*">
138+
# <feedback>
139+
# <p>Incorrect.</p>
140+
# </feedback>
141+
# </condition>
142+
# </var>
143+
# </setup>
144+
# </exercise>
145+
146+
147+
def visit_fitb_xml(self, node):
148+
149+
TEMPLATE_START = """
150+
<exercise>
151+
<statement>
152+
"""
153+
self.output.append(TEMPLATE_START)
154+
155+
156+
def depart_fitb_xml(self, node):
157+
blankCount = 0
158+
for xx in node.traverse(BlankNode):
159+
blankCount += 1
160+
161+
# pattlist = node["runestone_options"]["pattlist"] # answer patterns
162+
# flist = node["runestone_options"]["flist"] # feedback
163+
# for _ in pattlist:
164+
# blankCount += 1
165+
# while blankCount < len(flist):
166+
# visit_blank_xml(self, None)
167+
# blankCount += 1
168+
169+
self.output.append("</statement>")
170+
self.output.append("<setup>")
171+
# Walk the children of node
172+
# child 0 is the statement
173+
# children 1..N are the feedbacks
174+
# each of these children will have an atribute called blankfeedbackdict which is the match for this
175+
# each child will have a child/children that is the actual feedback we want to supply
176+
#
177+
self.output.append("<var>")
178+
for child in node.children[1:]:
179+
rx = child["blankfeedbackdict"]
180+
if "number" in rx:
181+
self.output.append(f"""<condition number="{rx['number']}">""")
182+
else:
183+
self.output.append(f"""<condition string="{rx['regex']}">""")
184+
fb = ""
185+
for p in child.children:
186+
fb += str(p)
187+
self.output.append(f"<feedback>{fb}</feedback>")
188+
self.output.append("</condition>")
189+
self.output.append("</var>")
190+
self.output.append("</setup>")
191+
self.output.append("</exercise>")
192+
113193

114194
class FillInTheBlank(RunestoneIdDirective):
115195
"""
@@ -177,7 +257,6 @@ def run(self):
177257
self.state.nested_parse(self.content, self.content_offset, fitbNode)
178258
env = self.state.document.settings.env
179259
self.options["divclass"] = env.config.fitb_div_class
180-
181260
# Expected _`structure`, with assigned variable names and transformations made:
182261
#
183262
# .. code-block::
@@ -239,6 +318,8 @@ def run(self):
239318
get_node_line(feedback_bullet_list)
240319
)
241320
)
321+
# Thelength of feedbback_list_item gives us the number of blanks.
322+
# the number of feedback is len(feedback_bullet_list.children[x].children[0].children)
242323
for feedback_list_item in feedback_bullet_list.children:
243324
assert isinstance(feedback_list_item, nodes.list_item)
244325
feedback_field_list = feedback_list_item[0]
@@ -299,7 +380,6 @@ def run(self):
299380
)
300381
)
301382
blankArray.append(blankFeedbackDict)
302-
303383
feedback_field_body = feedback_field[1]
304384
assert isinstance(feedback_field_body, nodes.field_body)
305385
# Append feedback for this answer to the end of the fitbNode.
@@ -315,6 +395,8 @@ def run(self):
315395
fitbNode["feedbackArray"].append(blankArray)
316396

317397
maybeAddToAssignment(self)
398+
fitbNode["runestone_options"]["pattlist"] = fitbNode["feedbackArray"][:]
399+
fitbNode["runestone_options"]["flist"] = feedback_field_list[:]
318400

319401
return [fitbNode]
320402

@@ -356,6 +438,10 @@ def visit_blank_html(self, node):
356438
self.body.append('<input type="text">')
357439

358440

441+
def visit_blank_xml(self, node):
442+
self.output.append('<p><var /></p>')
443+
444+
359445
def depart_blank_html(self, node):
360446
pass
361447

0 commit comments

Comments
 (0)