[READY][Gameplay] #310 Host transition idempotency and error catalog for scoreboard -> next round / finish #320
@@ -70,6 +70,57 @@ def build_lie_started_payload(session: GameSession, round_config: RoundConfig, r
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def build_phase_view_model(session: GameSession, *, players_count: int, has_round_question: bool) -> dict:
|
||||||
|
status = session.status
|
||||||
|
in_lobby = status == GameSession.Status.LOBBY
|
||||||
|
in_lie = status == GameSession.Status.LIE
|
||||||
|
in_guess = status == GameSession.Status.GUESS
|
||||||
|
in_scoreboard = status == GameSession.Status.SCOREBOARD
|
||||||
|
in_finished = status == GameSession.Status.FINISHED
|
||||||
|
|
||||||
|
min_players_reached = players_count >= 3
|
||||||
|
max_players_allowed = players_count <= 5
|
||||||
|
|
||||||
|
return {
|
||||||
|
"status": status,
|
||||||
|
"current_phase": status,
|
||||||
|
"round_number": session.current_round,
|
||||||
|
"players_count": players_count,
|
||||||
|
"constraints": {
|
||||||
|
"min_players_to_start": 3,
|
||||||
|
"max_players_mvp": 5,
|
||||||
|
"min_players_reached": min_players_reached,
|
||||||
|
"max_players_allowed": max_players_allowed,
|
||||||
|
},
|
||||||
|
"readiness": {
|
||||||
|
"question_ready": has_round_question,
|
||||||
|
"scoreboard_ready": status in {GameSession.Status.REVEAL, GameSession.Status.SCOREBOARD, GameSession.Status.FINISHED},
|
||||||
|
"can_advance_to_next_round": in_scoreboard,
|
||||||
|
},
|
||||||
|
"host": {
|
||||||
|
"can_start_round": in_lobby and min_players_reached and max_players_allowed,
|
||||||
|
"can_show_question": False,
|
||||||
|
"can_mix_answers": False,
|
||||||
|
"can_calculate_scores": False,
|
||||||
|
"can_reveal_scoreboard": False,
|
||||||
|
"can_start_next_round": in_scoreboard,
|
||||||
|
"can_finish_game": in_scoreboard,
|
||||||
|
},
|
||||||
|
"player": {
|
||||||
|
"can_join": status in {
|
||||||
|
GameSession.Status.LOBBY,
|
||||||
|
GameSession.Status.LIE,
|
||||||
|
GameSession.Status.GUESS,
|
||||||
|
GameSession.Status.REVEAL,
|
||||||
|
GameSession.Status.SCOREBOARD,
|
||||||
|
},
|
||||||
|
"can_submit_lie": in_lie and has_round_question,
|
||||||
|
"can_submit_guess": in_guess and has_round_question,
|
||||||
|
"can_view_final_result": in_finished,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def build_start_next_round_response(
|
def build_start_next_round_response(
|
||||||
session: GameSession,
|
session: GameSession,
|
||||||
round_config: RoundConfig,
|
round_config: RoundConfig,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from django.test import TestCase
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
from fupogfakta.models import Category, GameSession, Guess, LieAnswer, Player, Question, RoundConfig, RoundQuestion, ScoreEvent
|
from fupogfakta.models import Category, GameSession, Guess, LieAnswer, Player, Question, RoundConfig, RoundQuestion, ScoreEvent
|
||||||
from fupogfakta.payloads import build_lie_started_payload, build_reveal_payload
|
from fupogfakta.payloads import build_lie_started_payload, build_phase_view_model, build_reveal_payload
|
||||||
from fupogfakta.services import (
|
from fupogfakta.services import (
|
||||||
finish_game,
|
finish_game,
|
||||||
get_current_round_question,
|
get_current_round_question,
|
||||||
@@ -279,9 +279,16 @@ class FupOgFaktaExtractionSliceTests(TestCase):
|
|||||||
|
|
||||||
lie_payload = build_lie_started_payload(self.session, self.round_config, round_question)
|
lie_payload = build_lie_started_payload(self.session, self.round_config, round_question)
|
||||||
reveal_payload = build_reveal_payload(round_question)
|
reveal_payload = build_reveal_payload(round_question)
|
||||||
|
phase_view_model = build_phase_view_model(
|
||||||
|
self.session,
|
||||||
|
players_count=3,
|
||||||
|
has_round_question=True,
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(lie_payload["category"], {"slug": self.category.slug, "name": self.category.name})
|
self.assertEqual(lie_payload["category"], {"slug": self.category.slug, "name": self.category.name})
|
||||||
self.assertEqual(lie_payload["round_question_id"], round_question.id)
|
self.assertEqual(lie_payload["round_question_id"], round_question.id)
|
||||||
self.assertEqual(reveal_payload["correct_answer"], "1989")
|
self.assertEqual(reveal_payload["correct_answer"], "1989")
|
||||||
self.assertEqual(reveal_payload["lies"][0]["player_id"], lie.player_id)
|
self.assertEqual(reveal_payload["lies"][0]["player_id"], lie.player_id)
|
||||||
self.assertEqual(reveal_payload["guesses"][0]["fooled_player_nickname"], self.bob.nickname)
|
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"])
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ class LobbyGameplayExtractionTests(TestCase):
|
|||||||
self.assertIs(lobby_views._promote_reveal_to_scoreboard, gameplay_services.promote_reveal_to_scoreboard)
|
self.assertIs(lobby_views._promote_reveal_to_scoreboard, gameplay_services.promote_reveal_to_scoreboard)
|
||||||
self.assertIs(lobby_views._start_next_round, gameplay_services.start_next_round)
|
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._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_scoreboard_phase_event, gameplay_payloads.build_scoreboard_phase_event)
|
self.assertIs(lobby_views._build_scoreboard_phase_event, gameplay_payloads.build_scoreboard_phase_event)
|
||||||
|
|
||||||
def test_start_next_round_view_source_stays_http_thin(self):
|
def test_start_next_round_view_source_stays_http_thin(self):
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from fupogfakta.models import Category, GameSession, Guess, LieAnswer, Player, Q
|
|||||||
from fupogfakta.payloads import (
|
from fupogfakta.payloads import (
|
||||||
build_leaderboard as _build_leaderboard,
|
build_leaderboard as _build_leaderboard,
|
||||||
build_lie_started_payload as _build_lie_started_payload,
|
build_lie_started_payload as _build_lie_started_payload,
|
||||||
|
build_phase_view_model as _build_phase_view_model,
|
||||||
build_reveal_payload as _build_reveal_payload,
|
build_reveal_payload as _build_reveal_payload,
|
||||||
build_scoreboard_phase_event as _build_scoreboard_phase_event,
|
build_scoreboard_phase_event as _build_scoreboard_phase_event,
|
||||||
)
|
)
|
||||||
@@ -82,51 +83,6 @@ def _maybe_promote_reveal_to_scoreboard(session: GameSession) -> GameSession:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _build_phase_view_model(session: GameSession, *, players_count: int, has_round_question: bool) -> dict:
|
|
||||||
status = session.status
|
|
||||||
in_lobby = status == GameSession.Status.LOBBY
|
|
||||||
in_lie = status == GameSession.Status.LIE
|
|
||||||
in_guess = status == GameSession.Status.GUESS
|
|
||||||
in_scoreboard = status == GameSession.Status.SCOREBOARD
|
|
||||||
in_finished = status == GameSession.Status.FINISHED
|
|
||||||
|
|
||||||
min_players_reached = players_count >= 3
|
|
||||||
max_players_allowed = players_count <= 5
|
|
||||||
|
|
||||||
return {
|
|
||||||
"status": status,
|
|
||||||
"current_phase": status,
|
|
||||||
"round_number": session.current_round,
|
|
||||||
"players_count": players_count,
|
|
||||||
"constraints": {
|
|
||||||
"min_players_to_start": 3,
|
|
||||||
"max_players_mvp": 5,
|
|
||||||
"min_players_reached": min_players_reached,
|
|
||||||
"max_players_allowed": max_players_allowed,
|
|
||||||
},
|
|
||||||
"readiness": {
|
|
||||||
"question_ready": has_round_question,
|
|
||||||
"scoreboard_ready": status in {GameSession.Status.REVEAL, GameSession.Status.SCOREBOARD, GameSession.Status.FINISHED},
|
|
||||||
"can_advance_to_next_round": in_scoreboard,
|
|
||||||
},
|
|
||||||
"host": {
|
|
||||||
"can_start_round": in_lobby and min_players_reached and max_players_allowed,
|
|
||||||
"can_show_question": False,
|
|
||||||
"can_mix_answers": False,
|
|
||||||
"can_calculate_scores": False,
|
|
||||||
"can_reveal_scoreboard": False,
|
|
||||||
"can_start_next_round": in_scoreboard,
|
|
||||||
"can_finish_game": in_scoreboard,
|
|
||||||
},
|
|
||||||
"player": {
|
|
||||||
"can_join": status in JOINABLE_STATUSES,
|
|
||||||
"can_submit_lie": in_lie and has_round_question,
|
|
||||||
"can_submit_guess": in_guess and has_round_question,
|
|
||||||
"can_view_final_result": in_finished,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@require_POST
|
@require_POST
|
||||||
@login_required
|
@login_required
|
||||||
def create_session(request: HttpRequest) -> JsonResponse:
|
def create_session(request: HttpRequest) -> JsonResponse:
|
||||||
|
|||||||
Reference in New Issue
Block a user