Captures all brainstormed decisions: - Pluggable game cartridge platform (GameDriver interface) - Celery + Redis timer-driven phase transitions - Session owner play/pause/exit controls (no skip) - Escalating scoring per round, incremental reveal scoring - Emoji reactions during guess phase → post-game awards - Relational per-user config presets with game-specific models - Ephemeral game state (no persistence after exit/finish) - Full WebSocket event reference and data lifecycle Also: updated TODO.md (WebSocket done, persisted answers done), created CLAUDE.md, and PROMPT.md for ralph-loop. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
21 lines
781 B
Python
21 lines
781 B
Python
from asgiref.sync import async_to_sync
|
|
from channels.layers import get_channel_layer
|
|
|
|
|
|
async def broadcast_phase_event(session_code: str, event_type: str, payload: dict) -> None:
|
|
"""Send a phase event to all WebSocket clients connected to a game session."""
|
|
channel_layer = get_channel_layer()
|
|
group_name = f"game_{session_code.upper()}"
|
|
await channel_layer.group_send(
|
|
group_name,
|
|
{
|
|
"type": "phase_event",
|
|
"payload": {"type": event_type, **payload},
|
|
},
|
|
)
|
|
|
|
|
|
def sync_broadcast_phase_event(session_code: str, event_type: str, payload: dict) -> None:
|
|
"""Sync wrapper for calling broadcast_phase_event from synchronous Django views."""
|
|
async_to_sync(broadcast_phase_event)(session_code, event_type, payload)
|