Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
f1151eeb
Commit
f1151eeb
authored
Feb 18, 2014
by
Nick Parlante
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix bug with multiple responses per problem
parent
e8485060
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
55 additions
and
10 deletions
+55
-10
common/lib/capa/capa/responsetypes.py
+12
-5
common/lib/capa/capa/tests/test_answer_pool.py
+6
-4
common/lib/capa/capa/tests/test_shuffle.py
+34
-0
common/lib/xmodule/xmodule/capa_base.py
+3
-1
No files found.
common/lib/capa/capa/responsetypes.py
View file @
f1151eeb
...
...
@@ -825,8 +825,8 @@ class MultipleChoiceResponse(LoncapaResponse):
using the regular (non-masked) names.
Fails loudly if called on a response that is not masking.
"""
choice
groups
=
self
.
xml
.
xpath
(
'//choicegroup
'
)
return
[
self
.
unmask_name
(
choice
.
get
(
"name"
))
for
choice
in
choice
groups
[
0
]
.
getchildren
()
]
choice
s
=
self
.
xml
.
xpath
(
'choicegroup/choice
'
)
return
[
self
.
unmask_name
(
choice
.
get
(
"name"
))
for
choice
in
choice
s
]
def
do_shuffle
(
self
,
tree
):
"""
...
...
@@ -834,10 +834,12 @@ class MultipleChoiceResponse(LoncapaResponse):
based on the seed. Otherwise does nothing.
Does nothing if the tree has already been processed.
"""
choicegroups
=
tree
.
xpath
(
'//choicegroup[@shuffle="true"]'
)
# The tree is already pared down to this <multichoiceresponse> so this query just
# gets the child choicegroup (i.e. no leading //)
choicegroups
=
tree
.
xpath
(
'choicegroup[@shuffle="true"]'
)
if
choicegroups
:
if
len
(
choicegroups
)
>
1
:
raise
LoncapaProblemError
(
'We support
at most one shuffled choicegroup
'
)
raise
LoncapaProblemError
(
'We support
one shuffled choicegroup per response
'
)
choicegroup
=
choicegroups
[
0
]
# Note that this tree has been processed.
if
choicegroup
.
get
(
'shuffle-done'
)
is
not
None
:
...
...
@@ -890,11 +892,16 @@ class MultipleChoiceResponse(LoncapaResponse):
pool size. If that attribute is zero or not present, no operation is performed.
Calling this a second time does nothing.
"""
choicegroups
=
tree
.
xpath
(
"
//
choicegroup[@answer-pool]"
)
choicegroups
=
tree
.
xpath
(
"choicegroup[@answer-pool]"
)
# Uses self.seed -- but want to randomize every time reaches this problem,
# so problem's "randomization" should be set to "always"
rnd
=
random
.
Random
(
self
.
context
[
'seed'
])
# TODO: currently, each choicegroup uses the seed from the problem.
# This has the unfortunate effect of making choicegroups look similar
# when we have many in one problem. Could perturb the rnd a little
# per choicegroup so they look different.
for
choicegroup
in
choicegroups
:
num_str
=
choicegroup
.
get
(
'answer-pool'
)
...
...
common/lib/capa/capa/tests/test_answer_pool.py
View file @
f1151eeb
...
...
@@ -73,7 +73,7 @@ class CapaAnswerPoolTest(unittest.TestCase):
<p>What is the correct answer?</p>
<multiplechoiceresponse>
<choicegroup type="MultipleChoice" answer-pool="4">
<choicegroup type="MultipleChoice" answer-pool="4
">
<choice correct="false">wrong-1</choice>
<choice correct="false">wrong-2</choice>
<choice correct="true" explanation-id="solution1">correct-1</choice>
...
...
@@ -361,9 +361,11 @@ class CapaAnswerPoolTest(unittest.TestCase):
problem
=
new_loncapa_problem
(
xml_str
,
seed
=
723
)
the_html
=
problem
.
get_html
()
print
the_html
str1
=
r"<div>.*\[.*'wrong-3'.*'correct-2'.*'wrong-2'.*'wrong-4'.*\].*</div>"
str2
=
r"<div>.*\[.*'wrong-2'.*'wrong-1'.*'correct-2'.*\].*</div>"
str2
=
r"<div>.*\[.*'correct-2'.*'wrong-2'.*'wrong-3'.*\].*</div>"
str3
=
r"<div>\{.*'1_solution_2'.*\}</div>"
str4
=
r"<div>\{.*'1_solution_4'.*\}</div>"
...
...
@@ -447,9 +449,9 @@ class CapaAnswerPoolTest(unittest.TestCase):
the_html
=
problem
.
get_html
()
str1
=
r"<div>.*\[.*'wrong-4'.*'wrong-3'.*'correct-1'.*\].*</div>"
str2
=
r"<div>.*\[.*'wrong-
2'.*'wrong-3'.*'wrong-4'.*'correct-2
'.*\].*</div>"
str2
=
r"<div>.*\[.*'wrong-
1'.*'wrong-4'.*'wrong-3'.*'correct-1
'.*\].*</div>"
str3
=
r"<div>\{.*'1_solution_1'.*\}</div>"
str4
=
r"<div>\{.*'1_solution_
4
'.*\}</div>"
str4
=
r"<div>\{.*'1_solution_
3
'.*\}</div>"
self
.
assertRegexpMatches
(
the_html
,
str1
)
self
.
assertRegexpMatches
(
the_html
,
str2
)
...
...
common/lib/capa/capa/tests/test_shuffle.py
View file @
f1151eeb
...
...
@@ -245,3 +245,37 @@ class CapaShuffleTest(unittest.TestCase):
problem
=
new_loncapa_problem
(
xml_str
,
seed
=
0
)
the_html
=
problem
.
get_html
()
self
.
assertRegexpMatches
(
the_html
,
r"<div>.*\[.*'A'.*'Mid'.*'Mid'.*'C'.*'D'.*\].*</div>"
)
def
test_multiple_shuffle_responses
(
self
):
xml_str
=
textwrap
.
dedent
(
"""
<problem>
<multiplechoiceresponse>
<choicegroup type="MultipleChoice" shuffle="true">
<choice correct="false">Apple</choice>
<choice correct="false">Banana</choice>
<choice correct="false">Chocolate</choice>
<choice correct ="true">Donut</choice>
</choicegroup>
</multiplechoiceresponse>
<p>Here is some text</p>
<multiplechoiceresponse>
<choicegroup type="MultipleChoice" shuffle="true">
<choice correct="false">A</choice>
<choice correct="false">B</choice>
<choice correct="false">C</choice>
<choice correct ="true">D</choice>
</choicegroup>
</multiplechoiceresponse>
</problem>
"""
)
problem
=
new_loncapa_problem
(
xml_str
,
seed
=
0
)
orig_html
=
problem
.
get_html
()
self
.
assertEqual
(
orig_html
,
problem
.
get_html
(),
'should be able to call get_html() twice'
)
html
=
orig_html
.
replace
(
'
\n
'
,
' '
)
# avoid headaches with .* matching
self
.
assertRegexpMatches
(
html
,
r"<div>.*\[.*'Banana'.*'Apple'.*'Chocolate'.*'Donut'.*\].*</div>.*"
+
r"<div>.*\[.*'B'.*'A'.*'C'.*'D'.*\].*</div>"
)
responses
=
problem
.
responders
.
values
()
self
.
assertTrue
(
hasattr
(
responses
[
0
],
'is_masked'
))
self
.
assertTrue
(
hasattr
(
responses
[
1
],
'is_masked'
))
self
.
assertEqual
(
responses
[
0
]
.
unmask_order
(),
[
'choice_1'
,
'choice_0'
,
'choice_2'
,
'choice_3'
])
self
.
assertEqual
(
responses
[
1
]
.
unmask_order
(),
[
'choice_1'
,
'choice_0'
,
'choice_2'
,
'choice_3'
])
common/lib/xmodule/xmodule/capa_base.py
View file @
f1151eeb
...
...
@@ -1044,7 +1044,9 @@ class CapaMixin(CapaFields):
event_info
[
'state'
][
'student_answers'
][
response
.
answer_id
]
=
response
.
unmask_name
(
answer
)
# 3. Record the shuffled ordering
event_info
[
'display_order'
]
=
{
response
.
answer_id
:
response
.
unmask_order
()}
if
not
'display_order'
in
event_info
:
event_info
[
'display_order'
]
=
{}
event_info
[
'display_order'
][
response
.
answer_id
]
=
response
.
unmask_order
()
def
pretty_print_seconds
(
self
,
num_seconds
):
"""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment