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
1fc4ac86
Commit
1fc4ac86
authored
Jun 06, 2013
by
Renzo Lucioni
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add feature showing current score next to problem title
parent
73e6e6f4
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
165 additions
and
25 deletions
+165
-25
common/lib/xmodule/xmodule/capa_module.py
+17
-15
common/lib/xmodule/xmodule/css/capa/display.scss
+8
-0
common/lib/xmodule/xmodule/js/fixtures/problem.html
+1
-1
common/lib/xmodule/xmodule/js/fixtures/problem_content.html
+3
-0
common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee
+19
-0
common/lib/xmodule/xmodule/js/src/capa/display.coffee
+21
-5
common/lib/xmodule/xmodule/tests/test_capa_module.py
+45
-0
lms/djangoapps/courseware/features/problems.feature
+42
-0
lms/djangoapps/courseware/features/problems.py
+5
-0
lms/templates/problem.html
+3
-3
lms/templates/problem_ajax.html
+1
-1
No files found.
common/lib/xmodule/xmodule/capa_module.py
View file @
1fc4ac86
...
...
@@ -309,7 +309,13 @@ class CapaModule(CapaFields, XModule):
d
=
self
.
get_score
()
score
=
d
[
'score'
]
total
=
d
[
'total'
]
if
total
>
0
:
if
self
.
weight
is
not
None
:
# scale score and total by weight/total:
score
=
score
*
self
.
weight
/
total
total
=
self
.
weight
try
:
return
Progress
(
score
,
total
)
except
(
TypeError
,
ValueError
):
...
...
@@ -321,11 +327,13 @@ class CapaModule(CapaFields, XModule):
"""
Return some html with data about the module
"""
progress
=
self
.
get_progress
()
return
self
.
system
.
render_template
(
'problem_ajax.html'
,
{
'element_id'
:
self
.
location
.
html_id
(),
'id'
:
self
.
id
,
'ajax_url'
:
self
.
system
.
ajax_url
,
'progress'
:
Progress
.
to_js_status_str
(
self
.
get_progress
())
'progress_status'
:
Progress
.
to_js_status_str
(
progress
),
'progress_detail'
:
Progress
.
to_js_detail_str
(
progress
),
})
def
check_button_name
(
self
):
...
...
@@ -485,8 +493,7 @@ class CapaModule(CapaFields, XModule):
"""
Return html for the problem.
Adds check, reset, save buttons as necessary based on the problem config
and state.
Adds check, reset, save buttons as necessary based on the problem config and state.
"""
try
:
...
...
@@ -516,13 +523,12 @@ class CapaModule(CapaFields, XModule):
'reset_button'
:
self
.
should_show_reset_button
(),
'save_button'
:
self
.
should_show_save_button
(),
'answer_available'
:
self
.
answer_available
(),
'ajax_url'
:
self
.
system
.
ajax_url
,
'attempts_used'
:
self
.
attempts
,
'attempts_allowed'
:
self
.
max_attempts
,
'progress'
:
self
.
get_progress
(),
}
html
=
self
.
system
.
render_template
(
'problem.html'
,
context
)
if
encapsulate
:
html
=
u'<div id="problem_{id}" class="problem" data-url="{ajax_url}">'
.
format
(
id
=
self
.
location
.
html_id
(),
ajax_url
=
self
.
system
.
ajax_url
...
...
@@ -584,6 +590,7 @@ class CapaModule(CapaFields, XModule):
result
.
update
({
'progress_changed'
:
after
!=
before
,
'progress_status'
:
Progress
.
to_js_status_str
(
after
),
'progress_detail'
:
Progress
.
to_js_detail_str
(
after
),
})
return
json
.
dumps
(
result
,
cls
=
ComplexEncoder
)
...
...
@@ -607,13 +614,7 @@ class CapaModule(CapaFields, XModule):
return
False
def
is_submitted
(
self
):
"""
Used to decide to show or hide RESET or CHECK buttons.
Means that student submitted problem and nothing more.
Problem can be completely wrong.
Pressing RESET button makes this function to return False.
"""
# used by conditional module
return
self
.
lcp
.
done
def
is_attempted
(
self
):
...
...
@@ -755,7 +756,8 @@ class CapaModule(CapaFields, XModule):
Used if we want to reconfirm we have the right thing e.g. after
several AJAX calls.
"""
return
{
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
return
{
'html'
:
self
.
get_problem_html
()}
@staticmethod
def
make_dict_of_responses
(
data
):
...
...
@@ -934,7 +936,7 @@ class CapaModule(CapaFields, XModule):
self
.
system
.
psychometrics_handler
(
self
.
get_state_for_lcp
())
# render problem into HTML
html
=
self
.
get_problem_html
(
encapsulate
=
False
)
html
=
self
.
get_problem_html
()
return
{
'success'
:
success
,
'contents'
:
html
,
...
...
@@ -1101,7 +1103,7 @@ class CapaModule(CapaFields, XModule):
self
.
system
.
track_function
(
'reset_problem'
,
event_info
)
return
{
'success'
:
True
,
'html'
:
self
.
get_problem_html
(
encapsulate
=
False
)}
'html'
:
self
.
get_problem_html
()}
class
CapaDescriptor
(
CapaFields
,
RawDescriptor
):
...
...
common/lib/xmodule/xmodule/css/capa/display.scss
View file @
1fc4ac86
...
...
@@ -3,6 +3,7 @@ h2 {
margin-bottom
:
15px
;
&
.problem-header
{
display
:
inline-block
;
section
.staff
{
margin-top
:
30px
;
font-size
:
80%
;
...
...
@@ -28,6 +29,13 @@ iframe[seamless]{
color
:
darken
(
$error-red
,
11%
);
}
section
.problem-progress
{
display
:
inline-block
;
color
:
#999
;
font-size
:
em
(
16
);
font-weight
:
100
;
padding-left
:
5px
;
}
section
.problem
{
@media
print
{
...
...
common/lib/xmodule/xmodule/js/fixtures/problem.html
View file @
1fc4ac86
<section
class=
'xmodule_display xmodule_CapaModule'
data-type=
'Problem'
>
<section
id=
'problem_1'
class=
'problems-wrapper'
class=
'problems-wrapper'
data-problem-id=
'i4x://edX/101/problem/Problem1'
data-url=
'/problem/Problem1'
>
</section>
...
...
common/lib/xmodule/xmodule/js/fixtures/problem_content.html
View file @
1fc4ac86
<h2
class=
"problem-header"
>
Problem Header
</h2>
<section
class=
'problem-progress'
>
</section>
<section
class=
"problem"
>
<p>
Problem Content
</p>
...
...
common/lib/xmodule/xmodule/js/spec/capa/display_spec.coffee
View file @
1fc4ac86
...
...
@@ -77,6 +77,25 @@ describe 'Problem', ->
[
@
problem
.
updateMathML
,
@
stubbedJax
,
$
(
'#input_example_1'
).
get
(
0
)]
]
describe
'renderProgressState'
,
->
beforeEach
->
@
problem
=
new
Problem
(
$
(
'.xmodule_display'
))
#@renderProgressState = @problem.renderProgressState
describe
'with a status of "none"'
,
->
it
'reports the number of points possible'
,
->
@
problem
.
el
.
data
(
'progress_status'
,
'none'
)
@
problem
.
el
.
data
(
'progress_detail'
,
'0/1'
)
@
problem
.
renderProgressState
()
expect
(
@
problem
.
$
(
'.problem-progress'
).
html
()).
toEqual
"(1 point possible)"
describe
'with any other valid status'
,
->
it
'reports the current score'
,
->
@
problem
.
el
.
data
(
'progress_status'
,
'foo'
)
@
problem
.
el
.
data
(
'progress_detail'
,
'1/1'
)
@
problem
.
renderProgressState
()
expect
(
@
problem
.
$
(
'.problem-progress'
).
html
()).
toEqual
"(1/1 points)"
describe
'render'
,
->
beforeEach
->
@
problem
=
new
Problem
(
$
(
'.xmodule_display'
))
...
...
common/lib/xmodule/xmodule/js/src/capa/display.coffee
View file @
1fc4ac86
...
...
@@ -35,15 +35,31 @@ class @Problem
@
$
(
'input.math'
).
each
(
index
,
element
)
=>
MathJax
.
Hub
.
Queue
[
@
refreshMath
,
null
,
element
]
renderProgressState
:
()
=>
detail
=
@
el
.
data
(
'progress_detail'
)
status
=
@
el
.
data
(
'progress_status'
)
progress
=
"(
#{
detail
}
points)"
if
status
==
'none'
and
detail
?
and
detail
.
indexOf
(
'/'
)
>
0
a
=
detail
.
split
(
'/'
)
possible
=
parseInt
(
a
[
1
])
if
possible
==
1
progress
=
"(
#{
possible
}
point possible)"
else
progress
=
"(
#{
possible
}
points possible)"
@
$
(
'.problem-progress'
).
html
(
progress
)
updateProgress
:
(
response
)
=>
if
response
.
progress_changed
@
el
.
attr
progress
:
response
.
progress_status
@
el
.
data
(
'progress_status'
,
response
.
progress_status
)
@
el
.
data
(
'progress_detail'
,
response
.
progress_detail
)
@
el
.
trigger
(
'progressChanged'
)
@
renderProgressState
()
forceUpdate
:
(
response
)
=>
@
el
.
attr
progress
:
response
.
progress_status
@
el
.
data
(
'progress_status'
,
response
.
progress_status
)
@
el
.
data
(
'progress_detail'
,
response
.
progress_detail
)
@
el
.
trigger
(
'progressChanged'
)
@
renderProgressState
()
queueing
:
=>
@
queued_items
=
@
$
(
".xqueue"
)
...
...
@@ -113,7 +129,7 @@ class @Problem
@
setupInputTypes
()
@
bind
()
@
queueing
()
@
renderProgressState
()
# TODO add hooks for problem types here by inspecting response.html and doing
# stuff if a div w a class is found
...
...
@@ -240,7 +256,7 @@ class @Problem
analytics
.
track
"Problem Checked"
,
problem_id
:
@
id
answers
:
@
answers
$
.
postWithPrefix
"
#{
@
url
}
/problem_check"
,
@
answers
,
(
response
)
=>
switch
response
.
success
when
'incorrect'
,
'correct'
...
...
common/lib/xmodule/xmodule/tests/test_capa_module.py
View file @
1fc4ac86
...
...
@@ -1233,6 +1233,51 @@ class CapaModuleTest(unittest.TestCase):
mock_log
.
exception
.
assert_called_once_with
(
'Got bad progress'
)
mock_log
.
reset_mock
()
@patch
(
'xmodule.capa_module.Progress'
)
def
test_get_progress_calculate_progress_fraction
(
self
,
mock_progress
):
"""
Check that score and total are calculated correctly for the progress fraction.
"""
module
=
CapaFactory
.
create
()
module
.
weight
=
1
module
.
get_progress
()
mock_progress
.
assert_called_with
(
0
,
1
)
other_module
=
CapaFactory
.
create
(
correct
=
True
)
other_module
.
weight
=
1
other_module
.
get_progress
()
mock_progress
.
assert_called_with
(
1
,
1
)
@patch
(
'xmodule.capa_module.Progress'
)
def
test_get_progress_calculate_progress_fraction
(
self
,
mock_progress
):
"""
Check that score and total are calculated correctly for the progress fraction.
"""
module
=
CapaFactory
.
create
()
module
.
get_progress
()
mock_progress
.
assert_called_with
(
0
,
1
)
other_module
=
CapaFactory
.
create
(
correct
=
True
)
other_module
.
get_progress
()
mock_progress
.
assert_called_with
(
1
,
1
)
def
test_get_html
(
self
):
"""
Check that get_html() calls get_progress() with no arguments.
"""
module
=
CapaFactory
.
create
()
module
.
get_progress
=
Mock
(
wraps
=
module
.
get_progress
)
module
.
get_html
()
module
.
get_progress
.
assert_called_once_with
()
def
test_get_problem
(
self
):
"""
Check that get_problem() returns the expected dictionary.
"""
module
=
CapaFactory
.
create
()
self
.
assertEquals
(
module
.
get_problem
(
"data"
),
{
'html'
:
module
.
get_problem_html
()})
class
ComplexEncoderTest
(
unittest
.
TestCase
):
def
test_default
(
self
):
...
...
lms/djangoapps/courseware/features/problems.feature
View file @
1fc4ac86
...
...
@@ -129,3 +129,45 @@ Feature: Answer problems
When
I press the button with the label
"Hide Answer(s)"
Then
the button with the label
"Show Answer(s)"
does appear
And
I should not see
"4.14159"
anywhere on the page
Scenario
:
I
can see my score on a problem when I answer it and after I reset it
Given
I am viewing a
"<ProblemType>"
problem
When
I answer a
"<ProblemType>"
problem
"<Correctness>ly"
Then
I should see a score of
"<Score>"
When
I reset the problem
Then
I should see a score of
"<Points Possible>"
Examples
:
|
ProblemType
|
Correctness
|
Score
|
Points
Possible
|
|
drop
down
|
correct
|
1/1
points
|
1
point
possible
|
|
drop
down
|
incorrect
|
1
point
possible
|
1
point
possible
|
|
multiple
choice
|
correct
|
1/1
points
|
1
point
possible
|
|
multiple
choice
|
incorrect
|
1
point
possible
|
1
point
possible
|
|
checkbox
|
correct
|
1/1
points
|
1
point
possible
|
|
checkbox
|
incorrect
|
1
point
possible
|
1
point
possible
|
|
radio
|
correct
|
1/1
points
|
1
point
possible
|
|
radio
|
incorrect
|
1
point
possible
|
1
point
possible
|
|
string
|
correct
|
1/1
points
|
1
point
possible
|
|
string
|
incorrect
|
1
point
possible
|
1
point
possible
|
|
numerical
|
correct
|
1/1
points
|
1
point
possible
|
|
numerical
|
incorrect
|
1
point
possible
|
1
point
possible
|
|
formula
|
correct
|
1/1
points
|
1
point
possible
|
|
formula
|
incorrect
|
1
point
possible
|
1
point
possible
|
|
script
|
correct
|
2/2
points
|
2
points
possible
|
|
script
|
incorrect
|
2
points
possible
|
2
points
possible
|
Scenario
:
I
can see my score on a problem to which I submit a blank answer
Given
I am viewing a
"<ProblemType>"
problem
When
I check a problem
Then
I should see a score of
"<Points Possible>"
Examples
:
|
ProblemType
|
Points
Possible
|
|
drop
down
|
1
point
possible
|
|
multiple
choice
|
1
point
possible
|
|
checkbox
|
1
point
possible
|
|
radio
|
1
point
possible
|
|
string
|
1
point
possible
|
|
numerical
|
1
point
possible
|
|
formula
|
1
point
possible
|
|
script
|
2
points
possible
|
lms/djangoapps/courseware/features/problems.py
View file @
1fc4ac86
...
...
@@ -142,6 +142,11 @@ def button_with_label_present(_step, buttonname, doesnt_appear):
assert
world
.
browser
.
is_text_present
(
buttonname
,
wait_time
=
5
)
@step
(
u'I should see a score of "([^"]*)"$'
)
def
see_score
(
_step
,
score
):
assert
world
.
browser
.
is_text_present
(
score
)
@step
(
u'My "([^"]*)" answer is marked "([^"]*)"'
)
def
assert_answer_mark
(
step
,
problem_type
,
correctness
):
"""
...
...
lms/templates/problem.html
View file @
1fc4ac86
<
%
namespace
name=
'static'
file=
'static_content.html'
/>
<h2
class=
"problem-header"
>
${ problem['name'] }
% if problem['weight'] != 1 and problem['weight'] is not None:
: ${ problem['weight'] } points
% endif
</h2>
<section
class=
"problem-progress"
>
</section>
<section
class=
"problem"
>
${ problem['html'] }
...
...
lms/templates/problem_ajax.html
View file @
1fc4ac86
<section
id=
"problem_${element_id}"
class=
"problems-wrapper"
data-problem-id=
"${id}"
data-url=
"${ajax_url}"
progress=
"${progress
}"
></section>
<section
id=
"problem_${element_id}"
class=
"problems-wrapper"
data-problem-id=
"${id}"
data-url=
"${ajax_url}"
data-progress_status=
"${progress_status}"
data-progress_detail=
"${progress_detail
}"
></section>
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