From 1a02cfec8350dd8bc98beeef70aaa632ea9b2021 Mon Sep 17 00:00:00 2001 From: kimth Date: Sat, 15 Sep 2012 23:25:26 -0400 Subject: [PATCH 1/6] Reset CapaProblem when state HTML is corrupt --- common/lib/xmodule/xmodule/capa_module.py | 36 ++++++++++++++++++----- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 8bf1a56404..a344d2981d 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -131,17 +131,17 @@ class CapaModule(XModule): self.weight = None if self.rerandomize == 'never': - seed = 1 + self.seed = 1 elif self.rerandomize == "per_student" and hasattr(self.system, 'id'): - seed = system.id + self.seed = system.id else: - seed = None + self.seed = None try: # TODO (vshnayder): move as much as possible of this work and error # checking to descriptor load time self.lcp = LoncapaProblem(self.definition['data'], self.location.html_id(), - instance_state, seed=seed, system=self.system) + instance_state, seed=self.seed, system=self.system) except Exception as err: msg = 'cannot create LoncapaProblem {loc}: {err}'.format( loc=self.location.url(), err=err) @@ -160,7 +160,7 @@ class CapaModule(XModule): (self.location.url(), msg)) self.lcp = LoncapaProblem( problem_text, self.location.html_id(), - instance_state, seed=seed, system=self.system) + instance_state, seed=self.seed, system=self.system) else: # add extra info and raise raise Exception(msg), None, sys.exc_info()[2] @@ -220,9 +220,10 @@ class CapaModule(XModule): try: html = self.lcp.get_html() except Exception, err: + log.exception(err) + # TODO (vshnayder): another switch on DEBUG. if self.system.DEBUG: - log.exception(err) msg = ( '[courseware.capa.capa_module] ' 'Failed to generate HTML for problem %s' % @@ -231,7 +232,28 @@ class CapaModule(XModule): msg += '

%s

' % traceback.format_exc().replace('<', '<') html = msg else: - raise + # We're in non-debug mode, and possibly even in production. We want + # to avoid bricking of problem as much as possible + + # Presumably, student submission has corrupted LoncapaProblem HTML. + # So, let's try generate a fresh LoncapaProblem + self.lcp = LoncapaProblem(self.definition['data'], self.location.html_id(), + state=None, # Tabula rasa + seed=self.seed, system=self.system) + + # Prepend a scary warning to the student + warning = '
' + warning += '

Problem state was corruped by invalid input. ' + warning += 'Problem reset to initial state! ' + warning += 'If problem persists, please contact the course staff.

' + warning += '
' + + html = warning + try: + html += self.lcp.get_html() + except Exception, err: # Couldn't do it. Give up + log.exception(err) + raise content = {'name': self.display_name, 'html': html, From 827e211ac75f59ff0c19373f6b31cde06e2f55c2 Mon Sep 17 00:00:00 2001 From: kimth Date: Sun, 16 Sep 2012 00:27:41 -0400 Subject: [PATCH 2/6] Reveal student input at state of problem reset back to student --- common/lib/xmodule/xmodule/capa_module.py | 26 +++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index a344d2981d..894d23c342 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -1,3 +1,4 @@ +import cgi import datetime import dateutil import dateutil.parser @@ -236,16 +237,33 @@ class CapaModule(XModule): # to avoid bricking of problem as much as possible # Presumably, student submission has corrupted LoncapaProblem HTML. - # So, let's try generate a fresh LoncapaProblem + # First, pull down all student answers + student_answers = self.lcp.student_answers + answer_ids = student_answers.keys() + + # Some inputtypes, such as dynamath, have additional "hidden" state that + # is not exposed to the student. Keep those hidden + hidden_state_keywords = ['dynamath'] + for answer_id in answer_ids: + for hidden_state_keyword in hidden_state_keywords: + if answer_id.find(hidden_state_keyword) >= 0: + student_answers.pop(answer_id) + + # Next, generate a fresh LoncapaProblem self.lcp = LoncapaProblem(self.definition['data'], self.location.html_id(), state=None, # Tabula rasa seed=self.seed, system=self.system) # Prepend a scary warning to the student warning = '
' - warning += '

Problem state was corruped by invalid input. ' - warning += 'Problem reset to initial state! ' - warning += 'If problem persists, please contact the course staff.

' + warning += '

Problem reset to initial state!

' + warning += '

Problem state was corruped by invalid submission. The submission consisted of:

' + warning += '
    ' + for student_answer in student_answers.values(): + if student_answer != '': + warning += '
  • ' + cgi.escape(student_answer) + '
  • ' + warning += '
' + warning += '

If problem persists, please contact the course staff.

' warning += '
' html = warning From eac8037808c8c480ce3c34d6e39df06e21c2acdf Mon Sep 17 00:00:00 2001 From: kimth Date: Sun, 16 Sep 2012 00:29:48 -0400 Subject: [PATCH 3/6] Add TODO comment --- common/lib/xmodule/xmodule/capa_module.py | 1 + 1 file changed, 1 insertion(+) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 894d23c342..9eeaa57896 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -243,6 +243,7 @@ class CapaModule(XModule): # Some inputtypes, such as dynamath, have additional "hidden" state that # is not exposed to the student. Keep those hidden + # TODO: Use regex, e.g. 'dynamath' is suffix at end of answer_id hidden_state_keywords = ['dynamath'] for answer_id in answer_ids: for hidden_state_keyword in hidden_state_keywords: From f5d6f080c7dc05e78dafe6062dcd20e9049393df Mon Sep 17 00:00:00 2001 From: kimth Date: Sun, 16 Sep 2012 00:47:40 -0400 Subject: [PATCH 4/6] Add basic styles --- common/lib/xmodule/xmodule/capa_module.py | 14 +++++++------- common/lib/xmodule/xmodule/css/capa/display.scss | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 9eeaa57896..f6ba0d278d 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -256,16 +256,16 @@ class CapaModule(XModule): seed=self.seed, system=self.system) # Prepend a scary warning to the student - warning = '
' - warning += '

Problem reset to initial state!

' - warning += '

Problem state was corruped by invalid submission. The submission consisted of:

' - warning += '
    ' + warning = '
    '\ + '

    Warning: Problem reset to initial state!

    '\ + 'Problem state was corruped by invalid submission. The submission consisted of:'\ + '
      ' for student_answer in student_answers.values(): if student_answer != '': warning += '
    • ' + cgi.escape(student_answer) + '
    • ' - warning += '
    ' - warning += '

    If problem persists, please contact the course staff.

    ' - warning += '
    ' + warning += '
'\ + 'If problem persists, please contact the course staff.'\ + '
' html = warning try: diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index 0591a01843..944904ca54 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -465,6 +465,22 @@ section.problem { margin-top: 10px; } + div.capa_reset { + padding: 25px; + border: 1px solid #EBE8BF; + border-radius: 3px; + background: #FFFCDD; + font-size: 1em; + margin-top: 10px; + margin-bottom: 10px; + } + .capa_reset>h2 { + color: #FF0000; + } + .capa_reset li { + font-size: 0.9em; + } + .hints { border: 1px solid #ccc; From 2c239f87e890467111c1933b585a066c6aa658f5 Mon Sep 17 00:00:00 2001 From: kimth Date: Sun, 16 Sep 2012 00:48:53 -0400 Subject: [PATCH 5/6] Change wording of warning slightly --- common/lib/xmodule/xmodule/capa_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index f6ba0d278d..17b5e2921a 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -264,7 +264,7 @@ class CapaModule(XModule): if student_answer != '': warning += '
  • ' + cgi.escape(student_answer) + '
  • ' warning += ''\ - 'If problem persists, please contact the course staff.'\ + 'If the problem persists, please contact the course staff.'\ '' html = warning From 7682663e1b90a1566bab37987df02b817863415a Mon Sep 17 00:00:00 2001 From: Arjun Singh Date: Sat, 15 Sep 2012 22:07:10 -0700 Subject: [PATCH 6/6] Make broken problem error a bit scarier and fix typo in message --- common/lib/xmodule/xmodule/capa_module.py | 7 ++++--- common/lib/xmodule/xmodule/css/capa/display.scss | 6 +++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/common/lib/xmodule/xmodule/capa_module.py b/common/lib/xmodule/xmodule/capa_module.py index 17b5e2921a..a891474581 100644 --- a/common/lib/xmodule/xmodule/capa_module.py +++ b/common/lib/xmodule/xmodule/capa_module.py @@ -257,14 +257,15 @@ class CapaModule(XModule): # Prepend a scary warning to the student warning = '
    '\ - '

    Warning: Problem reset to initial state!

    '\ - 'Problem state was corruped by invalid submission. The submission consisted of:'\ + '

    Warning: The problem has been reset to its initial state!

    '\ + 'The problem\'s state was corrupted by an invalid submission. ' \ + 'The submission consisted of:'\ '
      ' for student_answer in student_answers.values(): if student_answer != '': warning += '
    • ' + cgi.escape(student_answer) + '
    • ' warning += '
    '\ - 'If the problem persists, please contact the course staff.'\ + 'If this error persists, please contact the course staff.'\ '
    ' html = warning diff --git a/common/lib/xmodule/xmodule/css/capa/display.scss b/common/lib/xmodule/xmodule/css/capa/display.scss index 944904ca54..f349de31b5 100644 --- a/common/lib/xmodule/xmodule/css/capa/display.scss +++ b/common/lib/xmodule/xmodule/css/capa/display.scss @@ -467,15 +467,15 @@ section.problem { div.capa_reset { padding: 25px; - border: 1px solid #EBE8BF; + border: 1px solid $error-red; + background-color: lighten($error-red, 25%); border-radius: 3px; - background: #FFFCDD; font-size: 1em; margin-top: 10px; margin-bottom: 10px; } .capa_reset>h2 { - color: #FF0000; + color: #AA0000; } .capa_reset li { font-size: 0.9em;