Merge pull request #19380 from stvstnfrd/show-answer
Add new Option to Show Answer Dropdown.
This commit is contained in:
@@ -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],
|
||||
])
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user