Add new Option to Show Answer Dropdown.

In Studio: Introduces a new option, `after some number of attempts`
and a new entry box for specifying the number of attempts.
This allows course creators to specify that a given question's
answer is only viewable, i.e its show answer button is visible,
after the learner has attempted answering the question -
by hitting the submit button - a given number of times. Included
in this commit are unit tests for the new feature.
This commit is contained in:
Joseph Okonda
2017-06-30 12:16:23 -07:00
committed by stv
parent bfc0c5acf5
commit 4a98e4626a
3 changed files with 125 additions and 1 deletions

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,