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
77c208a1
Commit
77c208a1
authored
Nov 18, 2013
by
polesye
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
BLD-474: Allow multiple answers for string response.
parent
d526027d
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
91 additions
and
19 deletions
+91
-19
CHANGELOG.rst
+2
-0
cms/templates/widgets/problem-edit.html
+3
-1
common/lib/capa/capa/responsetypes.py
+27
-8
common/lib/capa/capa/tests/test_responsetypes.py
+42
-1
common/lib/xmodule/xmodule/js/spec/problem/edit_spec.coffee
+0
-0
common/lib/xmodule/xmodule/js/src/problem/edit.coffee
+17
-9
No files found.
CHANGELOG.rst
View file @
77c208a1
...
@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
...
@@ -5,6 +5,8 @@ These are notable changes in edx-platform. This is a rolling list of changes,
in roughly chronological order, most recent first. Add your entries at or near
in roughly chronological order, most recent first. Add your entries at or near
the top. Include a label indicating the component affected.
the top. Include a label indicating the component affected.
Blades: Allow multiple strings as the correct answer to a string response question. BLD-474.
Blades: a11y - Videos will alert screenreaders when the video is over.
Blades: a11y - Videos will alert screenreaders when the video is over.
LMS: Trap focus on the loading element when a user loads more threads
LMS: Trap focus on the loading element when a user loads more threads
...
...
cms/templates/widgets/problem-edit.html
View file @
77c208a1
...
@@ -75,7 +75,9 @@
...
@@ -75,7 +75,9 @@
<
img
src
=
"${static.url("
img
/
string
-
example
.
png
")}"
/>
<
img
src
=
"${static.url("
img
/
string
-
example
.
png
")}"
/>
<
/div
>
<
/div
>
<
div
class
=
"col"
>
<
div
class
=
"col"
>
<
pre
><
code
>=
dog
<
/code></
pre
>
<
pre
><
code
>=
dog
or
=
cat
or
=
mouse
<
/code></
pre
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
div
class
=
"row"
>
<
div
class
=
"row"
>
...
...
common/lib/capa/capa/responsetypes.py
View file @
77c208a1
...
@@ -946,17 +946,34 @@ class NumericalResponse(LoncapaResponse):
...
@@ -946,17 +946,34 @@ class NumericalResponse(LoncapaResponse):
class
StringResponse
(
LoncapaResponse
):
class
StringResponse
(
LoncapaResponse
):
'''
This response type allows one or more answers. Use `_or_` separator to set
more than 1 answer.
Example:
# One answer
<stringresponse answer="Michigan">
<textline size="20" />
</stringresponse >
# Multiple answers
<stringresponse answer="Martin Luther King_or_Dr. Martin Luther King Jr.">
<textline size="20" />
</stringresponse >
'''
response_tag
=
'stringresponse'
response_tag
=
'stringresponse'
hint_tag
=
'stringhint'
hint_tag
=
'stringhint'
allowed_inputfields
=
[
'textline'
]
allowed_inputfields
=
[
'textline'
]
required_attributes
=
[
'answer'
]
required_attributes
=
[
'answer'
]
max_inputfields
=
1
max_inputfields
=
1
correct_answer
=
None
correct_answer
=
[]
SEPARATOR
=
'_or_'
def
setup_response
(
self
):
def
setup_response
(
self
):
self
.
correct_answer
=
contextualize_text
(
self
.
correct_answer
=
[
contextualize_text
(
answer
,
self
.
context
)
.
strip
()
self
.
xml
.
get
(
'answer'
),
self
.
context
)
.
strip
()
for
answer
in
self
.
xml
.
get
(
'answer'
)
.
split
(
self
.
SEPARATOR
)]
def
get_score
(
self
,
student_answers
):
def
get_score
(
self
,
student_answers
):
'''Grade a string response '''
'''Grade a string response '''
...
@@ -966,23 +983,25 @@ class StringResponse(LoncapaResponse):
...
@@ -966,23 +983,25 @@ class StringResponse(LoncapaResponse):
def
check_string
(
self
,
expected
,
given
):
def
check_string
(
self
,
expected
,
given
):
if
self
.
xml
.
get
(
'type'
)
==
'ci'
:
if
self
.
xml
.
get
(
'type'
)
==
'ci'
:
return
given
.
lower
()
==
expected
.
lower
()
return
given
.
lower
()
in
[
i
.
lower
()
for
i
in
expected
]
return
given
==
expected
return
given
in
expected
def
check_hint_condition
(
self
,
hxml_set
,
student_answers
):
def
check_hint_condition
(
self
,
hxml_set
,
student_answers
):
given
=
student_answers
[
self
.
answer_id
]
.
strip
()
given
=
student_answers
[
self
.
answer_id
]
.
strip
()
hints_to_show
=
[]
hints_to_show
=
[]
for
hxml
in
hxml_set
:
for
hxml
in
hxml_set
:
name
=
hxml
.
get
(
'name'
)
name
=
hxml
.
get
(
'name'
)
correct_answer
=
contextualize_text
(
hxml
.
get
(
'answer'
),
self
.
context
)
.
strip
()
correct_answer
=
[
contextualize_text
(
answer
,
self
.
context
)
.
strip
()
for
answer
in
hxml
.
get
(
'answer'
)
.
split
(
self
.
SEPARATOR
)]
if
self
.
check_string
(
correct_answer
,
given
):
if
self
.
check_string
(
correct_answer
,
given
):
hints_to_show
.
append
(
name
)
hints_to_show
.
append
(
name
)
log
.
debug
(
'hints_to_show =
%
s'
,
hints_to_show
)
log
.
debug
(
'hints_to_show =
%
s'
,
hints_to_show
)
return
hints_to_show
return
hints_to_show
def
get_answers
(
self
):
def
get_answers
(
self
):
return
{
self
.
answer_id
:
self
.
correct_answer
}
return
{
self
.
answer_id
:
' <b>or</b> '
.
join
(
self
.
correct_answer
)
}
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
...
...
common/lib/capa/capa/tests/test_responsetypes.py
View file @
77c208a1
...
@@ -500,6 +500,7 @@ class StringResponseTest(ResponseTest):
...
@@ -500,6 +500,7 @@ class StringResponseTest(ResponseTest):
xml_factory_class
=
StringResponseXMLFactory
xml_factory_class
=
StringResponseXMLFactory
def
test_case_sensitive
(
self
):
def
test_case_sensitive
(
self
):
# Test single answer
problem
=
self
.
build_problem
(
answer
=
"Second"
,
case_sensitive
=
True
)
problem
=
self
.
build_problem
(
answer
=
"Second"
,
case_sensitive
=
True
)
# Exact string should be correct
# Exact string should be correct
...
@@ -509,7 +510,20 @@ class StringResponseTest(ResponseTest):
...
@@ -509,7 +510,20 @@ class StringResponseTest(ResponseTest):
self
.
assert_grade
(
problem
,
"Other String"
,
"incorrect"
)
self
.
assert_grade
(
problem
,
"Other String"
,
"incorrect"
)
self
.
assert_grade
(
problem
,
"second"
,
"incorrect"
)
self
.
assert_grade
(
problem
,
"second"
,
"incorrect"
)
# Test multiple answers
answers
=
[
"Second"
,
"Third"
,
"Fourth"
]
problem
=
self
.
build_problem
(
answer
=
"_or_"
.
join
(
answers
),
case_sensitive
=
True
)
for
answer
in
answers
:
# Exact string should be correct
self
.
assert_grade
(
problem
,
answer
,
"correct"
)
# Other strings and the lowercase version of the string are incorrect
self
.
assert_grade
(
problem
,
"Other String"
,
"incorrect"
)
self
.
assert_grade
(
problem
,
"second"
,
"incorrect"
)
def
test_case_insensitive
(
self
):
def
test_case_insensitive
(
self
):
# Test single answer
problem
=
self
.
build_problem
(
answer
=
"Second"
,
case_sensitive
=
False
)
problem
=
self
.
build_problem
(
answer
=
"Second"
,
case_sensitive
=
False
)
# Both versions of the string should be allowed, regardless
# Both versions of the string should be allowed, regardless
...
@@ -520,9 +534,28 @@ class StringResponseTest(ResponseTest):
...
@@ -520,9 +534,28 @@ class StringResponseTest(ResponseTest):
# Other strings are not allowed
# Other strings are not allowed
self
.
assert_grade
(
problem
,
"Other String"
,
"incorrect"
)
self
.
assert_grade
(
problem
,
"Other String"
,
"incorrect"
)
# Test multiple answers
answers
=
[
"Second"
,
"Third"
,
"Fourth"
]
problem
=
self
.
build_problem
(
answer
=
"_or_"
.
join
(
answers
),
case_sensitive
=
False
)
for
answer
in
answers
:
# Exact string should be correct
self
.
assert_grade
(
problem
,
answer
,
"correct"
)
self
.
assert_grade
(
problem
,
answer
.
lower
(),
"correct"
)
# Other strings and the lowercase version of the string are incorrect
self
.
assert_grade
(
problem
,
"Other String"
,
"incorrect"
)
def
test_hints
(
self
):
def
test_hints
(
self
):
multiple_answers
=
[
"Martin Luther King Junior"
,
"Doctor Martin Luther King Junior"
,
"Dr. Martin Luther King Jr."
,
"Martin Luther King"
]
hints
=
[(
"wisconsin"
,
"wisc"
,
"The state capital of Wisconsin is Madison"
),
hints
=
[(
"wisconsin"
,
"wisc"
,
"The state capital of Wisconsin is Madison"
),
(
"minnesota"
,
"minn"
,
"The state capital of Minnesota is St. Paul"
)]
(
"minnesota"
,
"minn"
,
"The state capital of Minnesota is St. Paul"
),
(
"_or_"
.
join
(
multiple_answers
),
"mlk"
,
"He lead the civil right movement in the United States of America."
)]
problem
=
self
.
build_problem
(
answer
=
"Michigan"
,
problem
=
self
.
build_problem
(
answer
=
"Michigan"
,
case_sensitive
=
False
,
case_sensitive
=
False
,
...
@@ -550,6 +583,14 @@ class StringResponseTest(ResponseTest):
...
@@ -550,6 +583,14 @@ class StringResponseTest(ResponseTest):
correct_map
=
problem
.
grade_answers
(
input_dict
)
correct_map
=
problem
.
grade_answers
(
input_dict
)
self
.
assertEquals
(
correct_map
.
get_hint
(
'1_2_1'
),
""
)
self
.
assertEquals
(
correct_map
.
get_hint
(
'1_2_1'
),
""
)
# We should get the same hint for each answer
for
answer
in
multiple_answers
:
input_dict
=
{
'1_2_1'
:
answer
}
correct_map
=
problem
.
grade_answers
(
input_dict
)
self
.
assertEquals
(
correct_map
.
get_hint
(
'1_2_1'
),
"He lead the civil right movement in the United States of America."
)
def
test_computed_hints
(
self
):
def
test_computed_hints
(
self
):
problem
=
self
.
build_problem
(
problem
=
self
.
build_problem
(
answer
=
"Michigan"
,
answer
=
"Michigan"
,
...
...
common/lib/xmodule/xmodule/js/spec/problem/edit_spec.coffee
View file @
77c208a1
This diff is collapsed.
Click to expand it.
common/lib/xmodule/xmodule/js/src/problem/edit.coffee
View file @
77c208a1
...
@@ -228,11 +228,13 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
...
@@ -228,11 +228,13 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
});
});
//
replace
string
and
numerical
//
replace
string
and
numerical
xml
=
xml
.
replace
(
/^\=\s*(.*?$)/gm
,
function
(
match
,
p
)
{
xml
=
xml
.
replace
(
/(^\=\s*(.*?$)(\n*or\=\s*(.*?$))*)+/gm
,
function
(
match
,
p
)
{
var
string
;
var
string
,
var
floatValue
=
parseFloat
(
p
);
answersList
=
p
.
replace
(
/^(or)?=\s*/gm
,
''
).
split
(
'
\n
'
),
floatValue
=
parseFloat
(
answersList
[
0
]);
if
(
!
isNaN
(
floatValue
))
{
if
(
!
isNaN
(
floatValue
))
{
var
params
=
/(.*?)\+\-\s*(.*?$)/
.
exec
(
p
);
var
params
=
/(.*?)\+\-\s*(.*?$)/
.
exec
(
answersList
[
0
]
);
if
(
params
)
{
if
(
params
)
{
string
=
'<numericalresponse answer="'
+
floatValue
+
'">
\n
'
;
string
=
'<numericalresponse answer="'
+
floatValue
+
'">
\n
'
;
string
+=
' <responseparam type="tolerance" default="'
+
params
[
2
]
+
'" />
\n
'
;
string
+=
' <responseparam type="tolerance" default="'
+
params
[
2
]
+
'" />
\n
'
;
...
@@ -242,10 +244,16 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
...
@@ -242,10 +244,16 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
string
+=
' <formulaequationinput />
\n
'
;
string
+=
' <formulaequationinput />
\n
'
;
string
+=
'</numericalresponse>
\n\n
'
;
string
+=
'</numericalresponse>
\n\n
'
;
}
else
{
}
else
{
string
=
'<stringresponse answer="'
+
p
+
'" type="ci">
\n
<textline size="20"/>
\n
</stringresponse>
\n\n
'
;
var
answers
=
[];
for
(
var
i
=
0
;
i
<
answersList
.
length
;
i
++
)
{
answers
.
push
(
answersList
[
i
])
}
string
=
'<stringresponse answer="'
+
answers
.
join
(
'_or_'
)
+
'" type="ci">
\n
<textline size="20"/>
\n
</stringresponse>
\n\n
'
;
}
}
return
string
;
return
string
;
});
});
//
replace
selects
//
replace
selects
xml
=
xml
.
replace
(
/\[\[(.+?)\]\]/g
,
function
(
match
,
p
)
{
xml
=
xml
.
replace
(
/\[\[(.+?)\]\]/g
,
function
(
match
,
p
)
{
...
@@ -262,13 +270,13 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
...
@@ -262,13 +270,13 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
selectString
+=
'</optionresponse>
\n\n
'
;
selectString
+=
'</optionresponse>
\n\n
'
;
return
selectString
;
return
selectString
;
});
});
//
replace
explanations
//
replace
explanations
xml
=
xml
.
replace
(
/\[explanation\]\n?([^\]]*)\[\/?explanation\]/gmi
,
function
(
match
,
p1
)
{
xml
=
xml
.
replace
(
/\[explanation\]\n?([^\]]*)\[\/?explanation\]/gmi
,
function
(
match
,
p1
)
{
var
selectString
=
'<solution>
\n
<div class="detailed-solution">
\n
Explanation
\n\n
'
+
p1
+
'
\n
</div>
\n
</solution>'
;
var
selectString
=
'<solution>
\n
<div class="detailed-solution">
\n
Explanation
\n\n
'
+
p1
+
'
\n
</div>
\n
</solution>'
;
return
selectString
;
return
selectString
;
});
});
//
replace
code
blocks
//
replace
code
blocks
xml
=
xml
.
replace
(
/\[code\]\n?([^\]]*)\[\/?code\]/gmi
,
function
(
match
,
p1
)
{
xml
=
xml
.
replace
(
/\[code\]\n?([^\]]*)\[\/?code\]/gmi
,
function
(
match
,
p1
)
{
var
selectString
=
'<pre><code>
\n
'
+
p1
+
'</code></pre>'
;
var
selectString
=
'<pre><code>
\n
'
+
p1
+
'</code></pre>'
;
...
@@ -293,7 +301,7 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
...
@@ -293,7 +301,7 @@ class @MarkdownEditingDescriptor extends XModule.Descriptor
//
rid
white
space
//
rid
white
space
xml
=
xml
.
replace
(
/\n\n\n/g
,
'
\n
'
);
xml
=
xml
.
replace
(
/\n\n\n/g
,
'
\n
'
);
/
/ surround w/
problem
tag
/
/ surround w/
problem
tag
xml
=
'<problem>
\n
'
+
xml
+
'
\n
</problem>'
;
xml
=
'<problem>
\n
'
+
xml
+
'
\n
</problem>'
;
...
...
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