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
ee5ffedf
Commit
ee5ffedf
authored
May 10, 2013
by
Brian Wilson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clean up task progress javascript. Add before/after scores to tracking of regrading requests.
parent
0d38789a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
43 additions
and
27 deletions
+43
-27
common/lib/xmodule/xmodule/capa_module.py
+36
-21
common/lib/xmodule/xmodule/tests/test_conditional.py
+5
-6
lms/envs/test.py
+2
-0
No files found.
common/lib/xmodule/xmodule/capa_module.py
View file @
ee5ffedf
...
@@ -655,7 +655,7 @@ class CapaModule(CapaFields, XModule):
...
@@ -655,7 +655,7 @@ class CapaModule(CapaFields, XModule):
@staticmethod
@staticmethod
def
make_dict_of_responses
(
get
):
def
make_dict_of_responses
(
get
):
'''Make dictionary of student responses (aka "answers")
'''Make dictionary of student responses (aka "answers")
get is POST dictionary (Djano QueryDict).
get is POST dictionary (Djan
g
o QueryDict).
The *get* dict has keys of the form 'x_y', which are mapped
The *get* dict has keys of the form 'x_y', which are mapped
to key 'y' in the returned dict. For example,
to key 'y' in the returned dict. For example,
...
@@ -739,13 +739,13 @@ class CapaModule(CapaFields, XModule):
...
@@ -739,13 +739,13 @@ class CapaModule(CapaFields, XModule):
# Too late. Cannot submit
# Too late. Cannot submit
if
self
.
closed
():
if
self
.
closed
():
event_info
[
'failure'
]
=
'closed'
event_info
[
'failure'
]
=
'closed'
self
.
system
.
track_function
(
'
save_
problem_check_fail'
,
event_info
)
self
.
system
.
track_function
(
'problem_check_fail'
,
event_info
)
raise
NotFoundError
(
'Problem is closed'
)
raise
NotFoundError
(
'Problem is closed'
)
# Problem submitted. Student should reset before checking again
# Problem submitted. Student should reset before checking again
if
self
.
done
and
self
.
rerandomize
==
"always"
:
if
self
.
done
and
self
.
rerandomize
==
"always"
:
event_info
[
'failure'
]
=
'unreset'
event_info
[
'failure'
]
=
'unreset'
self
.
system
.
track_function
(
'
save_
problem_check_fail'
,
event_info
)
self
.
system
.
track_function
(
'problem_check_fail'
,
event_info
)
raise
NotFoundError
(
'Problem must be reset before it can be checked again'
)
raise
NotFoundError
(
'Problem must be reset before it can be checked again'
)
# Problem queued. Students must wait a specified waittime before they are allowed to submit
# Problem queued. Students must wait a specified waittime before they are allowed to submit
...
@@ -800,7 +800,7 @@ class CapaModule(CapaFields, XModule):
...
@@ -800,7 +800,7 @@ class CapaModule(CapaFields, XModule):
event_info
[
'correct_map'
]
=
correct_map
.
get_dict
()
event_info
[
'correct_map'
]
=
correct_map
.
get_dict
()
event_info
[
'success'
]
=
success
event_info
[
'success'
]
=
success
event_info
[
'attempts'
]
=
self
.
attempts
event_info
[
'attempts'
]
=
self
.
attempts
self
.
system
.
track_function
(
'
save_
problem_check'
,
event_info
)
self
.
system
.
track_function
(
'problem_check'
,
event_info
)
if
hasattr
(
self
.
system
,
'psychometrics_handler'
):
# update PsychometricsData using callback
if
hasattr
(
self
.
system
,
'psychometrics_handler'
):
# update PsychometricsData using callback
self
.
system
.
psychometrics_handler
(
self
.
get_state_for_lcp
())
self
.
system
.
psychometrics_handler
(
self
.
get_state_for_lcp
())
...
@@ -813,21 +813,33 @@ class CapaModule(CapaFields, XModule):
...
@@ -813,21 +813,33 @@ class CapaModule(CapaFields, XModule):
}
}
def
regrade_problem
(
self
):
def
regrade_problem
(
self
):
''' Checks whether answers to a problem are correct, and
"""
returns a map of correct/incorrect answers:
Checks whether the existing answers to a problem are correct.
{'success' : 'correct' | 'incorrect' | AJAX alert msg string,
This is called when the correct answer to a problem has been changed,
'contents' : html}
and the grade should be re-evaluated.
'''
Returns a dict with one key:
{'success' : 'correct' | 'incorrect' | AJAX alert msg string }
Raises NotFoundError if called on a problem that has not yet been answered
(since this is avoidable). Returns the error messages for exceptions
occurring while performing the regrading, rather than throwing them.
"""
event_info
=
dict
()
event_info
=
dict
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
if
not
self
.
done
:
if
not
self
.
done
:
event_info
[
'failure'
]
=
'unanswered'
event_info
[
'failure'
]
=
'unanswered'
self
.
system
.
track_function
(
'
save_
problem_regrade_fail'
,
event_info
)
self
.
system
.
track_function
(
'problem_regrade_fail'
,
event_info
)
raise
NotFoundError
(
'Problem must be answered before it can be graded again'
)
raise
NotFoundError
(
'Problem must be answered before it can be graded again'
)
# get old score, for comparison:
orig_score
=
self
.
lcp
.
get_score
()
event_info
[
'orig_score'
]
=
orig_score
[
'score'
]
event_info
[
'orig_max_score'
]
=
orig_score
[
'total'
]
try
:
try
:
correct_map
=
self
.
lcp
.
regrade_existing_answers
()
correct_map
=
self
.
lcp
.
regrade_existing_answers
()
# regrading should have no effect on attempts, so don't
# regrading should have no effect on attempts, so don't
...
@@ -835,8 +847,12 @@ class CapaModule(CapaFields, XModule):
...
@@ -835,8 +847,12 @@ class CapaModule(CapaFields, XModule):
self
.
set_state_from_lcp
()
self
.
set_state_from_lcp
()
except
StudentInputError
as
inst
:
except
StudentInputError
as
inst
:
log
.
exception
(
"StudentInputError in capa_module:problem_regrade"
)
log
.
exception
(
"StudentInputError in capa_module:problem_regrade"
)
event_info
[
'failure'
]
=
'student_input_error'
self
.
system
.
track_function
(
'problem_regrade_fail'
,
event_info
)
return
{
'success'
:
inst
.
message
}
return
{
'success'
:
inst
.
message
}
except
Exception
,
err
:
except
Exception
,
err
:
event_info
[
'failure'
]
=
'unexpected'
self
.
system
.
track_function
(
'problem_regrade_fail'
,
event_info
)
if
self
.
system
.
DEBUG
:
if
self
.
system
.
DEBUG
:
msg
=
"Error checking problem: "
+
str
(
err
)
msg
=
"Error checking problem: "
+
str
(
err
)
msg
+=
'
\n
Traceback:
\n
'
+
traceback
.
format_exc
()
msg
+=
'
\n
Traceback:
\n
'
+
traceback
.
format_exc
()
...
@@ -845,6 +861,10 @@ class CapaModule(CapaFields, XModule):
...
@@ -845,6 +861,10 @@ class CapaModule(CapaFields, XModule):
self
.
publish_grade
()
self
.
publish_grade
()
new_score
=
self
.
lcp
.
get_score
()
event_info
[
'new_score'
]
=
new_score
[
'score'
]
event_info
[
'new_max_score'
]
=
new_score
[
'total'
]
# success = correct if ALL questions in this problem are correct
# success = correct if ALL questions in this problem are correct
success
=
'correct'
success
=
'correct'
for
answer_id
in
correct_map
:
for
answer_id
in
correct_map
:
...
@@ -856,25 +876,20 @@ class CapaModule(CapaFields, XModule):
...
@@ -856,25 +876,20 @@ class CapaModule(CapaFields, XModule):
event_info
[
'correct_map'
]
=
correct_map
.
get_dict
()
event_info
[
'correct_map'
]
=
correct_map
.
get_dict
()
event_info
[
'success'
]
=
success
event_info
[
'success'
]
=
success
event_info
[
'attempts'
]
=
self
.
attempts
event_info
[
'attempts'
]
=
self
.
attempts
self
.
system
.
track_function
(
'
save_
problem_regrade'
,
event_info
)
self
.
system
.
track_function
(
'problem_regrade'
,
event_info
)
# TODO: figure out if psychometrics should be called on regrading requests
# TODO: figure out if psychometrics should be called on regrading requests
if
hasattr
(
self
.
system
,
'psychometrics_handler'
):
# update PsychometricsData using callback
if
hasattr
(
self
.
system
,
'psychometrics_handler'
):
# update PsychometricsData using callback
self
.
system
.
psychometrics_handler
(
self
.
get_instance_state
())
self
.
system
.
psychometrics_handler
(
self
.
get_instance_state
())
# render problem into HTML
return
{
'success'
:
success
}
html
=
self
.
get_problem_html
(
encapsulate
=
False
)
return
{
'success'
:
success
,
'contents'
:
html
,
}
def
save_problem
(
self
,
get
):
def
save_problem
(
self
,
get
):
'''
"""
Save the passed in answers.
Save the passed in answers.
Returns a dict { 'success' : bool,
['error' : error-msg]},
Returns a dict { 'success' : bool,
'msg' : message }
with the error key only present if success is Fals
e.
The message is informative on success, and an error message on failur
e.
'''
"""
event_info
=
dict
()
event_info
=
dict
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'state'
]
=
self
.
lcp
.
get_state
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
event_info
[
'problem_id'
]
=
self
.
location
.
url
()
...
...
common/lib/xmodule/xmodule/tests/test_conditional.py
View file @
ee5ffedf
...
@@ -20,7 +20,7 @@ from . import test_system
...
@@ -20,7 +20,7 @@ from . import test_system
class
DummySystem
(
ImportSystem
):
class
DummySystem
(
ImportSystem
):
@patch
(
'xmodule.modulestore.xml.OSFS'
,
lambda
dir
:
MemoryFS
())
@patch
(
'xmodule.modulestore.xml.OSFS'
,
lambda
dir
ectory
:
MemoryFS
())
def
__init__
(
self
,
load_error_modules
):
def
__init__
(
self
,
load_error_modules
):
xmlstore
=
XMLModuleStore
(
"data_dir"
,
course_dirs
=
[],
load_error_modules
=
load_error_modules
)
xmlstore
=
XMLModuleStore
(
"data_dir"
,
course_dirs
=
[],
load_error_modules
=
load_error_modules
)
...
@@ -41,7 +41,8 @@ class DummySystem(ImportSystem):
...
@@ -41,7 +41,8 @@ class DummySystem(ImportSystem):
)
)
def
render_template
(
self
,
template
,
context
):
def
render_template
(
self
,
template
,
context
):
raise
Exception
(
"Shouldn't be called"
)
raise
Exception
(
"Shouldn't be called"
)
class
ConditionalFactory
(
object
):
class
ConditionalFactory
(
object
):
"""
"""
...
@@ -93,7 +94,7 @@ class ConditionalFactory(object):
...
@@ -93,7 +94,7 @@ class ConditionalFactory(object):
# return dict:
# return dict:
return
{
'cond_module'
:
cond_module
,
return
{
'cond_module'
:
cond_module
,
'source_module'
:
source_module
,
'source_module'
:
source_module
,
'child_module'
:
child_module
}
'child_module'
:
child_module
}
class
ConditionalModuleBasicTest
(
unittest
.
TestCase
):
class
ConditionalModuleBasicTest
(
unittest
.
TestCase
):
...
@@ -109,12 +110,11 @@ class ConditionalModuleBasicTest(unittest.TestCase):
...
@@ -109,12 +110,11 @@ class ConditionalModuleBasicTest(unittest.TestCase):
'''verify that get_icon_class works independent of condition satisfaction'''
'''verify that get_icon_class works independent of condition satisfaction'''
modules
=
ConditionalFactory
.
create
(
self
.
test_system
)
modules
=
ConditionalFactory
.
create
(
self
.
test_system
)
for
attempted
in
[
"false"
,
"true"
]:
for
attempted
in
[
"false"
,
"true"
]:
for
icon_class
in
[
'other'
,
'problem'
,
'video'
]:
for
icon_class
in
[
'other'
,
'problem'
,
'video'
]:
modules
[
'source_module'
]
.
is_attempted
=
attempted
modules
[
'source_module'
]
.
is_attempted
=
attempted
modules
[
'child_module'
]
.
get_icon_class
=
lambda
:
icon_class
modules
[
'child_module'
]
.
get_icon_class
=
lambda
:
icon_class
self
.
assertEqual
(
modules
[
'cond_module'
]
.
get_icon_class
(),
icon_class
)
self
.
assertEqual
(
modules
[
'cond_module'
]
.
get_icon_class
(),
icon_class
)
def
test_get_html
(
self
):
def
test_get_html
(
self
):
modules
=
ConditionalFactory
.
create
(
self
.
test_system
)
modules
=
ConditionalFactory
.
create
(
self
.
test_system
)
# because test_system returns the repr of the context dict passed to render_template,
# because test_system returns the repr of the context dict passed to render_template,
...
@@ -224,4 +224,3 @@ class ConditionalModuleXmlTest(unittest.TestCase):
...
@@ -224,4 +224,3 @@ class ConditionalModuleXmlTest(unittest.TestCase):
print
"post-attempt ajax: "
,
ajax
print
"post-attempt ajax: "
,
ajax
html
=
ajax
[
'html'
]
html
=
ajax
[
'html'
]
self
.
assertTrue
(
any
([
'This is a secret'
in
item
for
item
in
html
]))
self
.
assertTrue
(
any
([
'This is a secret'
in
item
for
item
in
html
]))
lms/envs/test.py
View file @
ee5ffedf
...
@@ -193,3 +193,5 @@ PASSWORD_HASHERS = (
...
@@ -193,3 +193,5 @@ PASSWORD_HASHERS = (
# By default don't use a worker, execute tasks as if they were local functions
# By default don't use a worker, execute tasks as if they were local functions
CELERY_ALWAYS_EAGER
=
True
CELERY_ALWAYS_EAGER
=
True
CELERY_RESULT_BACKEND
=
'cache'
BROKER_TRANSPORT
=
'memory'
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