119 lines
4.5 KiB
Python
119 lines
4.5 KiB
Python
#-----------------------------------------------------------------------------
|
|
# class used to store graded responses to CAPA questions
|
|
#
|
|
# Used by responsetypes and capa_problem
|
|
|
|
|
|
class CorrectMap(object):
|
|
'''
|
|
Stores map between answer_id and response evaluation result for each question
|
|
in a capa problem. The response evaluation result for each answer_id includes
|
|
(correctness, npoints, msg, hint, hintmode).
|
|
|
|
- correctness : either 'correct' or 'incorrect'
|
|
- npoints : None, or integer specifying number of points awarded for this answer_id
|
|
- msg : string (may have HTML) giving extra message response (displayed below textline or textbox)
|
|
- hint : string (may have HTML) giving optional hint (displayed below textline or textbox, above msg)
|
|
- hintmode : one of (None,'on_request','always') criteria for displaying hint
|
|
- queuekey : a random integer for xqueue_callback verification
|
|
|
|
Behaves as a dict.
|
|
'''
|
|
def __init__(self, *args, **kwargs):
|
|
self.cmap = dict() # start with empty dict
|
|
self.items = self.cmap.items
|
|
self.keys = self.cmap.keys
|
|
self.set(*args, **kwargs)
|
|
|
|
def __getitem__(self, *args, **kwargs):
|
|
return self.cmap.__getitem__(*args, **kwargs)
|
|
|
|
def __iter__(self):
|
|
return self.cmap.__iter__()
|
|
|
|
def set(self, answer_id=None, correctness=None, npoints=None, msg='', hint='', hintmode=None, queuekey=None):
|
|
if answer_id is not None:
|
|
self.cmap[answer_id] = {'correctness': correctness,
|
|
'npoints': npoints,
|
|
'msg': msg,
|
|
'hint': hint,
|
|
'hintmode': hintmode,
|
|
'queuekey': queuekey,
|
|
}
|
|
|
|
def __repr__(self):
|
|
return repr(self.cmap)
|
|
|
|
def get_dict(self):
|
|
'''
|
|
return dict version of self
|
|
'''
|
|
return self.cmap
|
|
|
|
def set_dict(self, correct_map):
|
|
'''
|
|
set internal dict to provided correct_map dict
|
|
for graceful migration, if correct_map is a one-level dict, then convert it to the new
|
|
dict of dicts format.
|
|
'''
|
|
if correct_map and not (type(correct_map[correct_map.keys()[0]]) == dict):
|
|
self.__init__() # empty current dict
|
|
for k in correct_map: self.set(k, correct_map[k]) # create new dict entries
|
|
else:
|
|
self.cmap = correct_map
|
|
|
|
def is_correct(self, answer_id):
|
|
if answer_id in self.cmap: return self.cmap[answer_id]['correctness'] == 'correct'
|
|
return None
|
|
|
|
def is_queued(self, answer_id):
|
|
return answer_id in self.cmap and self.cmap[answer_id]['queuekey'] is not None
|
|
|
|
def is_right_queuekey(self, answer_id, test_key):
|
|
return answer_id in self.cmap and self.cmap[answer_id]['queuekey'] == test_key
|
|
|
|
def get_npoints(self, answer_id):
|
|
if self.is_correct(answer_id):
|
|
npoints = self.cmap[answer_id].get('npoints', 1) # default to 1 point if correct
|
|
return npoints or 1
|
|
return 0 # if not correct, return 0
|
|
|
|
def set_property(self, answer_id, property, value):
|
|
if answer_id in self.cmap: self.cmap[answer_id][property] = value
|
|
else: self.cmap[answer_id] = {property: value}
|
|
|
|
def get_property(self, answer_id, property, default=None):
|
|
if answer_id in self.cmap: return self.cmap[answer_id].get(property, default)
|
|
return default
|
|
|
|
def get_correctness(self, answer_id):
|
|
return self.get_property(answer_id, 'correctness')
|
|
|
|
def get_msg(self, answer_id):
|
|
return self.get_property(answer_id, 'msg', '')
|
|
|
|
def get_hint(self, answer_id):
|
|
return self.get_property(answer_id, 'hint', '')
|
|
|
|
def get_hintmode(self, answer_id):
|
|
return self.get_property(answer_id, 'hintmode', None)
|
|
|
|
def set_hint_and_mode(self, answer_id, hint, hintmode):
|
|
'''
|
|
- hint : (string) HTML text for hint
|
|
- hintmode : (string) mode for hint display ('always' or 'on_request')
|
|
'''
|
|
self.set_property(answer_id, 'hint', hint)
|
|
self.set_property(answer_id, 'hintmode', hintmode)
|
|
|
|
def update(self, other_cmap):
|
|
'''
|
|
Update this CorrectMap with the contents of another CorrectMap
|
|
'''
|
|
if not isinstance(other_cmap, CorrectMap):
|
|
raise Exception('CorrectMap.update called with invalid argument %s' % other_cmap)
|
|
self.cmap.update(other_cmap.get_dict())
|
|
|
|
|
|
|