Add in the ability to handle due dates and grace periods
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -155,12 +159,27 @@ 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:
|
||||
self.display_due_date = dateutil.parser.parse(display_due_date_string)
|
||||
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:
|
||||
self.grace_period = parse_timedelta(grace_period_string)
|
||||
self.close_date = self.display_due_date + self.grace_period
|
||||
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))
|
||||
@@ -189,12 +208,12 @@ class CombinedOpenEndedModule(XModule):
|
||||
self.setup_next_task()
|
||||
|
||||
def closed(self):
|
||||
return True
|
||||
#''' Is the student still allowed to submit answers? '''
|
||||
#if self.attempts == self.max_attempts:
|
||||
# return True
|
||||
#if self.close_date is not None and datetime.datetime.utcnow() > self.close_date:
|
||||
# return True
|
||||
''' Is the student still allowed to submit answers? '''
|
||||
if self.attempts == self.max_attempts:
|
||||
return True
|
||||
if self.close_date is not None and datetime.datetime.utcnow() > self.close_date:
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def get_tag_name(self, xml):
|
||||
|
||||
@@ -2,9 +2,14 @@
|
||||
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):
|
||||
"""
|
||||
Takes a time string in TIME_FORMAT
|
||||
@@ -20,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)
|
||||
|
||||
Reference in New Issue
Block a user