fix(gameplay): refresh stale next-round bootstrap config
This commit is contained in:
@@ -140,21 +140,44 @@ def start_next_round(session: GameSession) -> RoundTransitionResult:
|
|||||||
raise ValueError("round_config_missing")
|
raise ValueError("round_config_missing")
|
||||||
|
|
||||||
next_round_number = locked_session.current_round + 1
|
next_round_number = locked_session.current_round + 1
|
||||||
next_round_config = RoundConfig(
|
next_round_config, _created = RoundConfig.objects.get_or_create(
|
||||||
session=locked_session,
|
session=locked_session,
|
||||||
number=next_round_number,
|
number=next_round_number,
|
||||||
category=previous_round_config.category,
|
defaults={
|
||||||
lie_seconds=previous_round_config.lie_seconds,
|
"category": previous_round_config.category,
|
||||||
guess_seconds=previous_round_config.guess_seconds,
|
"lie_seconds": previous_round_config.lie_seconds,
|
||||||
points_correct=previous_round_config.points_correct,
|
"guess_seconds": previous_round_config.guess_seconds,
|
||||||
points_bluff=previous_round_config.points_bluff,
|
"points_correct": previous_round_config.points_correct,
|
||||||
started_from_scoreboard=True,
|
"points_bluff": previous_round_config.points_bluff,
|
||||||
|
"started_from_scoreboard": True,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
round_config_update_fields: list[str] = []
|
||||||
|
if next_round_config.category_id != previous_round_config.category_id:
|
||||||
|
next_round_config.category = previous_round_config.category
|
||||||
|
round_config_update_fields.append("category")
|
||||||
|
if next_round_config.lie_seconds != previous_round_config.lie_seconds:
|
||||||
|
next_round_config.lie_seconds = previous_round_config.lie_seconds
|
||||||
|
round_config_update_fields.append("lie_seconds")
|
||||||
|
if next_round_config.guess_seconds != previous_round_config.guess_seconds:
|
||||||
|
next_round_config.guess_seconds = previous_round_config.guess_seconds
|
||||||
|
round_config_update_fields.append("guess_seconds")
|
||||||
|
if next_round_config.points_correct != previous_round_config.points_correct:
|
||||||
|
next_round_config.points_correct = previous_round_config.points_correct
|
||||||
|
round_config_update_fields.append("points_correct")
|
||||||
|
if next_round_config.points_bluff != previous_round_config.points_bluff:
|
||||||
|
next_round_config.points_bluff = previous_round_config.points_bluff
|
||||||
|
round_config_update_fields.append("points_bluff")
|
||||||
|
if not next_round_config.started_from_scoreboard:
|
||||||
|
next_round_config.started_from_scoreboard = True
|
||||||
|
round_config_update_fields.append("started_from_scoreboard")
|
||||||
|
if round_config_update_fields:
|
||||||
|
next_round_config.save(update_fields=round_config_update_fields)
|
||||||
|
|
||||||
locked_session.current_round = next_round_number
|
locked_session.current_round = next_round_number
|
||||||
|
|
||||||
round_question = reset_round_question_bootstrap_state(select_round_question(locked_session, next_round_config))
|
round_question = reset_round_question_bootstrap_state(select_round_question(locked_session, next_round_config))
|
||||||
|
|
||||||
next_round_config.save()
|
|
||||||
locked_session.status = GameSession.Status.LIE
|
locked_session.status = GameSession.Status.LIE
|
||||||
locked_session.save(update_fields=["current_round", "status"])
|
locked_session.save(update_fields=["current_round", "status"])
|
||||||
should_broadcast = True
|
should_broadcast = True
|
||||||
|
|||||||
@@ -135,6 +135,44 @@ class FupOgFaktaExtractionSliceTests(TestCase):
|
|||||||
self.assertEqual(stale_round_question.lies.count(), 0)
|
self.assertEqual(stale_round_question.lies.count(), 0)
|
||||||
self.assertEqual(stale_round_question.guesses.count(), 0)
|
self.assertEqual(stale_round_question.guesses.count(), 0)
|
||||||
|
|
||||||
|
def test_start_next_round_reuses_existing_bootstrap_round_config_with_fresh_canonical_values(self):
|
||||||
|
self.session.status = GameSession.Status.SCOREBOARD
|
||||||
|
self.session.save(update_fields=["status"])
|
||||||
|
stale_category = Category.objects.create(name="Sport", slug="sport", is_active=True)
|
||||||
|
stale_round_config = RoundConfig.objects.create(
|
||||||
|
session=self.session,
|
||||||
|
number=2,
|
||||||
|
category=stale_category,
|
||||||
|
lie_seconds=12,
|
||||||
|
guess_seconds=18,
|
||||||
|
points_correct=9,
|
||||||
|
points_bluff=7,
|
||||||
|
started_from_scoreboard=False,
|
||||||
|
)
|
||||||
|
stale_round_question = RoundQuestion.objects.create(
|
||||||
|
session=self.session,
|
||||||
|
round_number=2,
|
||||||
|
question=self.question_two,
|
||||||
|
correct_answer=self.question_two.correct_answer,
|
||||||
|
shown_at=timezone.now() - timedelta(minutes=10),
|
||||||
|
mixed_answers=["Stale truth"],
|
||||||
|
)
|
||||||
|
|
||||||
|
result = start_next_round(self.session)
|
||||||
|
|
||||||
|
stale_round_config.refresh_from_db()
|
||||||
|
stale_round_question.refresh_from_db()
|
||||||
|
self.assertEqual(result.round_config.id, stale_round_config.id)
|
||||||
|
self.assertEqual(RoundConfig.objects.filter(session=self.session, number=2).count(), 1)
|
||||||
|
self.assertEqual(stale_round_config.category_id, self.round_config.category_id)
|
||||||
|
self.assertEqual(stale_round_config.lie_seconds, self.round_config.lie_seconds)
|
||||||
|
self.assertEqual(stale_round_config.guess_seconds, self.round_config.guess_seconds)
|
||||||
|
self.assertEqual(stale_round_config.points_correct, self.round_config.points_correct)
|
||||||
|
self.assertEqual(stale_round_config.points_bluff, self.round_config.points_bluff)
|
||||||
|
self.assertTrue(stale_round_config.started_from_scoreboard)
|
||||||
|
self.assertEqual(result.round_question.id, stale_round_question.id)
|
||||||
|
self.assertEqual(stale_round_question.mixed_answers, [])
|
||||||
|
|
||||||
def test_finish_game_moves_scoreboard_transition_into_service(self):
|
def test_finish_game_moves_scoreboard_transition_into_service(self):
|
||||||
self.session.status = GameSession.Status.SCOREBOARD
|
self.session.status = GameSession.Status.SCOREBOARD
|
||||||
self.session.save(update_fields=["status"])
|
self.session.save(update_fields=["status"])
|
||||||
|
|||||||
@@ -1643,6 +1643,51 @@ class RevealRoundFlowTests(TestCase):
|
|||||||
|
|
||||||
detail_payload = self.client.get(reverse("lobby:session_detail", kwargs={"code": self.session.code})).json()
|
detail_payload = self.client.get(reverse("lobby:session_detail", kwargs={"code": self.session.code})).json()
|
||||||
self.assertEqual(detail_payload["session"]["status"], GameSession.Status.LIE)
|
self.assertEqual(detail_payload["session"]["status"], GameSession.Status.LIE)
|
||||||
|
|
||||||
|
def test_start_next_round_reuses_existing_next_round_config_with_refreshed_canonical_values(self):
|
||||||
|
self.client.login(username="host_reveal", password="secret123")
|
||||||
|
self.client.get(reverse("lobby:reveal_scoreboard", kwargs={"code": self.session.code}))
|
||||||
|
|
||||||
|
stale_category = Category.objects.create(name="Sport reveal", slug="sport-reveal", is_active=True)
|
||||||
|
stale_round_config = RoundConfig.objects.create(
|
||||||
|
session=self.session,
|
||||||
|
number=2,
|
||||||
|
category=stale_category,
|
||||||
|
lie_seconds=12,
|
||||||
|
guess_seconds=18,
|
||||||
|
points_correct=9,
|
||||||
|
points_bluff=7,
|
||||||
|
started_from_scoreboard=False,
|
||||||
|
)
|
||||||
|
stale_round_question = RoundQuestion.objects.create(
|
||||||
|
session=self.session,
|
||||||
|
round_number=2,
|
||||||
|
question=self.next_question,
|
||||||
|
correct_answer=self.next_question.correct_answer,
|
||||||
|
shown_at=timezone.now() - timedelta(minutes=10),
|
||||||
|
mixed_answers=["Stale truth"],
|
||||||
|
)
|
||||||
|
|
||||||
|
response = self.client.post(reverse("lobby:start_next_round", kwargs={"code": self.session.code}))
|
||||||
|
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.session.refresh_from_db()
|
||||||
|
stale_round_config.refresh_from_db()
|
||||||
|
stale_round_question.refresh_from_db()
|
||||||
|
self.assertEqual(self.session.status, GameSession.Status.LIE)
|
||||||
|
self.assertEqual(self.session.current_round, 2)
|
||||||
|
self.assertEqual(RoundConfig.objects.filter(session=self.session, number=2).count(), 1)
|
||||||
|
self.assertEqual(stale_round_config.category_id, self.round_config.category_id)
|
||||||
|
self.assertEqual(stale_round_config.lie_seconds, self.round_config.lie_seconds)
|
||||||
|
self.assertEqual(stale_round_config.guess_seconds, self.round_config.guess_seconds)
|
||||||
|
self.assertEqual(stale_round_config.points_correct, self.round_config.points_correct)
|
||||||
|
self.assertEqual(stale_round_config.points_bluff, self.round_config.points_bluff)
|
||||||
|
self.assertTrue(stale_round_config.started_from_scoreboard)
|
||||||
|
self.assertEqual(response.json()["round_question"]["id"], stale_round_question.id)
|
||||||
|
self.assertEqual(response.json()["config"]["lie_seconds"], self.round_config.lie_seconds)
|
||||||
|
expected_deadline = stale_round_question.shown_at + timedelta(seconds=self.round_config.lie_seconds)
|
||||||
|
self.assertEqual(response.json()["round_question"]["lie_deadline_at"], expected_deadline.isoformat())
|
||||||
|
detail_payload = self.client.get(reverse("lobby:session_detail", kwargs={"code": self.session.code})).json()
|
||||||
self.assertEqual(detail_payload["session"]["current_round"], 2)
|
self.assertEqual(detail_payload["session"]["current_round"], 2)
|
||||||
self.assertEqual(detail_payload["round_question"]["id"], stale_round_question.id)
|
self.assertEqual(detail_payload["round_question"]["id"], stale_round_question.id)
|
||||||
self.assertEqual(detail_payload["round_question"]["answers"], [])
|
self.assertEqual(detail_payload["round_question"]["answers"], [])
|
||||||
|
|||||||
Reference in New Issue
Block a user