Rum: et lukket rum kan ikke vækkes igen
Efter et skift af spil midt i en runde kan det gamle rums sene opgaver (speakerens oplæsning, dommeren, ventetider) kalde changed() eller _schedule_timer() bagefter og starte timeren igen uden spillere. Nu sætter close() et flag, og changed, timeren, udsendelsen, nye replikker og Tegn og Gæts trin-snapshots gør intet i et lukket rum. Forslag fra review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+9
-2
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user