import asyncio from typing import Optional, Dict, Callable, Awaitable from datetime import datetime, timedelta from app.config import get_settings settings = get_settings() class TimerManager: def __init__(self): self.active_timers: Dict[str, asyncio.Task] = {} # room_code -> task self.timer_end_times: Dict[str, datetime] = {} # room_code -> end_time async def start_timer( self, room_code: str, seconds: int, on_expire: Callable[[str], Awaitable[None]], is_steal: bool = False ) -> datetime: """ Inicia un timer para una sala. Args: room_code: Codigo de la sala seconds: Segundos base (se reduce si is_steal) on_expire: Callback async cuando expire el timer is_steal: Si es intento de robo (tiempo reducido) Returns: datetime cuando expira el timer """ # Cancelar timer anterior si existe await self.cancel_timer(room_code) # Calcular tiempo real if is_steal: seconds = int(seconds * settings.steal_time_multiplier) end_time = datetime.utcnow() + timedelta(seconds=seconds) self.timer_end_times[room_code] = end_time # Crear task async def timer_task(): try: await asyncio.sleep(seconds) # Timer expiro if room_code in self.active_timers: del self.active_timers[room_code] del self.timer_end_times[room_code] await on_expire(room_code) except asyncio.CancelledError: # Timer fue cancelado (respuesta recibida a tiempo) pass self.active_timers[room_code] = asyncio.create_task(timer_task()) return end_time async def cancel_timer(self, room_code: str) -> bool: """Cancela el timer de una sala.""" if room_code in self.active_timers: self.active_timers[room_code].cancel() try: await self.active_timers[room_code] except asyncio.CancelledError: pass del self.active_timers[room_code] if room_code in self.timer_end_times: del self.timer_end_times[room_code] return True return False def get_remaining_time(self, room_code: str) -> Optional[float]: """Obtiene segundos restantes del timer.""" if room_code in self.timer_end_times: remaining = (self.timer_end_times[room_code] - datetime.utcnow()).total_seconds() return max(0, remaining) return None def is_timer_active(self, room_code: str) -> bool: """Verifica si hay un timer activo para la sala.""" return room_code in self.active_timers # Singleton timer_manager = TimerManager()