Spaces:
Running
Running
| """ | |
| Devil's Dozen - Lobby Manager | |
| CRUD operations for the `lobbies` table. | |
| """ | |
| import secrets | |
| import string | |
| from supabase import Client | |
| from src.database.models import Lobby | |
| def _generate_code(length: int = 6) -> str: | |
| """Generate an alphanumeric lobby code, avoiding ambiguous characters.""" | |
| alphabet = string.ascii_uppercase.replace("O", "").replace("I", "") | |
| alphabet += string.digits.replace("0", "").replace("1", "") | |
| return "".join(secrets.choice(alphabet) for _ in range(length)) | |
| class LobbyManager: | |
| """Manages lobby lifecycle in Supabase.""" | |
| def __init__(self, client: Client) -> None: | |
| self.client = client | |
| self.table = client.table("lobbies") | |
| def create(self, game_mode: str, win_condition: int) -> Lobby: | |
| """Create a new lobby with a unique code.""" | |
| code = _generate_code() | |
| data = ( | |
| self.table | |
| .insert({ | |
| "code": code, | |
| "game_mode": game_mode, | |
| "win_condition": win_condition, | |
| }) | |
| .execute() | |
| ) | |
| return Lobby.model_validate(data.data[0]) | |
| def get_by_code(self, code: str) -> Lobby | None: | |
| """Look up a lobby by its join code.""" | |
| data = ( | |
| self.table | |
| .select("*") | |
| .eq("code", code.upper()) | |
| .execute() | |
| ) | |
| if data.data: | |
| return Lobby.model_validate(data.data[0]) | |
| return None | |
| def get_by_id(self, lobby_id: str) -> Lobby | None: | |
| """Look up a lobby by its UUID.""" | |
| data = ( | |
| self.table | |
| .select("*") | |
| .eq("id", lobby_id) | |
| .execute() | |
| ) | |
| if data.data: | |
| return Lobby.model_validate(data.data[0]) | |
| return None | |
| def update_status(self, lobby_id: str, status: str) -> Lobby: | |
| """Update lobby status (waiting, playing, finished).""" | |
| data = ( | |
| self.table | |
| .update({"status": status}) | |
| .eq("id", lobby_id) | |
| .execute() | |
| ) | |
| return Lobby.model_validate(data.data[0]) | |
| def advance_turn(self, lobby_id: str, next_turn_index: int) -> Lobby: | |
| """Move to the next player's turn.""" | |
| data = ( | |
| self.table | |
| .update({"current_turn_index": next_turn_index}) | |
| .eq("id", lobby_id) | |
| .execute() | |
| ) | |
| return Lobby.model_validate(data.data[0]) | |
| def set_winner(self, lobby_id: str, winner_id: str) -> Lobby: | |
| """Record the winning player and mark lobby as finished.""" | |
| data = ( | |
| self.table | |
| .update({ | |
| "winner_id": winner_id, | |
| "status": "finished", | |
| }) | |
| .eq("id", lobby_id) | |
| .execute() | |
| ) | |
| return Lobby.model_validate(data.data[0]) | |
| def delete(self, lobby_id: str) -> None: | |
| """Delete a lobby (cascades to players and game_state).""" | |
| self.table.delete().eq("id", lobby_id).execute() | |