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
62dcd09b
Commit
62dcd09b
authored
Feb 06, 2013
by
VikParuchuri
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1428 from MITx/feature/diana/close-oe-problems
Close OE Problems
parents
53312713
f3fa4380
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
90 additions
and
19 deletions
+90
-19
common/lib/xmodule/xmodule/combined_open_ended_module.py
+30
-0
common/lib/xmodule/xmodule/open_ended_module.py
+5
-8
common/lib/xmodule/xmodule/openendedchild.py
+23
-1
common/lib/xmodule/xmodule/self_assessment_module.py
+4
-9
common/lib/xmodule/xmodule/tests/test_combined_open_ended.py
+2
-0
common/lib/xmodule/xmodule/tests/test_self_assessment.py
+3
-1
common/lib/xmodule/xmodule/timeparse.py
+23
-0
No files found.
common/lib/xmodule/xmodule/combined_open_ended_module.py
View file @
62dcd09b
...
...
@@ -7,7 +7,11 @@ from lxml import etree
from
lxml.html
import
rewrite_links
from
path
import
path
import
os
import
dateutil
import
dateutil.parser
import
datetime
import
sys
from
timeparse
import
parse_timedelta
from
pkg_resources
import
resource_string
...
...
@@ -157,12 +161,35 @@ class CombinedOpenEndedModule(XModule):
self
.
attempts
=
instance_state
.
get
(
'attempts'
,
0
)
#Allow reset is true if student has failed the criteria to move to the next child task
self
.
allow_reset
=
instance_state
.
get
(
'ready_to_reset'
,
False
)
self
.
max_attempts
=
int
(
self
.
metadata
.
get
(
'attempts'
,
MAX_ATTEMPTS
))
self
.
is_scored
=
self
.
metadata
.
get
(
'is_graded'
,
IS_SCORED
)
in
TRUE_DICT
self
.
accept_file_upload
=
self
.
metadata
.
get
(
'accept_file_upload'
,
ACCEPT_FILE_UPLOAD
)
in
TRUE_DICT
display_due_date_string
=
self
.
metadata
.
get
(
'due'
,
None
)
if
display_due_date_string
is
not
None
:
try
:
self
.
display_due_date
=
dateutil
.
parser
.
parse
(
display_due_date_string
)
except
ValueError
:
log
.
error
(
"Could not parse due date {0} for location {1}"
.
format
(
display_due_date_string
,
location
))
raise
else
:
self
.
display_due_date
=
None
grace_period_string
=
self
.
metadata
.
get
(
'graceperiod'
,
None
)
if
grace_period_string
is
not
None
and
self
.
display_due_date
:
try
:
self
.
grace_period
=
parse_timedelta
(
grace_period_string
)
self
.
close_date
=
self
.
display_due_date
+
self
.
grace_period
except
:
log
.
error
(
"Error parsing the grace period {0} for location {1}"
.
format
(
grace_period_string
,
location
))
raise
else
:
self
.
grace_period
=
None
self
.
close_date
=
self
.
display_due_date
# Used for progress / grading. Currently get credit just for
# completion (doesn't matter if you self-assessed correct/incorrect).
self
.
_max_score
=
int
(
self
.
metadata
.
get
(
'max_score'
,
MAX_SCORE
))
...
...
@@ -185,11 +212,13 @@ class CombinedOpenEndedModule(XModule):
'rubric'
:
definition
[
'rubric'
],
'display_name'
:
self
.
display_name
,
'accept_file_upload'
:
self
.
accept_file_upload
,
'close_date'
:
self
.
close_date
}
self
.
task_xml
=
definition
[
'task_xml'
]
self
.
setup_next_task
()
def
get_tag_name
(
self
,
xml
):
"""
Gets the tag name of a given xml block.
...
...
@@ -299,6 +328,7 @@ class CombinedOpenEndedModule(XModule):
return
True
def
check_allow_reset
(
self
):
"""
Checks to see if the student has passed the criteria to move to the next module. If not, sets
...
...
common/lib/xmodule/xmodule/open_ended_module.py
View file @
62dcd09b
...
...
@@ -549,14 +549,11 @@ class OpenEndedModule(openendedchild.OpenEndedChild):
@param system: modulesystem
@return: Success indicator
"""
if
self
.
attempts
>
self
.
max_attempts
:
# If too many attempts, prevent student from saving answer and
# seeing rubric. In normal use, students shouldn't see this because
# they won't see the reset button once they're out of attempts.
return
{
'success'
:
False
,
'error'
:
'Too many attempts.'
}
# Once we close the problem, we should not allow students
# to save answers
closed
,
msg
=
self
.
check_if_closed
()
if
closed
:
return
msg
if
self
.
state
!=
self
.
INITIAL
:
return
self
.
out_of_sync_error
(
get
)
...
...
common/lib/xmodule/xmodule/openendedchild.py
View file @
62dcd09b
...
...
@@ -74,7 +74,7 @@ class OpenEndedChild(object):
'done'
:
'Problem complete'
,
}
def
__init__
(
self
,
system
,
location
,
definition
,
descriptor
,
static_data
,
def
__init__
(
self
,
system
,
location
,
definition
,
descriptor
,
static_data
,
instance_state
=
None
,
shared_state
=
None
,
**
kwargs
):
# Load instance state
if
instance_state
is
not
None
:
...
...
@@ -99,6 +99,7 @@ class OpenEndedChild(object):
self
.
rubric
=
static_data
[
'rubric'
]
self
.
display_name
=
static_data
[
'display_name'
]
self
.
accept_file_upload
=
static_data
[
'accept_file_upload'
]
self
.
close_date
=
static_data
[
'close_date'
]
# Used for progress / grading. Currently get credit just for
# completion (doesn't matter if you self-assessed correct/incorrect).
...
...
@@ -117,6 +118,27 @@ class OpenEndedChild(object):
"""
pass
def
closed
(
self
):
if
self
.
close_date
is
not
None
and
datetime
.
utcnow
()
>
self
.
close_date
:
return
True
return
False
def
check_if_closed
(
self
):
if
self
.
closed
():
return
True
,
{
'success'
:
False
,
'error'
:
'This problem is now closed.'
}
elif
self
.
attempts
>
self
.
max_attempts
:
return
True
,
{
'success'
:
False
,
'error'
:
'Too many attempts.'
}
else
:
return
False
,
{}
def
latest_answer
(
self
):
"""Empty string if not available"""
if
not
self
.
history
:
...
...
common/lib/xmodule/xmodule/self_assessment_module.py
View file @
62dcd09b
...
...
@@ -190,15 +190,10 @@ class SelfAssessmentModule(openendedchild.OpenEndedChild):
Dictionary with keys 'success' and either 'error' (if not success),
or 'rubric_html' (if success).
"""
# Check to see if attempts are less than max
if
self
.
attempts
>
self
.
max_attempts
:
# If too many attempts, prevent student from saving answer and
# seeing rubric. In normal use, students shouldn't see this because
# they won't see the reset button once they're out of attempts.
return
{
'success'
:
False
,
'error'
:
'Too many attempts.'
}
# Check to see if this problem is closed
closed
,
msg
=
self
.
check_if_closed
()
if
closed
:
return
msg
if
self
.
state
!=
self
.
INITIAL
:
return
self
.
out_of_sync_error
(
get
)
...
...
common/lib/xmodule/xmodule/tests/test_combined_open_ended.py
View file @
62dcd09b
...
...
@@ -42,6 +42,7 @@ class OpenEndedChildTest(unittest.TestCase):
'max_score'
:
max_score
,
'display_name'
:
'Name'
,
'accept_file_upload'
:
False
,
'close_date'
:
None
}
definition
=
Mock
()
descriptor
=
Mock
()
...
...
@@ -157,6 +158,7 @@ class OpenEndedModuleTest(unittest.TestCase):
'max_score'
:
max_score
,
'display_name'
:
'Name'
,
'accept_file_upload'
:
False
,
'close_date'
:
None
}
oeparam
=
etree
.
XML
(
'''
...
...
common/lib/xmodule/xmodule/tests/test_self_assessment.py
View file @
62dcd09b
...
...
@@ -46,11 +46,13 @@ class SelfAssessmentTest(unittest.TestCase):
'max_score'
:
1
,
'display_name'
:
"Name"
,
'accept_file_upload'
:
False
,
'close_date'
:
None
}
self
.
module
=
SelfAssessmentModule
(
test_system
,
self
.
location
,
self
.
definition
,
self
.
descriptor
,
static_data
,
state
,
metadata
=
self
.
metadata
)
static_data
,
state
,
metadata
=
self
.
metadata
)
def
test_get_html
(
self
):
html
=
self
.
module
.
get_html
(
test_system
)
...
...
common/lib/xmodule/xmodule/timeparse.py
View file @
62dcd09b
...
...
@@ -2,9 +2,12 @@
Helper functions for handling time in the format we like.
"""
import
time
import
re
from
datetime
import
timedelta
TIME_FORMAT
=
"
%
Y-
%
m-
%
dT
%
H:
%
M"
TIMEDELTA_REGEX
=
re
.
compile
(
r'^((?P<days>\d+?) day(?:s?))?(\s)?((?P<hours>\d+?) hour(?:s?))?(\s)?((?P<minutes>\d+?) minute(?:s)?)?(\s)?((?P<seconds>\d+?) second(?:s)?)?$'
)
def
parse_time
(
time_str
):
"""
...
...
@@ -22,3 +25,23 @@ def stringify_time(time_struct):
Convert a time struct to a string
"""
return
time
.
strftime
(
TIME_FORMAT
,
time_struct
)
def
parse_timedelta
(
time_str
):
"""
time_str: A string with the following components:
<D> day[s] (optional)
<H> hour[s] (optional)
<M> minute[s] (optional)
<S> second[s] (optional)
Returns a datetime.timedelta parsed from the string
"""
parts
=
TIMEDELTA_REGEX
.
match
(
time_str
)
if
not
parts
:
return
parts
=
parts
.
groupdict
()
time_params
=
{}
for
(
name
,
param
)
in
parts
.
iteritems
():
if
param
:
time_params
[
name
]
=
int
(
param
)
return
timedelta
(
**
time_params
)
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