Commit f9cca8be by Diana Huang

Starting a framework for handling the closure of an open ended problem.

Currently incomplete.
parent 01fab2ec
......@@ -188,6 +188,15 @@ class CombinedOpenEndedModule(XModule):
self.task_xml = definition['task_xml']
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
def get_tag_name(self, xml):
"""
Gets the tag name of a given xml block.
......@@ -269,7 +278,7 @@ class CombinedOpenEndedModule(XModule):
self.current_task_parsed_xml = self.current_task_descriptor.definition_from_xml(etree_xml, self.system)
if current_task_state is None and self.current_task_number == 0:
self.current_task = child_task_module(self.system, self.location,
self.current_task_parsed_xml, self.current_task_descriptor, self.static_data)
self.current_task_parsed_xml, self.current_task_descriptor, self.static_data, self)
self.task_states.append(self.current_task.get_instance_state())
self.state = self.ASSESSING
elif current_task_state is None and self.current_task_number > 0:
......@@ -285,7 +294,7 @@ class CombinedOpenEndedModule(XModule):
})
self.current_task = child_task_module(self.system, self.location,
self.current_task_parsed_xml, self.current_task_descriptor, self.static_data,
instance_state=current_task_state)
self, instance_state=current_task_state)
self.task_states.append(self.current_task.get_instance_state())
self.state = self.ASSESSING
else:
......@@ -293,10 +302,11 @@ class CombinedOpenEndedModule(XModule):
current_task_state = self.overwrite_state(current_task_state)
self.current_task = child_task_module(self.system, self.location,
self.current_task_parsed_xml, self.current_task_descriptor, self.static_data,
instance_state=current_task_state)
self, instance_state=current_task_state)
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
......@@ -404,7 +414,7 @@ class CombinedOpenEndedModule(XModule):
task_parsed_xml = task_descriptor.definition_from_xml(etree_xml, self.system)
task = children['modules'][task_type](self.system, self.location, task_parsed_xml, task_descriptor,
self.static_data, instance_state=task_state)
self.static_data, self, instance_state=task_state)
last_response = task.latest_answer()
last_score = task.latest_score()
last_post_assessment = task.latest_post_assessment(self.system)
......@@ -700,4 +710,4 @@ class CombinedOpenEndedDescriptor(XmlDescriptor, EditingDescriptor):
for child in ['task']:
add_child(child)
return elt
\ No newline at end of file
return elt
......@@ -548,13 +548,12 @@ 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.
# Once we close the problem, we should not allow students
# to save answers
if self.closed():
return {
'success': False,
'error': 'Too many attempts.'
'error': 'Problem is closed.'
}
if self.state != self.INITIAL:
......
......@@ -73,7 +73,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, parent,
instance_state=None, shared_state=None, **kwargs):
# Load instance state
if instance_state is not None:
......@@ -87,6 +87,8 @@ class OpenEndedChild(object):
# Scores are on scale from 0 to max_score
self.history = instance_state.get('history', [])
self.parent = parent
self.state = instance_state.get('state', self.INITIAL)
self.created = instance_state.get('created', False)
......@@ -116,6 +118,9 @@ class OpenEndedChild(object):
"""
pass
def closed(self):
return self.parent.closed()
def latest_answer(self):
"""Empty string if not available"""
if not self.history:
......
......@@ -189,14 +189,11 @@ 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.
# Check to see if this problem is closed
if self.closed():
return {
'success': False,
'error': 'Too many attempts.'
'error': 'This problem is now closed.'
}
if self.state != self.INITIAL:
......
......@@ -43,11 +43,14 @@ class OpenEndedChildTest(unittest.TestCase):
'accept_file_upload' : False,
}
definition = Mock()
parent = Mock()
parent.closed.return_value = False;
descriptor = Mock()
def setUp(self):
self.openendedchild = OpenEndedChild(test_system, self.location,
self.definition, self.descriptor, self.static_data, self.metadata)
self.definition, self.descriptor, self.static_data,
self.parent, self.metadata)
def test_latest_answer_empty(self):
......@@ -166,6 +169,8 @@ class OpenEndedModuleTest(unittest.TestCase):
''')
definition = {'oeparam': oeparam}
descriptor = Mock()
parent = Mock()
parent.closed.return_value = False;
def setUp(self):
test_system.location = self.location
......@@ -173,7 +178,8 @@ class OpenEndedModuleTest(unittest.TestCase):
self.mock_xqueue.send_to_queue.return_value=(None, "Message")
test_system.xqueue = {'interface':self.mock_xqueue, 'callback_url':'/', 'default_queuename': 'testqueue', 'waittime': 1}
self.openendedmodule = OpenEndedModule(test_system, self.location,
self.definition, self.descriptor, self.static_data, self.metadata)
self.definition, self.descriptor, self.static_data,
self.parent, self.metadata)
def test_message_post(self):
get = {'feedback': 'feedback text',
......
......@@ -30,6 +30,8 @@ class SelfAssessmentTest(unittest.TestCase):
metadata = {'attempts': '10'}
descriptor = Mock()
parent = Mock()
parent.closed.return_value = False
def setUp(self):
state = json.dumps({'student_answers': ["Answer 1", "answer 2", "answer 3"],
......@@ -49,7 +51,8 @@ class SelfAssessmentTest(unittest.TestCase):
self.module = SelfAssessmentModule(test_system, self.location,
self.definition, self.descriptor,
static_data, state, metadata=self.metadata)
static_data, self.parent,
state, metadata=self.metadata)
def test_get_html(self):
html = self.module.get_html(test_system)
......@@ -72,6 +75,7 @@ class SelfAssessmentTest(unittest.TestCase):
# if we now assess as right, skip the REQUEST_HINT state
self.module.save_answer({'student_answer': 'answer 4'}, test_system)
self.parent.closed.assert_called_with()
self.module.save_assessment({'assessment': '1'}, test_system)
self.assertEqual(self.module.state, self.module.DONE)
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