Define initial celery task on instructor dash.

Add CourseTaskLog, and make calls to regrading.

Add regrading implementation, and hack the marshalling of request.
This commit is contained in:
Brian Wilson
2013-04-25 18:22:00 -04:00
parent 94238238e7
commit 91ac6e68e8
7 changed files with 738 additions and 6 deletions

View File

@@ -270,7 +270,26 @@ class LoncapaProblem(object):
# if answers include File objects, convert them to filenames.
self.student_answers = convert_files_to_filenames(answers)
return self._grade_answers(answers)
def regrade_existing_answers(self):
'''
Regrade student responses. Called by capa_module.regrade_problem.
'''
return self._grade_answers(None)
def _grade_answers(self, answers):
'''
Internal grading call used for checking new student answers and also
regrading existing student answers.
answers is a dict of all the entries from request.POST, but with the first part
of each key removed (the string before the first "_").
Thus, for example, input_ID123 -> ID123, and input_fromjs_ID123 -> fromjs_ID123
Calls the Response for each question in this problem, to do the actual grading.
'''
# old CorrectMap
oldcmap = self.correct_map
@@ -281,10 +300,11 @@ class LoncapaProblem(object):
for responder in self.responders.values():
# File objects are passed only if responsetype explicitly allows for file
# submissions
if 'filesubmission' in responder.allowed_inputfields:
# TODO: figure out where to get file submissions when regrading.
if 'filesubmission' in responder.allowed_inputfields and answers is not None:
results = responder.evaluate_answers(answers, oldcmap)
else:
results = responder.evaluate_answers(convert_files_to_filenames(answers), oldcmap)
results = responder.evaluate_answers(self.student_answers, oldcmap)
newcmap.update(results)
self.correct_map = newcmap
# log.debug('%s: in grade_answers, answers=%s, cmap=%s' % (self,answers,newcmap))

View File

@@ -759,6 +759,8 @@ class CapaModule(CapaFields, XModule):
try:
correct_map = self.lcp.grade_answers(answers)
self.attempts = self.attempts + 1
self.lcp.done = True
self.set_state_from_lcp()
except (StudentInputError, ResponseError, LoncapaProblemError) as inst:
@@ -785,10 +787,6 @@ class CapaModule(CapaFields, XModule):
return {'success': msg}
raise
self.attempts = self.attempts + 1
self.lcp.done = True
self.set_state_from_lcp()
self.publish_grade()
# success = correct if ALL questions in this problem are correct
@@ -814,6 +812,63 @@ class CapaModule(CapaFields, XModule):
'contents': html,
}
def regrade_problem(self):
''' Checks whether answers to a problem are correct, and
returns a map of correct/incorrect answers:
{'success' : 'correct' | 'incorrect' | AJAX alert msg string,
'contents' : html}
'''
event_info = dict()
event_info['state'] = self.lcp.get_state()
event_info['problem_id'] = self.location.url()
if not self.done:
event_info['failure'] = 'unanswered'
self.system.track_function('save_problem_regrade_fail', event_info)
raise NotFoundError('Problem must be answered before it can be graded again')
try:
correct_map = self.lcp.regrade_existing_answers()
# regrading should have no effect on attempts, so don't
# need to increment here, or mark done. Just save.
self.set_state_from_lcp()
except StudentInputError as inst:
log.exception("StudentInputError in capa_module:problem_regrade")
return {'success': inst.message}
except Exception, err:
if self.system.DEBUG:
msg = "Error checking problem: " + str(err)
msg += '\nTraceback:\n' + traceback.format_exc()
return {'success': msg}
raise
self.publish_grade()
# success = correct if ALL questions in this problem are correct
success = 'correct'
for answer_id in correct_map:
if not correct_map.is_correct(answer_id):
success = 'incorrect'
# NOTE: We are logging both full grading and queued-grading submissions. In the latter,
# 'success' will always be incorrect
event_info['correct_map'] = correct_map.get_dict()
event_info['success'] = success
event_info['attempts'] = self.attempts
self.system.track_function('save_problem_regrade', event_info)
# TODO: figure out if psychometrics should be called on regrading requests
if hasattr(self.system, 'psychometrics_handler'): # update PsychometricsData using callback
self.system.psychometrics_handler(self.get_instance_state())
# render problem into HTML
html = self.get_problem_html(encapsulate=False)
return {'success': success,
'contents': html,
}
def save_problem(self, get):
'''
Save the passed in answers.