Merge pull request #19380 from stvstnfrd/show-answer

Add new Option to Show Answer Dropdown.
This commit is contained in:
David Ormsbee
2019-02-08 16:05:54 -05:00
committed by GitHub
5 changed files with 128 additions and 1 deletions

View File

@@ -16,6 +16,7 @@ MAXIMUM_ATTEMPTS = "Maximum Attempts"
PROBLEM_WEIGHT = "Problem Weight"
RANDOMIZATION = 'Randomization'
SHOW_ANSWER = "Show Answer"
SHOW_ANSWER_AFTER_SOME_NUMBER_OF_ATTEMPTS = 'Show Answer: Number of Attempts'
SHOW_RESET_BUTTON = "Show Reset Button"
TIMER_BETWEEN_ATTEMPTS = "Timer Between Attempts"
MATLAB_API_KEY = "Matlab API key"
@@ -106,6 +107,7 @@ def i_see_advanced_settings_with_values(_step):
[PROBLEM_WEIGHT, "", False],
[RANDOMIZATION, "Never", False],
[SHOW_ANSWER, "Finished", False],
[SHOW_ANSWER_AFTER_SOME_NUMBER_OF_ATTEMPTS, '0', False],
[SHOW_RESET_BUTTON, "False", False],
[TIMER_BETWEEN_ATTEMPTS, "0", False],
])

View File

@@ -139,7 +139,16 @@ class CapaFields(object):
{"display_name": _("Finished"), "value": SHOWANSWER.FINISHED},
{"display_name": _("Correct or Past Due"), "value": SHOWANSWER.CORRECT_OR_PAST_DUE},
{"display_name": _("Past Due"), "value": SHOWANSWER.PAST_DUE},
{"display_name": _("Never"), "value": SHOWANSWER.NEVER}]
{"display_name": _("Never"), "value": SHOWANSWER.NEVER},
{"display_name": _("After Some Number of Attempts"), "value": SHOWANSWER.AFTER_SOME_NUMBER_OF_ATTEMPTS},
]
)
attempts_before_showanswer_button = Integer(
display_name=_("Show Answer: Number of Attempts"),
help=_("Number of times the student must attempt to answer the question before the Show Answer button appears."),
values={"min": 0},
default=0,
scope=Scope.settings,
)
force_save_button = Boolean(
help=_("Whether to force the save button to appear on the page"),
@@ -913,6 +922,11 @@ class CapaMixin(ScorableXBlockMixin, CapaFields):
return self.is_correct() or self.is_past_due()
elif self.showanswer == SHOWANSWER.PAST_DUE:
return self.is_past_due()
elif self.showanswer == SHOWANSWER.AFTER_SOME_NUMBER_OF_ATTEMPTS:
required_attempts = self.attempts_before_showanswer_button
if self.max_attempts and required_attempts >= self.max_attempts:
required_attempts = self.max_attempts
return self.attempts >= required_attempts
elif self.showanswer == SHOWANSWER.ALWAYS:
return True

View File

@@ -16,6 +16,7 @@ class SHOWANSWER(object):
CORRECT_OR_PAST_DUE = "correct_or_past_due"
PAST_DUE = "past_due"
NEVER = "never"
AFTER_SOME_NUMBER_OF_ATTEMPTS = "after_attempts"
class RANDOMIZATION(object):

View File

@@ -415,6 +415,115 @@ class CapaModuleTest(unittest.TestCase):
graceperiod=self.two_day_delta_str)
self.assertFalse(still_in_grace.answer_available())
def test_showanswer_after_attempts_with_max(self):
"""
Button should not be visible when attempts < required attempts.
Even with max attempts set, the show answer button should only
show up after the user has attempted answering the question for
the requisite number of times, i.e `attempts_before_showanswer_button`
"""
problem = CapaFactory.create(
showanswer='after_attempts',
attempts='2',
attempts_before_showanswer_button='3',
max_attempts='5',
)
self.assertFalse(problem.answer_available())
def test_showanswer_after_attempts_no_max(self):
"""
Button should not be visible when attempts < required attempts.
Even when max attempts is NOT set, the answer should still
only be available after the student has attempted the
problem at least `attempts_before_showanswer_button` times
"""
problem = CapaFactory.create(
showanswer='after_attempts',
attempts='2',
attempts_before_showanswer_button='3',
)
self.assertFalse(problem.answer_available())
def test_showanswer_after_attempts_used_all_attempts(self):
"""
Button should be visible even after all attempts are used up.
As long as the student has attempted the question for
the requisite number of times, then the show ans. button is
visible even after they have exhausted their attempts.
"""
problem = CapaFactory.create(
showanswer='after_attempts',
attempts_before_showanswer_button='2',
max_attempts='3',
attempts='3',
due=self.tomorrow_str,
)
self.assertTrue(problem.answer_available())
def test_showanswer_after_attempts_past_due_date(self):
"""
Show Answer button should be visible even after the due date.
As long as the student has attempted the problem for the requisite
number of times, the answer should be available past the due date.
"""
problem = CapaFactory.create(
showanswer='after_attempts',
attempts_before_showanswer_button='2',
attempts='2',
due=self.yesterday_str,
)
self.assertTrue(problem.answer_available())
def test_showanswer_after_attempts_still_in_grace(self):
"""
If attempts > required attempts, ans. is available in grace period.
As long as the user has attempted for the requisite # of times,
the show answer button is visible throughout the grace period.
"""
problem = CapaFactory.create(
showanswer='after_attempts',
after_attempts='3',
attempts='4',
due=self.yesterday_str,
graceperiod=self.two_day_delta_str,
)
self.assertTrue(problem.answer_available())
def test_showanswer_after_attempts_large(self):
"""
If required attempts > max attempts then required attempts = max attempts.
Ensure that if attempts_before_showanswer_button > max_attempts,
the button should show up after all attempts are used up,
i.e after_attempts falls back to max_attempts
"""
problem = CapaFactory.create(
showanswer='after_attempts',
attempts_before_showanswer_button='5',
max_attempts='3',
attempts='3',
)
self.assertTrue(problem.answer_available())
def test_showanswer_after_attempts_zero(self):
"""
Button should always be visible if required min attempts = 0.
If attempts_before_showanswer_button = 0, then the show answer
button should be visible at all times.
"""
problem = CapaFactory.create(
showanswer='after_attempts',
attempts_before_showanswer_button='0',
attempts='0',
)
self.assertTrue(problem.answer_available())
def test_showanswer_finished(self):
"""
With showanswer="finished" should show answer after the problem is closed,

View File

@@ -56,6 +56,7 @@ class ProblemComponentEditor(ContainerBase):
'Problem Weight': u'',
'Randomization': u'Never',
'Show Answer': u'Finished',
'Show Answer: Number of Attempts': u'0',
'Show Reset Button': u'False',
'Timer Between Attempts': u'0'
}