"""Routes WebSocket — Mises à jour en temps réel.""" import asyncio import json from fastapi import APIRouter, WebSocket, WebSocketDisconnect, Request import structlog router = APIRouter() log = structlog.get_logger() _clients: list[WebSocket] = [] @router.websocket("/game") async def ws_game(websocket: WebSocket, request: Request): """WebSocket principal pour conseils en temps réel.""" await websocket.accept() _clients.append(websocket) log.info("ws.client_connected", total=len(_clients)) try: while True: raw = await websocket.receive_text() msg = json.loads(raw) msg_type = msg.get("type") if msg_type == "state_update": # L'état du jeu a changé → calculer un conseil ai = request.app.state.ai_service if ai: advice = await ai.get_advice(msg.get("state", {})) await websocket.send_json({ "type": "advice", "data": { "action": advice.main_decision.action, "reasoning": advice.main_decision.reasoning, "confidence": advice.main_decision.confidence, "warnings": advice.main_decision.warnings, "board_analysis": advice.board_analysis, "model": advice.model_used, "ms": advice.processing_ms, } }) elif msg_type == "ping": await websocket.send_json({"type": "pong", "ts": asyncio.get_event_loop().time()}) elif msg_type == "screenshot_request": # Demande de capture d'écran vis = request.app.state.vision_service if vis: state = await vis.capture_now() await websocket.send_json({ "type": "screenshot_result", "state": state, "screenshot": vis.get_screenshot_b64(), }) except WebSocketDisconnect: _clients.remove(websocket) log.info("ws.client_disconnected", total=len(_clients)) except Exception as e: log.error("ws.error", error=str(e)) if websocket in _clients: _clients.remove(websocket) async def broadcast(message: dict): """Diffuse un message à tous les clients connectés.""" disconnected = [] for client in _clients: try: await client.send_json(message) except Exception: disconnected.append(client) for c in disconnected: _clients.remove(c)