From dd615796f40f906e4ae3518aaf435bf861492711 Mon Sep 17 00:00:00 2001 From: DEV-bot Date: Wed, 18 Mar 2026 01:33:47 +0000 Subject: [PATCH] refactor(payloads): delegate session detail gameplay payload --- fupogfakta/payloads.py | 22 ++++++++++++++++++++++ fupogfakta/tests.py | 32 ++++++++++++++++++++++++++++++++ lobby/tests.py | 13 +++++++------ lobby/views.py | 20 ++++---------------- 4 files changed, 65 insertions(+), 22 deletions(-) diff --git a/fupogfakta/payloads.py b/fupogfakta/payloads.py index 16cf5e3..15fce65 100644 --- a/fupogfakta/payloads.py +++ b/fupogfakta/payloads.py @@ -134,6 +134,28 @@ def build_phase_view_model(session: GameSession, *, players_count: int, has_roun } +def build_session_detail_gameplay_payload( + session: GameSession, + *, + current_round_question: RoundQuestion | None, + players_count: int, +) -> dict: + return { + "round_question": build_round_question_payload(current_round_question), + "reveal": build_reveal_payload(current_round_question) + if session.status in {GameSession.Status.REVEAL, GameSession.Status.SCOREBOARD} and current_round_question + else None, + "scoreboard": build_scoreboard_phase_event(session)["payload"]["leaderboard"] + if session.status in {GameSession.Status.SCOREBOARD, GameSession.Status.FINISHED} + else None, + "phase_view_model": build_phase_view_model( + session, + players_count=players_count, + has_round_question=bool(current_round_question), + ), + } + + def build_start_round_response( session: GameSession, round_config: RoundConfig, diff --git a/fupogfakta/tests.py b/fupogfakta/tests.py index 68594a0..bb6237f 100644 --- a/fupogfakta/tests.py +++ b/fupogfakta/tests.py @@ -11,6 +11,7 @@ from fupogfakta.payloads import ( build_phase_view_model, build_reveal_payload, build_round_question_payload, + build_session_detail_gameplay_payload, ) from fupogfakta.services import ( finish_game, @@ -343,3 +344,34 @@ class FupOgFaktaExtractionSliceTests(TestCase): self.assertEqual(reveal_payload["guesses"][0]["fooled_player_nickname"], self.bob.nickname) self.assertTrue(phase_view_model["host"]["can_start_round"]) self.assertFalse(phase_view_model["host"]["can_finish_game"]) + + def test_build_session_detail_gameplay_payload_keeps_session_detail_semantics_in_cartridge(self): + self.session.status = GameSession.Status.SCOREBOARD + self.session.save(update_fields=["status"]) + round_question = RoundQuestion.objects.create( + session=self.session, + round_number=1, + question=self.question_one, + correct_answer=self.question_one.correct_answer, + ) + lie = LieAnswer.objects.create(round_question=round_question, player=self.bob, text="1991") + Guess.objects.create( + round_question=round_question, + player=self.alice, + selected_text="1991", + is_correct=False, + fooled_player=self.bob, + ) + + gameplay_payload = build_session_detail_gameplay_payload( + self.session, + current_round_question=round_question, + players_count=3, + ) + + self.assertEqual(gameplay_payload["round_question"]["id"], round_question.id) + self.assertEqual(gameplay_payload["reveal"]["lies"][0]["player_id"], lie.player_id) + self.assertEqual(gameplay_payload["scoreboard"], [{"id": self.alice.id, "nickname": self.alice.nickname, "score": self.alice.score}, {"id": self.bob.id, "nickname": self.bob.nickname, "score": self.bob.score}, {"id": self.clara.id, "nickname": self.clara.nickname, "score": self.clara.score}]) + self.assertEqual(gameplay_payload["phase_view_model"]["status"], GameSession.Status.SCOREBOARD) + self.assertTrue(gameplay_payload["phase_view_model"]["host"]["can_start_next_round"]) + self.assertTrue(gameplay_payload["phase_view_model"]["host"]["can_finish_game"]) diff --git a/lobby/tests.py b/lobby/tests.py index f455eba..cc65eb8 100644 --- a/lobby/tests.py +++ b/lobby/tests.py @@ -61,8 +61,7 @@ class LobbyGameplayExtractionTests(TestCase): self.assertIs(lobby_views._show_question, gameplay_services.show_question) self.assertIs(lobby_views._start_next_round, gameplay_services.start_next_round) self.assertIs(lobby_views._finish_game, gameplay_services.finish_game) - self.assertIs(lobby_views._build_phase_view_model, gameplay_payloads.build_phase_view_model) - self.assertIs(lobby_views._build_round_question_payload, gameplay_payloads.build_round_question_payload) + self.assertIs(lobby_views._build_session_detail_gameplay_payload, gameplay_payloads.build_session_detail_gameplay_payload) self.assertIs(lobby_views._build_scoreboard_phase_event, gameplay_payloads.build_scoreboard_phase_event) def test_start_round_view_source_stays_http_thin(self): @@ -113,10 +112,12 @@ class LobbyGameplayExtractionTests(TestCase): self.assertIn("session = _maybe_promote_reveal_to_scoreboard(session)", source) self.assertIn("current_round_question = _get_current_round_question(session)", source) - self.assertIn("round_question_payload = _build_round_question_payload(current_round_question)", source) - self.assertIn("phase_view_model = _build_phase_view_model(", source) - self.assertIn('"scoreboard": _build_scoreboard_phase_event(session)["payload"]["leaderboard"]', source) - self.assertIn('"reveal": _build_reveal_payload(current_round_question)', source) + self.assertIn("gameplay_payload = _build_session_detail_gameplay_payload(", source) + self.assertIn("**gameplay_payload", source) + self.assertNotIn("build_round_question_payload", source) + self.assertNotIn("build_phase_view_model", source) + self.assertNotIn("build_reveal_payload", source) + self.assertNotIn("build_scoreboard_phase_event(session)[\"payload\"][\"leaderboard\"]", source) self.assertNotIn("lies.select_related", source) self.assertNotIn("guesses.select_related", source) self.assertNotIn("Player.objects.filter(session=session)", source) diff --git a/lobby/views.py b/lobby/views.py index ba26a79..d569386 100644 --- a/lobby/views.py +++ b/lobby/views.py @@ -11,9 +11,7 @@ from django.views.decorators.http import require_GET, require_POST from fupogfakta.models import GameSession, Guess, LieAnswer, Player, RoundConfig, RoundQuestion, ScoreEvent from fupogfakta.payloads import ( build_leaderboard as _build_leaderboard, - build_phase_view_model as _build_phase_view_model, - build_reveal_payload as _build_reveal_payload, - build_round_question_payload as _build_round_question_payload, + build_session_detail_gameplay_payload as _build_session_detail_gameplay_payload, build_scoreboard_phase_event as _build_scoreboard_phase_event, ) from fupogfakta.services import ( @@ -192,13 +190,10 @@ def session_detail(request: HttpRequest, code: str) -> JsonResponse: session = _maybe_promote_reveal_to_scoreboard(session) current_round_question = _get_current_round_question(session) - - round_question_payload = _build_round_question_payload(current_round_question) - - phase_view_model = _build_phase_view_model( + gameplay_payload = _build_session_detail_gameplay_payload( session, + current_round_question=current_round_question, players_count=len(players), - has_round_question=bool(current_round_question), ) return JsonResponse( @@ -211,14 +206,7 @@ def session_detail(request: HttpRequest, code: str) -> JsonResponse: "players_count": len(players), }, "players": players, - "round_question": round_question_payload, - "reveal": _build_reveal_payload(current_round_question) - if session.status in {GameSession.Status.REVEAL, GameSession.Status.SCOREBOARD} and current_round_question - else None, - "scoreboard": _build_scoreboard_phase_event(session)["payload"]["leaderboard"] - if session.status in {GameSession.Status.SCOREBOARD, GameSession.Status.FINISHED} - else None, - "phase_view_model": phase_view_model, + **gameplay_payload, } )