correctmap.py 4.08 KB
Newer Older
1 2 3 4 5 6 7
#-----------------------------------------------------------------------------
# class used to store graded responses to CAPA questions
#
# Used by responsetypes and capa_problem

class CorrectMap(object):
    '''
ichuang committed
8 9 10 11 12 13 14 15 16 17
    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

18 19 20
    Behaves as a dict.
    '''
    def __init__(self,*args,**kwargs):
21 22 23
        self.cmap = dict()		# start with empty dict
        self.items = self.cmap.items
        self.keys = self.cmap.keys
24 25
        self.set(*args,**kwargs)

26
    def __getitem__(self, *args, **kwargs):
ichuang committed
27
        return self.cmap.__getitem__(*args, **kwargs)
28

29 30 31
    def __iter__(self):
        return self.cmap.__iter__()

ichuang committed
32
    def set(self, answer_id=None, correctness=None, npoints=None, msg='', hint='', hintmode=None):
33 34 35
        if answer_id is not None:
            self.cmap[answer_id] = {'correctness': correctness,
                                    'npoints': npoints,
ichuang committed
36 37 38 39
                                    'msg': msg,
                                    'hint' : hint,
                                    'hintmode' : hintmode,
                                    }
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

    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):
57
            self.__init__()							# empty current dict
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
            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 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','')

ichuang committed
86 87 88 89 90 91 92 93 94 95 96 97 98 99
    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)

100 101 102 103 104 105 106 107 108 109
    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())