refactor(gameplay): delegate host transition events from service
All checks were successful
CI / test-and-quality (push) Successful in 3m35s
CI / test-and-quality (pull_request) Successful in 3m35s

This commit is contained in:
2026-03-17 13:43:44 +00:00
parent a102a72a77
commit 94f940e5d8
3 changed files with 185 additions and 15 deletions

View File

@@ -1,10 +1,12 @@
import random
from dataclasses import dataclass
from typing import Any
from django.db import transaction
from django.utils import timezone
from .models import GameSession, Guess, LieAnswer, Player, Question, RoundConfig, RoundQuestion, ScoreEvent
from .payloads import build_finish_game_phase_event, build_start_next_round_phase_event
@dataclass(frozen=True)
@@ -13,12 +15,16 @@ class RoundTransitionResult:
round_config: RoundConfig
round_question: RoundQuestion
should_broadcast: bool
phase_event_name: str | None = None
phase_event_payload: dict[str, Any] | None = None
@dataclass(frozen=True)
class FinishGameResult:
session: GameSession
should_broadcast: bool
phase_event_name: str | None = None
phase_event_payload: dict[str, Any] | None = None
@dataclass(frozen=True)
@@ -110,6 +116,9 @@ def start_next_round(session: GameSession) -> RoundTransitionResult:
round_question = None
should_broadcast = False
phase_event_name = None
phase_event_payload = None
if locked_session.status == GameSession.Status.SCOREBOARD:
previous_round_config = RoundConfig.objects.filter(
session=locked_session,
@@ -137,6 +146,9 @@ def start_next_round(session: GameSession) -> RoundTransitionResult:
locked_session.status = GameSession.Status.LIE
locked_session.save(update_fields=["current_round", "status"])
should_broadcast = True
phase_event = build_start_next_round_phase_event(locked_session, next_round_config, round_question)
phase_event_name = phase_event["name"]
phase_event_payload = phase_event["payload"]
elif locked_session.status == GameSession.Status.LIE:
if locked_session.current_round <= 1:
raise ValueError("next_round_invalid_phase")
@@ -160,6 +172,8 @@ def start_next_round(session: GameSession) -> RoundTransitionResult:
round_config=next_round_config,
round_question=round_question,
should_broadcast=should_broadcast,
phase_event_name=phase_event_name,
phase_event_payload=phase_event_payload,
)
@@ -168,15 +182,25 @@ def finish_game(session: GameSession) -> FinishGameResult:
with transaction.atomic():
locked_session = GameSession.objects.select_for_update().get(pk=session.pk)
should_broadcast = False
phase_event_name = None
phase_event_payload = None
if locked_session.status == GameSession.Status.SCOREBOARD:
locked_session.status = GameSession.Status.FINISHED
locked_session.save(update_fields=["status"])
should_broadcast = True
phase_event = build_finish_game_phase_event(locked_session)
phase_event_name = phase_event["name"]
phase_event_payload = phase_event["payload"]
elif locked_session.status != GameSession.Status.FINISHED:
raise ValueError("finish_game_invalid_phase")
return FinishGameResult(session=locked_session, should_broadcast=should_broadcast)
return FinishGameResult(
session=locked_session,
should_broadcast=should_broadcast,
phase_event_name=phase_event_name,
phase_event_payload=phase_event_payload,
)