'Checks whether the existing answers to a problem are correct.
This is called when the correct answer to a problem has been changed,
and the grade should be re-evaluated.
If only_if_higher is True, the answer and grade are updated
only if the resulting score is higher than before.
Returns a dict with one key:
{\'success\' : \'correct\' | \'incorrect\' | AJAX alert msg string }
Raises NotFoundError if called on a problem that has not yet been
answered, or NotImplementedError if it\'s a problem that cannot be rescored.
Returns the error messages for exceptions occurring while performing
the rescoring, rather than throwing them.'

def rescore(self, only_if_higher=False):

    event_info = {'state': self.lcp.get_state(), 'problem_id': self.location.to_deprecated_string()}
    _ = self.runtime.service(self, 'i18n').ugettext
    if (not self.lcp.supports_rescoring()):
        event_info['failure'] = 'unsupported'
        self.track_function_unmask('problem_rescore_fail', event_info)
        raise NotImplementedError(_("Problem's    definition    does    not    support    rescoring."))
    if (not self.done):
        event_info['failure'] = 'unanswered'
        self.track_function_unmask('problem_rescore_fail', event_info)
        raise NotFoundError(_('Problem    must    be    answered    before    it    can    be    graded    again.'))
    orig_score = self.get_score()
    event_info['orig_score'] = orig_score.raw_earned
    event_info['orig_total'] = orig_score.raw_possible
    try:
        calculated_score = self.calculate_score()
    except (StudentInputError, ResponseError, LoncapaProblemError) as inst:
        log.warning('Input    error    in    capa_module:problem_rescore', exc_info=True)
        event_info['failure'] = 'input_error'
        self.track_function_unmask('problem_rescore_fail', event_info)
        raise
    except Exception:
        event_info['failure'] = 'unexpected'
        self.track_function_unmask('problem_rescore_fail', event_info)
        raise
    self.set_state_from_lcp()
    self.set_score(calculated_score)
    self.publish_grade(only_if_higher)
    event_info['new_score'] = calculated_score.raw_earned
    event_info['new_total'] = calculated_score.raw_possible
    success = 'correct'
    for answer_id in self.lcp.correct_map:
        if (not self.lcp.correct_map.is_correct(answer_id)):
            success = 'incorrect'
    event_info['correct_map'] = self.lcp.correct_map.get_dict()
    event_info['success'] = success
    event_info['attempts'] = self.attempts
    self.track_function_unmask('problem_rescore', event_info)
