diff --git a/party/rooms.py b/party/rooms.py index eb6ac07..e2ebc94 100644 --- a/party/rooms.py +++ b/party/rooms.py @@ -58,6 +58,7 @@ class BaseRoom: Spillet (`game`) skal have deadline, hold_until, tick(), phase_key() og drain_events().""" mic_laughs = 0 + closed = False # lukket (fx skiftet til et andet spil): sene opgaver må ikke vække rummet igen def __init__(self, code: str, game, host_username: str): self.code = code @@ -84,6 +85,8 @@ class BaseRoom: def changed(self): """Kald efter hver ændring: planlæg timer og send nyt snapshot til alle.""" + if self.closed: + return self.touch() self._phase_key = self.game.phase_key() self.handle_events() @@ -111,7 +114,7 @@ class BaseRoom: self.game.hold_until = hold def broadcast(self): - if not self._broadcast_pending: + if not self._broadcast_pending and not self.closed: self._broadcast_pending = True asyncio.get_running_loop().create_task(self._broadcast()) @@ -130,6 +133,8 @@ class BaseRoom: if self._timer: self._timer.cancel() self._timer = None + if self.closed: + return deadline = self.game.deadline if deadline is not None: when = max(deadline, self.game.hold_until or 0) @@ -151,8 +156,10 @@ class BaseRoom: self._schedule_timer() def close(self): + self.closed = True if self._timer: self._timer.cancel() + self._timer = None for h in self._side_timers: h.cancel() if self._voice_task: @@ -210,7 +217,7 @@ class BaseRoom: def say(self, text: str | None, blocking: bool = True, voice: str | None = None): """Læg en replik i kø. Lyden genereres med det samme, men udgives i rækkefølge. blocking=False: en sidebemærkning, som ikke holder skærmen tilbage (fx "det var sandheden").""" - if not text: + if not text or self.closed: return if self._voice_queue is None: self._voice_queue = asyncio.Queue() diff --git a/party/tegn.py b/party/tegn.py index 6ec4536..8c19bee 100644 --- a/party/tegn.py +++ b/party/tegn.py @@ -55,6 +55,8 @@ class TegnRoom(rooms.BaseRoom): for h in self._beat_timers: h.cancel() self._beat_timers = [] + if self.closed: + return g = self.game if g.phase != "reveal": return diff --git a/party/tests/test_switch.py b/party/tests/test_switch.py index 10098c3..c14f0c7 100644 --- a/party/tests/test_switch.py +++ b/party/tests/test_switch.py @@ -181,3 +181,27 @@ class SwitchGameTests(TransactionTestCase): self.assertEqual((st["game"], st["me"]["role"], st["me"]["name"]), ("fof", "audience", "Spiller9")) await phone.disconnect() room.close() + + async def test_a_closed_room_stays_asleep(self): + """Sene opgaver i det gamle rum (speaker, dommer, timere) må ikke vække det efter et skift midt i et spil.""" + await asyncio.to_thread(make_bank) + resp = await self.async_client.post("/host/new", {"game": "fof"}, **HOST) + old = rooms.get_room(resp["Location"].rstrip("/").rsplit("/", 1)[-1]) + for n in ("A", "B"): + old.game.join(n) + old.game.start(None, 0) + old.changed() + self.assertIsNotNone(old._timer) # kategorien har en deadline + create_tegn_room("agw", "http://testserver", code=old.code) + self.assertTrue(old.closed) + self.assertIsNone(old._timer) + await asyncio.sleep(0.01) # udsendelsen fra før skiftet er sendt (til ingen) + old.changed() # som når en sen opgave er færdig + old._schedule_timer() + old.say("en sen replik") + old.broadcast() + self.assertIsNone(old._timer) + self.assertFalse(old._broadcast_pending) + self.assertIsNone(old._voice_queue) + self.assertIsInstance(rooms.get_room(old.code), TegnRoom) + rooms.get_room(old.code).close()