diff --git a/djangoapps/courseware/capa/inputtypes.py b/djangoapps/courseware/capa/inputtypes.py index 8ca13371b5..8fd82d7885 100644 --- a/djangoapps/courseware/capa/inputtypes.py +++ b/djangoapps/courseware/capa/inputtypes.py @@ -33,7 +33,7 @@ from lxml import etree from mitxmako.shortcuts import render_to_string class SimpleInput():# XModule - ''' Type for simple inputs + ''' Type for simple inputs -- plain HTML with a form element State is a dictionary with optional keys: * Value * ID @@ -42,18 +42,18 @@ class SimpleInput():# XModule feedback from previous attempt) ''' - simple_types = {} ## Maps tags to functions + xml_tags = {} ## Maps tags to functions @classmethod def get_xml_tags(c): - return c.simple_types.keys() + return c.xml_tags.keys() @classmethod def get_uses(c): - return ['capa_input'] + return ['capa_input', 'capa_transform'] def get_html(self): - return self.simple_types[self.tag](self.xml, self.value, self.status, self.msg) + return self.xml_tags[self.tag](self.xml, self.value, self.status, self.msg) def __init__(self, system, xml, item_id = None, track_url=None, state=None, use = 'capa_input'): self.xml = xml @@ -80,18 +80,65 @@ class SimpleInput():# XModule if 'status' in state: self.status = state['status'] -def simpleinput(fn, names=None): +## TODO +# class SimpleTransform(): +# ''' Type for simple XML to HTML transforms. Examples: +# * Math tags, which go from LON-CAPA-style m-tags to MathJAX +# ''' +# xml_tags = {} ## Maps tags to functions + +# @classmethod +# def get_xml_tags(c): +# return c.xml_tags.keys() + +# @classmethod +# def get_uses(c): +# return ['capa_transform'] + +# def get_html(self): +# return self.xml_tags[self.tag](self.xml, self.value, self.status, self.msg) + +# def __init__(self, system, xml, item_id = None, track_url=None, state=None, use = 'capa_input'): +# self.xml = xml +# self.tag = xml.tag +# if not state: +# state = {} +# if item_id: +# self.id = item_id +# if xml.get('id'): +# self.id = xml.get('id') +# if 'id' in state: +# self.id = state['id'] +# self.system = system + +# self.value = '' +# if 'value' in state: +# self.value = state['value'] + +# self.msg = '' +# if 'feedback' in state and 'message' in state['feedback']: +# self.msg = state['feedback']['message'] + +# self.status = 'unanswered' +# if 'status' in state: +# self.status = state['status'] + + +def register_render_function(fn, names=None, cls=SimpleInput): if names == None: - SimpleInput.simple_types[fn.__name__] = fn + SimpleInput.xml_tags[fn.__name__] = fn else: raise "Unimplemented/input types" def wrapped(): return fn return wrapped + + + #----------------------------------------------------------------------------- -@simpleinput +@register_render_function def optioninput(element, value, status, msg=''): ''' Select option input type. @@ -125,7 +172,7 @@ def optioninput(element, value, status, msg=''): return etree.XML(html) #----------------------------------------------------------------------------- -@simpleinput +@register_render_function def choicegroup(element, value, status, msg=''): ''' Radio button inputs: multiple choice or true/false @@ -148,7 +195,7 @@ def choicegroup(element, value, status, msg=''): html=render_to_string("choicegroup.html", context) return etree.XML(html) -@simpleinput +@register_render_function def textline(element, value, state, msg=""): eid=element.get('id') count = int(eid.split('_')[-2])-1 # HACK @@ -159,7 +206,7 @@ def textline(element, value, state, msg=""): #----------------------------------------------------------------------------- -@simpleinput +@register_render_function def js_textline(element, value, status, msg=''): ''' Plan: We will inspect element to figure out type @@ -185,7 +232,7 @@ def js_textline(element, value, status, msg=''): #----------------------------------------------------------------------------- ## TODO: Make a wrapper for -@simpleinput +@register_render_function def textbox(element, value, status, msg=''): ''' The textbox is used for code input. The message is the return HTML string from @@ -201,7 +248,7 @@ def textbox(element, value, status, msg=''): return etree.XML(html) #----------------------------------------------------------------------------- -@simpleinput +@register_render_function def schematic(element, value, status, msg=''): eid = element.get('id') height = element.get('height') @@ -226,7 +273,7 @@ def schematic(element, value, status, msg=''): #----------------------------------------------------------------------------- ### TODO: Move out of inputtypes -@simpleinput +@register_render_function def math(element, value, status, msg=''): ''' This is not really an input type. It is a convention from Lon-CAPA, used for @@ -261,7 +308,7 @@ def math(element, value, status, msg=''): #----------------------------------------------------------------------------- -@simpleinput +@register_render_function def solution(element, value, status, msg=''): ''' This is not really an input type. It is just a ... which is given an ID, @@ -282,7 +329,7 @@ def solution(element, value, status, msg=''): #----------------------------------------------------------------------------- -@simpleinput +@register_render_function def imageinput(element, value, status, msg=''): ''' Clickable image as an input field. Element should specify the image source, height, and width, eg diff --git a/djangoapps/courseware/capa/responsetypes.py b/djangoapps/courseware/capa/responsetypes.py index 190f52e7b6..380ab85c56 100644 --- a/djangoapps/courseware/capa/responsetypes.py +++ b/djangoapps/courseware/capa/responsetypes.py @@ -47,10 +47,10 @@ def compare_with_tolerance(v1, v2, tol): return abs(v1-v2) <= tolerance class GenericResponse(object): - __metaclass__=abc.ABCMeta + __metaclass__=abc.ABCMeta # abc = Abstract Base Class @abc.abstractmethod - def grade(self, student_answers): + def get_score(self, student_answers): pass @abc.abstractmethod @@ -61,7 +61,7 @@ class GenericResponse(object): def preprocess_response(self): pass -#Every response type needs methods "grade" and "get_answers" +#Every response type needs methods "get_score" and "get_answers" #----------------------------------------------------------------------------- @@ -95,7 +95,7 @@ class MultipleChoiceResponse(GenericResponse): raise Exception("should have exactly one choice group per multiplechoicceresponse") self.answer_id=self.answer_id[0] - def grade(self, student_answers): + def get_score(self, student_answers): if self.answer_id in student_answers and student_answers[self.answer_id] in self.correct_choices: return {self.answer_id:'correct'} else: @@ -132,7 +132,7 @@ class TrueFalseResponse(MultipleChoiceResponse): else: choice.set("name", "choice_"+choice.get("name")) - def grade(self, student_answers): + def get_score(self, student_answers): correct = set(self.correct_choices) answers = set(student_answers.get(self.answer_id, [])) @@ -162,7 +162,7 @@ class OptionResponse(GenericResponse): print '[courseware.capa.responsetypes.OR.init] answer_fields=%s' % (self.answer_fields) self.context = context - def grade(self, student_answers): + def get_score(self, student_answers): cmap = {} amap = self.get_answers() for aid in amap: @@ -194,7 +194,7 @@ class NumericalResponse(GenericResponse): except Exception, err: self.answer_id = None - def grade(self, student_answers): + def get_score(self, student_answers): ''' Display HTML for a numeric response ''' student_answer = student_answers[self.answer_id] try: @@ -300,7 +300,7 @@ def sympy_check2(): else: self.code = answer.text - def grade(self, student_answers): + def get_score(self, student_answers): ''' student_answers is a dict with everything from request.POST, but with the first part of each key removed (the string before the first "_"). @@ -363,7 +363,7 @@ def sympy_check2(): print "oops in customresponse (cfn) error %s" % err # print "context = ",self.context print traceback.format_exc() - if settings.DEBUG: print "[courseware.capa.responsetypes.customresponse.grade] ret = ",ret + if settings.DEBUG: print "[courseware.capa.responsetypes.customresponse.get_score] ret = ",ret if type(ret)==dict: correct[0] = 'correct' if ret['ok'] else 'incorrect' msg = ret['msg'] @@ -428,7 +428,7 @@ class ExternalResponse(GenericResponse): self.tests = xml.get('answer') - def grade(self, student_answers): + def get_score(self, student_answers): submission = [student_answers[k] for k in sorted(self.answer_ids)] self.context.update({'submission':submission}) @@ -504,7 +504,7 @@ class FormulaResponse(GenericResponse): self.case_sensitive = False - def grade(self, student_answers): + def get_score(self, student_answers): variables=self.samples.split('@')[0].split(',') numsamples=int(self.samples.split('@')[1].split('#')[1]) sranges=zip(*map(lambda x:map(float, x.split(",")), @@ -566,7 +566,7 @@ class SchematicResponse(GenericResponse): else: self.code = answer.text - def grade(self, student_answers): + def get_score(self, student_answers): from capa_problem import global_context submission = [json.loads(student_answers[k]) for k in sorted(self.answer_ids)] self.context.update({'submission':submission}) @@ -605,7 +605,7 @@ class ImageResponse(GenericResponse): self.ielements = xml.findall('imageinput') self.answer_ids = [ie.get('id') for ie in self.ielements] - def grade(self, student_answers): + def get_score(self, student_answers): correct_map = {} expectedset = self.get_answers()