From 62a424312495100fab193805ae2d5f4bb1990538 Mon Sep 17 00:00:00 2001 From: Murhu Markus Date: Wed, 5 Jun 2024 15:45:29 +0300 Subject: [PATCH] Hide module model answers on lifesupport --- exercise/cache/basetypes.py | 4 ++++ exercise/cache/points.py | 16 +++++++++++----- exercise/tests.py | 7 +++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/exercise/cache/basetypes.py b/exercise/cache/basetypes.py index 9db1ba85f..f5139be2b 100644 --- a/exercise/cache/basetypes.py +++ b/exercise/cache/basetypes.py @@ -496,6 +496,8 @@ class CachedDataBase(CourseInstanceProto, CacheBase, Generic[ModuleEntry, Learni exercise_index: Dict[int, LearningObjectEntry] paths: Dict[int, Dict[str, int]] modules: List[ModuleEntry] + is_on_lifesupport: bool + lifesupport_start: Optional[datetime] categories: Dict[int, CategoryEntry] total: Totals @@ -529,6 +531,8 @@ def _generate_data( # pylint: disable=too-many-locals self.url = instance.url self.course_url_kwargs = instance.course.get_url_kwargs() + self.is_on_lifesupport = instance.is_on_lifesupport() + self.lifesupport_start = instance.lifesupport_start self.exercise_index = exercise_index = {} self.module_index = module_index = {} diff --git a/exercise/cache/points.py b/exercise/cache/points.py index cfc18e8b1..08304bb94 100644 --- a/exercise/cache/points.py +++ b/exercise/cache/points.py @@ -90,6 +90,11 @@ def none_min(a: Optional[float], b: Optional[float]) -> Optional[float]: return min(a,b) return a or b +def next_timestamp(timestamps) -> Optional[float]: + now = timezone.now().timestamp() + future_timestamps = [ts for ts in timestamps if ts and ts > now] + return min(timestamps) if future_timestamps else None + def _add_to(target: Union[ModulePoints, CategoryPoints, Totals], entry: ExercisePoints) -> None: target.feedback_revealed = target.feedback_revealed and entry.feedback_revealed @@ -952,11 +957,12 @@ def add_points(children): self.is_model_answer_revealed = True else: state = ModuleRevealState(self) - self.is_model_answer_revealed = reveal_rule.is_revealed(state) - if not self.is_model_answer_revealed: - reveal_time = reveal_rule.get_reveal_time(state) - timestamp = reveal_time and reveal_time.timestamp() - self._expires_on = none_min(self._expires_on, timestamp) + self.is_model_answer_revealed = reveal_rule.is_revealed(state) and \ + not self.instance.is_on_lifesupport + reveal_time = reveal_rule.get_reveal_time(state) + reveal_rule_timestamp = reveal_time and reveal_time.timestamp() + self._expires_on = next_timestamp([reveal_rule_timestamp, + self.instance.lifesupport_start.timestamp()]) return { ModuleEntryBase: [self._params[:1]], diff --git a/exercise/tests.py b/exercise/tests.py index d328a1cf7..1d693e90d 100644 --- a/exercise/tests.py +++ b/exercise/tests.py @@ -994,6 +994,13 @@ def test_can_be_shown_as_module_model_solution(self): self.assertTrue(self.base_exercise.can_be_shown_as_module_model_solution(self.user)) self.assertTrue(self.static_exercise.can_be_shown_as_module_model_solution(self.user)) + self.course_instance.ending_time = self.today - timedelta(days=2) + self.course_instance.lifesupport_time = self.yesterday + self.course_instance.save() + # Model answer chapters not visible after lifesupport time + self.assertFalse(chapter.can_be_shown_as_module_model_solution(self.user)) + self.assertFalse(self.base_exercise.can_be_shown_as_module_model_solution(self.user2)) + def test_reveal_rule(self): reveal_rule = RevealRule.objects.create( trigger=RevealRule.TRIGGER.MANUAL,