'This is called by courseware.module_render, to handle an AJAX call.
`data` is request.POST.
Returns a json dictionary:
{ \'progress_changed\' : True/False,
\'progress\' : \'none\'/\'in_progress\'/\'done\',
<other request-specific values here > }'

def handle_ajax(self, dispatch, data):

    handlers = {'hint_button': self.hint_button, 'problem_get': self.get_problem, 'problem_check': self.submit_problem, 'problem_reset': self.reset_problem, 'problem_save': self.save_problem, 'problem_show': self.get_answer, 'score_update': self.update_score, 'input_ajax': self.handle_input_ajax, 'ungraded_response': self.handle_ungraded_response}
    _ = self.runtime.service(self, 'i18n').ugettext
    generic_error_message = _("We're    sorry,    there    was    an    error    with    processing    your    request.    Please    try    reloading    your    page    and    trying    again.")
    not_found_error_message = _('The    state    of    this    problem    has    changed    since    you    loaded    this    page.    Please    refresh    your    page.')
    if (dispatch not in handlers):
        return 'Error:    {}    is    not    a    known    capa    action'.format(dispatch)
    before = self.get_progress()
    before_attempts = self.attempts
    try:
        result = handlers[dispatch](data)
    except NotFoundError:
        log.info('Unable    to    find    data    when    dispatching    %s    to    %s    for    user    %s', dispatch, self.scope_ids.usage_id, self.scope_ids.user_id)
        (_, _, traceback_obj) = sys.exc_info()
        raise ProcessingError(not_found_error_message), None, traceback_obj
    except Exception:
        log.exception('Unknown    error    when    dispatching    %s    to    %s    for    user    %s', dispatch, self.scope_ids.usage_id, self.scope_ids.user_id)
        (_, _, traceback_obj) = sys.exc_info()
        raise ProcessingError(generic_error_message), None, traceback_obj
    after = self.get_progress()
    after_attempts = self.attempts
    progress_changed = ((after != before) or (after_attempts != before_attempts))
    (curr_score, total_possible) = self.get_display_progress()
    result.update({'progress_changed': progress_changed, 'current_score': curr_score, 'total_possible': total_possible, 'attempts_used': after_attempts})
    return json.dumps(result, cls=ComplexEncoder)
