Commit dacc1f3c by Nimisha Asthagiri Committed by GitHub

Merge pull request #14055 from edx/naa/fix-capa-max-score

Fix CAPA's max_score computation
parents ca5c741f 562aeee0
...@@ -187,7 +187,7 @@ class LoncapaProblem(object): ...@@ -187,7 +187,7 @@ class LoncapaProblem(object):
# construct script processor context (eg for customresponse problems) # construct script processor context (eg for customresponse problems)
if minimal_init: if minimal_init:
self.context = {'script_code': ""} self.context = {}
else: else:
self.context = self._extract_context(self.tree) self.context = self._extract_context(self.tree)
...@@ -195,24 +195,24 @@ class LoncapaProblem(object): ...@@ -195,24 +195,24 @@ class LoncapaProblem(object):
# transformations. This also creates the dict (self.responders) of Response # transformations. This also creates the dict (self.responders) of Response
# instances for each question in the problem. The dict has keys = xml subtree of # instances for each question in the problem. The dict has keys = xml subtree of
# Response, values = Response instance # Response, values = Response instance
self.problem_data = self._preprocess_problem(self.tree) self.problem_data = self._preprocess_problem(self.tree, minimal_init)
if not self.student_answers: # True when student_answers is an empty dict if not minimal_init:
self.set_initial_display() if not self.student_answers: # True when student_answers is an empty dict
self.set_initial_display()
# dictionary of InputType objects associated with this problem # dictionary of InputType objects associated with this problem
# input_id string -> InputType object # input_id string -> InputType object
self.inputs = {} self.inputs = {}
# Run response late_transforms last (see MultipleChoiceResponse) # Run response late_transforms last (see MultipleChoiceResponse)
# Sort the responses to be in *_1 *_2 ... order. # Sort the responses to be in *_1 *_2 ... order.
responses = self.responders.values() responses = self.responders.values()
responses = sorted(responses, key=lambda resp: int(resp.id[resp.id.rindex('_') + 1:])) responses = sorted(responses, key=lambda resp: int(resp.id[resp.id.rindex('_') + 1:]))
for response in responses: for response in responses:
if hasattr(response, 'late_transforms'): if hasattr(response, 'late_transforms'):
response.late_transforms(self) response.late_transforms(self)
if not minimal_init:
self.extracted_tree = self._extract_html(self.tree) self.extracted_tree = self._extract_html(self.tree)
def make_xml_compatible(self, tree): def make_xml_compatible(self, tree):
...@@ -869,7 +869,7 @@ class LoncapaProblem(object): ...@@ -869,7 +869,7 @@ class LoncapaProblem(object):
return tree return tree
def _preprocess_problem(self, tree): # private def _preprocess_problem(self, tree, minimal_init): # private
""" """
Assign IDs to all the responses Assign IDs to all the responses
Assign sub-IDs to all entries (textline, schematic, etc.) Assign sub-IDs to all entries (textline, schematic, etc.)
...@@ -907,28 +907,31 @@ class LoncapaProblem(object): ...@@ -907,28 +907,31 @@ class LoncapaProblem(object):
# instantiate capa Response # instantiate capa Response
responsetype_cls = responsetypes.registry.get_class_for_tag(response.tag) responsetype_cls = responsetypes.registry.get_class_for_tag(response.tag)
responder = responsetype_cls(response, inputfields, self.context, self.capa_system, self.capa_module) responder = responsetype_cls(
response, inputfields, self.context, self.capa_system, self.capa_module, minimal_init
)
# save in list in self # save in list in self
self.responders[response] = responder self.responders[response] = responder
# get responder answers (do this only once, since there may be a performance cost, if not minimal_init:
# eg with externalresponse) # get responder answers (do this only once, since there may be a performance cost,
self.responder_answers = {} # eg with externalresponse)
for response in self.responders.keys(): self.responder_answers = {}
try: for response in self.responders.keys():
self.responder_answers[response] = self.responders[response].get_answers() try:
except: self.responder_answers[response] = self.responders[response].get_answers()
log.debug('responder %s failed to properly return get_answers()', except:
self.responders[response]) # FIXME log.debug('responder %s failed to properly return get_answers()',
raise self.responders[response]) # FIXME
raise
# <solution>...</solution> may not be associated with any specific response; give
# IDs for those separately # <solution>...</solution> may not be associated with any specific response; give
# TODO: We should make the namespaces consistent and unique (e.g. %s_problem_%i). # IDs for those separately
solution_id = 1 # TODO: We should make the namespaces consistent and unique (e.g. %s_problem_%i).
for solution in tree.findall('.//solution'): solution_id = 1
solution.attrib['id'] = "%s_solution_%i" % (self.problem_id, solution_id) for solution in tree.findall('.//solution'):
solution_id += 1 solution.attrib['id'] = "%s_solution_%i" % (self.problem_id, solution_id)
solution_id += 1
return problem_data return problem_data
......
...@@ -154,7 +154,7 @@ class LoncapaResponse(object): ...@@ -154,7 +154,7 @@ class LoncapaResponse(object):
# By default, we set this to False, allowing subclasses to override as appropriate. # By default, we set this to False, allowing subclasses to override as appropriate.
multi_device_support = False multi_device_support = False
def __init__(self, xml, inputfields, context, system, capa_module): def __init__(self, xml, inputfields, context, system, capa_module, minimal_init):
""" """
Init is passed the following arguments: Init is passed the following arguments:
...@@ -213,28 +213,29 @@ class LoncapaResponse(object): ...@@ -213,28 +213,29 @@ class LoncapaResponse(object):
maxpoints = inputfield.get('points', '1') maxpoints = inputfield.get('points', '1')
self.maxpoints.update({inputfield.get('id'): int(maxpoints)}) self.maxpoints.update({inputfield.get('id'): int(maxpoints)})
# dict for default answer map (provided in input elements) if not minimal_init:
self.default_answer_map = {} # dict for default answer map (provided in input elements)
for entry in self.inputfields: self.default_answer_map = {}
answer = entry.get('correct_answer') for entry in self.inputfields:
if answer: answer = entry.get('correct_answer')
self.default_answer_map[entry.get( if answer:
'id')] = contextualize_text(answer, self.context) self.default_answer_map[entry.get(
'id')] = contextualize_text(answer, self.context)
# Does this problem have partial credit?
# If so, what kind? Get it as a list of strings. # Does this problem have partial credit?
partial_credit = xml.xpath('.')[0].get('partial_credit', default=False) # If so, what kind? Get it as a list of strings.
partial_credit = xml.xpath('.')[0].get('partial_credit', default=False)
if str(partial_credit).lower().strip() == 'false':
self.has_partial_credit = False if str(partial_credit).lower().strip() == 'false':
self.credit_type = [] self.has_partial_credit = False
else: self.credit_type = []
self.has_partial_credit = True else:
self.credit_type = partial_credit.split(',') self.has_partial_credit = True
self.credit_type = [word.strip().lower() for word in self.credit_type] self.credit_type = partial_credit.split(',')
self.credit_type = [word.strip().lower() for word in self.credit_type]
if hasattr(self, 'setup_response'): if hasattr(self, 'setup_response'):
self.setup_response() self.setup_response()
def get_max_score(self): def get_max_score(self):
""" """
......
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