2323import ast
2424from numbers import Number
2525import re
26+ import pdb
2627
2728from docutils import nodes
2829from docutils .parsers .rst import directives
4243from runestone .common .xmlcommon import substitute_departure , substitute_visitor
4344
4445
46+ def noop (self , node ):
47+ pass
48+
49+
4550def 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
114194class 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+
359445def depart_blank_html (self , node ):
360446 pass
361447
0 commit comments