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

Commit 6d9e8e4

Browse files
committed
multiple choice is working for xml
1 parent dd75ea5 commit 6d9e8e4

File tree

2 files changed

+70
-11
lines changed

2 files changed

+70
-11
lines changed

runestone/mchoice/assess.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,20 @@ def setup(app):
3535
xml=(visit_mc_xml, depart_mc_xml))
3636

3737
app.add_node(
38-
AnswersBulletList, html=(visit_answers_bullet_html, depart_answers_bullet_html)
38+
AnswersBulletList, html=(visit_answers_bullet_html, depart_answers_bullet_html),
39+
xml=(visit_answers_bullet_xml, depart_answers_bullet_xml)
3940
)
40-
app.add_node(AnswerListItem, html=(visit_answer_list_item, depart_answer_list_item))
41+
app.add_node(AnswerListItem, html=(visit_answer_list_item, depart_answer_list_item),
42+
xml=(visit_answer_list_item_xml, depart_answer_list_item_xml)
43+
)
4144
app.add_node(
4245
FeedbackBulletList,
4346
html=(visit_feedback_bullet_html, depart_feedback_bullet_html),
47+
xml=(visit_feedback_bullet_html, depart_feedback_bullet_html)
4448
)
4549
app.add_node(
46-
FeedbackListItem, html=(visit_feedback_list_item, depart_feedback_list_item)
50+
FeedbackListItem, html=(visit_feedback_list_item, depart_feedback_list_item),
51+
xml=(visit_feedback_list_item_xml, depart_feedback_list_item_xml)
4752
)
4853

4954

runestone/mchoice/multiplechoice.py

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,9 @@ class MChoiceNode(nodes.General, nodes.Element, RunestoneIdNode):
4040
<statement>
4141
4242
"""
43-
43+
# TODO: detect old versus new style to include the choices or not
4444
XML_START_END = """
4545
</statement>
46-
<choices>
4746
"""
4847

4948
XML_OPTION = """
@@ -52,13 +51,12 @@ class MChoiceNode(nodes.General, nodes.Element, RunestoneIdNode):
5251
<p>{atext}</p>
5352
</statement>
5453
<feedback>
55-
<p>Incorrect: green means "go!".</p>
54+
{feedtext}
5655
</feedback>
5756
</choice>
5857
"""
5958

6059
XML_END = """
61-
</choices>
6260
</exercise>
6361
"""
6462

@@ -101,6 +99,8 @@ def depart_mc_common(self, node):
10199
res = ""
102100
currFeedback = ""
103101
# Add all of the possible answers
102+
if node["runestone_options"]["is_new_style"] == False and hasattr(self, "output"):
103+
res += "<choices>\n"
104104
okeys = list(node["runestone_options"].keys())
105105
okeys.sort()
106106
for k in okeys:
@@ -113,11 +113,12 @@ def depart_mc_common(self, node):
113113
currFeedback, ""
114114
) # node["runestone_options"][currFeedback]
115115
if label in node["runestone_options"]["correct"]:
116-
node["runestone_options"]["is_correct"] = "data-correct"
116+
node["runestone_options"]["is_correct"] = "data-correct='yes'"
117117
else:
118118
node["runestone_options"]["is_correct"] = ""
119119
res += node["template_option"].format(**node["runestone_options"])
120-
120+
if node["runestone_options"]["is_new_style"] == False and hasattr(self, "output"):
121+
res += "</choices>\n"
121122
res += node["template_end"].format(**node["runestone_options"])
122123
return res
123124

@@ -126,8 +127,8 @@ def visit_mc_xml(self, node):
126127
node["template_start"] = XML_START
127128
node["template_end"] = XML_END
128129
node["template_option"] = XML_OPTION
129-
pdb.set_trace()
130130
res = visit_mc_common(self, node)
131+
res = res.replace("data-correct", "correct")
131132
self.output.append(res)
132133

133134

@@ -290,13 +291,14 @@ def run(self):
290291
# ...and so on...
291292
#
292293
# See if the last item is a list. If so, and questions/answers weren't specified as options, assume it contains questions and answers.
294+
self.options["is_new_style"] = False
293295
answers_bullet_list = mcNode[-1] if len(mcNode) else None
294296
if isinstance(answers_bullet_list, nodes.bullet_list) and (
295297
"answer_a" not in self.options and ("correct" not in self.options)
296298
):
297299
# Accumulate the correct answers.
298300
correct_answers = []
299-
301+
self.options["is_new_style"] = True
300302
# Walk it, processing each answer and its associated feedback.
301303
for answer_list_item in answers_bullet_list:
302304
assert isinstance(answer_list_item, nodes.list_item)
@@ -402,6 +404,15 @@ def depart_answers_bullet_html(self, node):
402404
self.compact_simple, self.compact_p = self.context.pop()
403405

404406

407+
def visit_answers_bullet_xml(self, node):
408+
self.output.append("</statement>")
409+
self.output.append("<choices>")
410+
411+
412+
def depart_answers_bullet_xml(self, node):
413+
self.output.append("</choice>")
414+
415+
405416
# Write out the special attributes needed by the ``<li>`` tag.
406417
def visit_answer_list_item(self, node):
407418
# See the structure_.
@@ -423,11 +434,36 @@ def visit_answer_list_item(self, node):
423434
)
424435

425436

437+
def visit_answer_list_item_xml(self, node):
438+
# See the structure_.
439+
mc_node = node.parent.parent
440+
441+
# _`label`: Turn the index of this item in the answer_bullet_list (see structure_) into a letter.
442+
label = chr(node.parent.index(node) + ord("a"))
443+
# Update dict for formatting the HTML.
444+
mc_node["runestone_options"]["alabel"] = label
445+
if label in mc_node["runestone_options"]["correct"]:
446+
mc_node["runestone_options"]["is_correct"] = "data-correct"
447+
self.output.append("<choice correct='yes'>")
448+
else:
449+
mc_node["runestone_options"]["is_correct"] = ""
450+
self.output.append("<choice>")
451+
# Format the HTML.
452+
self.output.append(
453+
'<statement id="{divid}_opt_{alabel}">'.format(
454+
**mc_node["runestone_options"])
455+
)
456+
457+
426458
# Although the feedback for an answer is given as a sublist, the HTML is just a list. So, let the feedback list item close this list.
427459
def depart_answer_list_item(self, node):
428460
pass
429461

430462

463+
def depart_answer_list_item_xml(self, node):
464+
self.output.append("</choice>")
465+
466+
431467
# Nothing to output, since feedback isn't nested under an answer in the HTML.
432468
def visit_feedback_bullet_html(self, node):
433469
pass
@@ -450,11 +486,29 @@ def visit_feedback_list_item(self, node):
450486
)
451487

452488

489+
def visit_feedback_list_item_xml(self, node):
490+
# See label_ and structure_.
491+
answer_list_item = node.parent.parent
492+
mc_node = answer_list_item.parent.parent
493+
label = chr(answer_list_item.parent.index(answer_list_item) + ord("a"))
494+
mc_node["runestone_options"]["alabel"] = label
495+
self.output.append("</statement>")
496+
self.output.append(
497+
'<feedback id="{divid}_opt_{alabel}">\n'.format(
498+
**mc_node["runestone_options"])
499+
)
500+
501+
453502
def depart_feedback_list_item(self, node):
454503
self.body.append("</li>")
455504

456505

506+
def depart_feedback_list_item_xml(self, node):
507+
self.output.append("</feedback>")
508+
457509
# backwards compatibility
510+
511+
458512
class MChoiceMF(MChoice):
459513
def run(self):
460514
raise self.error(

0 commit comments

Comments
 (0)