diff --git a/lobby/tests.py b/lobby/tests.py index 6b156f3..2db7cd9 100644 --- a/lobby/tests.py +++ b/lobby/tests.py @@ -687,6 +687,7 @@ class ScoreCalculationTests(TestCase): self.player_three = Player.objects.create(session=self.session, nickname="Nora") def test_host_can_calculate_scores_and_transition_to_reveal(self): + LieAnswer.objects.create(round_question=self.round_question, player=self.player_three, text="Padel") Guess.objects.create(round_question=self.round_question, player=self.player_one, selected_text="Tennis", is_correct=True) Guess.objects.create( round_question=self.round_question, @@ -715,6 +716,57 @@ class ScoreCalculationTests(TestCase): payload = response.json() self.assertEqual(payload["session"]["status"], GameSession.Status.REVEAL) self.assertEqual(payload["events_created"], 2) + self.assertEqual(payload["reveal"]["correct_answer"], "Tennis") + self.assertEqual( + payload["reveal"]["lies"], + [ + { + "player_id": self.player_three.id, + "nickname": "Nora", + "text": "Padel", + "created_at": payload["reveal"]["lies"][0]["created_at"], + } + ], + ) + self.assertEqual( + [ + { + "player_id": item["player_id"], + "nickname": item["nickname"], + "selected_text": item["selected_text"], + "is_correct": item["is_correct"], + "fooled_player_id": item["fooled_player_id"], + "fooled_player_nickname": item.get("fooled_player_nickname"), + } + for item in payload["reveal"]["guesses"] + ], + [ + { + "player_id": self.player_one.id, + "nickname": "Luna", + "selected_text": "Tennis", + "is_correct": True, + "fooled_player_id": None, + "fooled_player_nickname": None, + }, + { + "player_id": self.player_two.id, + "nickname": "Mads", + "selected_text": "Padel", + "is_correct": False, + "fooled_player_id": self.player_three.id, + "fooled_player_nickname": "Nora", + }, + { + "player_id": self.player_three.id, + "nickname": "Nora", + "selected_text": "Padel", + "is_correct": False, + "fooled_player_id": self.player_three.id, + "fooled_player_nickname": "Nora", + }, + ], + ) self.player_one.refresh_from_db() self.player_three.refresh_from_db() @@ -1149,7 +1201,62 @@ class SessionDetailRoundQuestionTests(TestCase): self.assertEqual(payload["round_question"]["id"], round_question.id) self.assertEqual(payload["round_question"]["prompt"], self.question.prompt) + def test_session_detail_includes_reveal_payload_for_active_round_question(self): + self.session.status = GameSession.Status.REVEAL + self.session.save(update_fields=["status"]) + round_question = RoundQuestion.objects.create( + session=self.session, + round_number=1, + question=self.question, + correct_answer=self.question.correct_answer, + ) + liar = Player.objects.create(session=self.session, nickname="Bluffer") + guesser = Player.objects.create(session=self.session, nickname="Guesser") + LieAnswer.objects.create(round_question=round_question, player=liar, text="Tesla") + Guess.objects.create( + round_question=round_question, + player=guesser, + selected_text="Tesla", + is_correct=False, + fooled_player=liar, + ) + response = self.client.get(reverse("lobby:session_detail", kwargs={"code": self.session.code})) + + self.assertEqual(response.status_code, 200) + payload = response.json() + self.assertEqual(payload["reveal"]["round_question_id"], round_question.id) + self.assertEqual(payload["reveal"]["correct_answer"], "Edison") + self.assertEqual( + [ + {"player_id": lie["player_id"], "nickname": lie["nickname"], "text": lie["text"]} + for lie in payload["reveal"]["lies"] + ], + [{"player_id": liar.id, "nickname": "Bluffer", "text": "Tesla"}], + ) + self.assertEqual( + [ + { + "player_id": guess["player_id"], + "nickname": guess["nickname"], + "selected_text": guess["selected_text"], + "is_correct": guess["is_correct"], + "fooled_player_id": guess["fooled_player_id"], + "fooled_player_nickname": guess.get("fooled_player_nickname"), + } + for guess in payload["reveal"]["guesses"] + ], + [ + { + "player_id": guesser.id, + "nickname": "Guesser", + "selected_text": "Tesla", + "is_correct": False, + "fooled_player_id": liar.id, + "fooled_player_nickname": "Bluffer", + } + ], + ) class SessionDetailPhaseViewModelTests(TestCase): diff --git a/lobby/views.py b/lobby/views.py index 0282fb2..75f748b 100644 --- a/lobby/views.py +++ b/lobby/views.py @@ -61,6 +61,52 @@ def _create_unique_session_code() -> str: raise RuntimeError("Could not generate unique session code") +def _build_player_ref(player: Player | None) -> dict | None: + if player is None: + return None + + return { + "player_id": player.id, + "nickname": player.nickname, + } + + +def _build_reveal_payload(round_question: RoundQuestion | None) -> dict | None: + if round_question is None: + return None + + lies = [ + { + **_build_player_ref(lie.player), + "text": lie.text, + "created_at": lie.created_at.isoformat(), + } + for lie in round_question.lies.select_related("player").order_by("created_at", "id") + ] + + guesses = [] + for guess in round_question.guesses.select_related("player", "fooled_player").order_by("created_at", "id"): + guess_payload = { + **_build_player_ref(guess.player), + "selected_text": guess.selected_text, + "is_correct": guess.is_correct, + "created_at": guess.created_at.isoformat(), + "fooled_player_id": guess.fooled_player_id, + } + if guess.fooled_player is not None: + guess_payload["fooled_player_nickname"] = guess.fooled_player.nickname + guesses.append(guess_payload) + + return { + "round_question_id": round_question.id, + "round_number": round_question.round_number, + "prompt": round_question.question.prompt, + "correct_answer": round_question.correct_answer, + "lies": lies, + "guesses": guesses, + } + + def _build_phase_view_model(session: GameSession, *, players_count: int, has_round_question: bool) -> dict: status = session.status in_lobby = status == GameSession.Status.LOBBY @@ -238,6 +284,9 @@ def session_detail(request: HttpRequest, code: str) -> JsonResponse: }, "players": players, "round_question": round_question_payload, + "reveal": _build_reveal_payload(current_round_question) + if session.status == GameSession.Status.REVEAL and current_round_question + else None, "phase_view_model": phase_view_model, } ) @@ -909,6 +958,7 @@ def calculate_scores(request: HttpRequest, code: str, round_question_id: int) -> "id": round_question.id, "round_number": round_question.round_number, }, + "reveal": _build_reveal_payload(round_question), "events_created": len(score_events), "leaderboard": leaderboard, }