146 lines
4.7 KiB
Python
146 lines
4.7 KiB
Python
from datetime import timedelta
|
|
|
|
from .models import GameSession, Player, RoundConfig, RoundQuestion
|
|
|
|
|
|
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_leaderboard(session: GameSession) -> list[dict]:
|
|
return list(
|
|
Player.objects.filter(session=session)
|
|
.order_by("-score", "nickname")
|
|
.values("id", "nickname", "score")
|
|
)
|
|
|
|
|
|
def build_lie_started_payload(session: GameSession, round_config: RoundConfig, round_question: RoundQuestion) -> dict:
|
|
lie_deadline_at = round_question.shown_at + timedelta(seconds=round_config.lie_seconds)
|
|
return {
|
|
"round_number": session.current_round,
|
|
"category": {"slug": round_config.category.slug, "name": round_config.category.name},
|
|
"round_question_id": round_question.id,
|
|
"prompt": round_question.question.prompt,
|
|
"shown_at": round_question.shown_at.isoformat(),
|
|
"lie_deadline_at": lie_deadline_at.isoformat(),
|
|
"lie_seconds": round_config.lie_seconds,
|
|
}
|
|
|
|
|
|
def build_start_next_round_response(
|
|
session: GameSession,
|
|
round_config: RoundConfig,
|
|
round_question: RoundQuestion,
|
|
) -> dict:
|
|
lie_started_payload = build_lie_started_payload(session, round_config, round_question)
|
|
return {
|
|
"session": {
|
|
"code": session.code,
|
|
"status": session.status,
|
|
"current_round": session.current_round,
|
|
},
|
|
"round": {
|
|
"number": round_config.number,
|
|
"category": {
|
|
"slug": round_config.category.slug,
|
|
"name": round_config.category.name,
|
|
},
|
|
},
|
|
"round_question": {
|
|
"id": round_question.id,
|
|
"prompt": round_question.question.prompt,
|
|
"round_number": round_question.round_number,
|
|
"shown_at": round_question.shown_at.isoformat(),
|
|
"lie_deadline_at": lie_started_payload["lie_deadline_at"],
|
|
},
|
|
"config": {
|
|
"lie_seconds": round_config.lie_seconds,
|
|
},
|
|
}
|
|
|
|
|
|
def build_start_next_round_phase_event(
|
|
session: GameSession,
|
|
round_config: RoundConfig,
|
|
round_question: RoundQuestion,
|
|
) -> dict:
|
|
return {
|
|
"name": "phase.lie_started",
|
|
"payload": build_lie_started_payload(session, round_config, round_question),
|
|
}
|
|
|
|
|
|
def build_scoreboard_phase_event(session: GameSession, leaderboard: list[dict] | None = None) -> dict:
|
|
return {
|
|
"name": "phase.scoreboard",
|
|
"payload": {
|
|
"leaderboard": leaderboard if leaderboard is not None else build_leaderboard(session),
|
|
"current_round": session.current_round,
|
|
},
|
|
}
|
|
|
|
|
|
def build_finish_game_phase_event(session: GameSession) -> dict:
|
|
leaderboard = build_leaderboard(session)
|
|
winner = leaderboard[0] if leaderboard else None
|
|
return {
|
|
"name": "phase.game_over",
|
|
"payload": {"winner": winner, "leaderboard": leaderboard},
|
|
}
|
|
|
|
|
|
def build_finish_game_response(session: GameSession) -> dict:
|
|
finish_event = build_finish_game_phase_event(session)
|
|
return {
|
|
"session": {
|
|
"code": session.code,
|
|
"status": GameSession.Status.FINISHED,
|
|
"current_round": session.current_round,
|
|
},
|
|
"winner": finish_event["payload"]["winner"],
|
|
"leaderboard": finish_event["payload"]["leaderboard"],
|
|
}
|