Commit 14044ea0 by Joe Blaylock

Merge pull request #70 from Stanford-Online/jbau/timed-exam-hack

HACK capa timed-test on capa_base.py
parents cc34a0f0 846ab440
......@@ -160,6 +160,9 @@ class CapaFields(object):
student_answers = Dict(help=_("Dictionary with the current student responses"), scope=Scope.user_state)
done = Boolean(help=_("Whether the student has answered the problem"), scope=Scope.user_state)
seed = Integer(help=_("Random seed for this student"), scope=Scope.user_state)
minutes_allowed = Integer(help=_("EXPERIMENTAL FEATURE: DO NOT USE. Number of minutes allowed to finish this assessment. Set 0 for no time-limit"),
default=0, scope=Scope.settings)
time_started = Date(help=_("time student started this assessment"), scope=Scope.user_state)
last_submission_time = Date(help=_("Last submission time"), scope=Scope.user_state)
submission_wait_seconds = Integer(
display_name=_("Timer Between Attempts"),
......@@ -346,6 +349,12 @@ class CapaMixin(CapaFields):
self.student_answers = lcp_state['student_answers']
self.seed = lcp_state['seed']
def set_time_started(self):
"""
Sets the time when the student started the module.
"""
self.time_started = datetime.datetime.now(UTC())
def set_last_submission_time(self):
"""
Set the module's last submission time (when the problem was checked)
......@@ -616,6 +625,21 @@ class CapaMixin(CapaFields):
check_button = False
check_button_checking = False
problem_is_timed = self.minutes_allowed > 0
if problem_is_timed and not self.time_started:
self.set_time_started()
end_time_to_display = (self.time_started + datetime.timedelta(minutes=self.minutes_allowed)
if problem_is_timed
else None)
# because we use self.due and not self.close_date below, this is not the actual end_time, but the
# end_time we want to display to the user
if self.due and end_time_to_display:
end_time_to_display = min(self.due, end_time_to_display)
content = {
'name': self.display_name_with_default,
'html': html,
......@@ -625,6 +649,9 @@ class CapaMixin(CapaFields):
context = {
'problem': content,
'id': self.location.to_deprecated_string(),
'problem_is_timed': problem_is_timed,
'start_time': self.time_started,
'end_time_to_display': end_time_to_display,
'check_button': check_button,
'check_button_checking': check_button_checking,
'reset_button': self.should_show_reset_button(),
......@@ -652,6 +679,17 @@ class CapaMixin(CapaFields):
return html
def exceeded_time_limit(self):
"""
Has student used up allotted time, if set
"""
if self.minutes_allowed <= 0 or not self.time_started:
return False
now = datetime.datetime.now(UTC())
# built in hardcoded grace period of 5 min
time_limit_end = self.time_started + datetime.timedelta(minutes=(self.minutes_allowed + 5))
return now > time_limit_end
def is_past_due(self):
"""
Is it now past this problem's due date, including grace period?
......@@ -667,6 +705,8 @@ class CapaMixin(CapaFields):
return True
if self.is_past_due():
return True
if self.exceeded_time_limit():
return True
return False
......
<%! from django.utils.translation import ugettext as _ %>
<%!
from django.utils.translation import ugettext as _
from xmodule.util.date_utils import get_time_display
from django.conf import settings
%>
<%namespace name='static' file='static_content.html'/>
<h2 class="problem-header">
......@@ -7,6 +11,20 @@
<div class="problem-progress"></div>
% if problem_is_timed:
<div class="time_limit">
<p>
${_("At {start_time}, you started this exam.").format(
start_time=get_time_display(start_time, coerce_tz=settings.TIME_ZONE))}
<br />
<b>
${_("By {end_time}, you must manually click the 'Final Submit' button below!").format(
end_time=get_time_display(end_time_to_display, coerce_tz=settings.TIME_ZONE))}
</b>
</p>
</div>
% endif
<div class="problem" role="application">
${ problem['html'] }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment