143 lines
4.4 KiB
Python
143 lines
4.4 KiB
Python
from fastapi import FastAPI, WebSocket, WebSocketDisconnect
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.responses import JSONResponse
|
|
import asyncio
|
|
import json
|
|
from typing import List, Dict
|
|
|
|
from app.database import engine, SessionLocal
|
|
from app.models import player, court, booking, match, tournament
|
|
|
|
# Create all tables
|
|
player.Base.metadata.create_all(bind=engine)
|
|
court.Base.metadata.create_all(bind=engine)
|
|
booking.Base.metadata.create_all(bind=engine)
|
|
match.Base.metadata.create_all(bind=engine)
|
|
tournament.Base.metadata.create_all(bind=engine)
|
|
|
|
from app.api import players, courts, matches, tournaments, screen, admin
|
|
|
|
app = FastAPI(
|
|
title="ServeSync API",
|
|
description="Pickleball Court Management System",
|
|
version="1.0.0",
|
|
)
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Include routers
|
|
app.include_router(players.router, prefix="/api")
|
|
app.include_router(courts.router, prefix="/api")
|
|
app.include_router(matches.router, prefix="/api")
|
|
app.include_router(tournaments.router, prefix="/api")
|
|
app.include_router(screen.router, prefix="/api")
|
|
app.include_router(admin.router, prefix="/api")
|
|
|
|
|
|
# WebSocket connection manager
|
|
class ConnectionManager:
|
|
def __init__(self):
|
|
self.active_connections: Dict[str, List[WebSocket]] = {}
|
|
|
|
async def connect(self, websocket: WebSocket, channel: str):
|
|
await websocket.accept()
|
|
if channel not in self.active_connections:
|
|
self.active_connections[channel] = []
|
|
self.active_connections[channel].append(websocket)
|
|
|
|
def disconnect(self, websocket: WebSocket, channel: str):
|
|
if channel in self.active_connections:
|
|
self.active_connections[channel].remove(websocket)
|
|
|
|
async def broadcast(self, channel: str, data: dict):
|
|
if channel in self.active_connections:
|
|
disconnected = []
|
|
for connection in self.active_connections[channel]:
|
|
try:
|
|
await connection.send_text(json.dumps(data))
|
|
except Exception:
|
|
disconnected.append(connection)
|
|
for conn in disconnected:
|
|
self.active_connections[channel].remove(conn)
|
|
|
|
|
|
manager = ConnectionManager()
|
|
|
|
|
|
@app.websocket("/ws/court/{court_id}")
|
|
async def websocket_court(websocket: WebSocket, court_id: int):
|
|
"""WebSocket for real-time court display updates"""
|
|
channel = f"court_{court_id}"
|
|
await manager.connect(websocket, channel)
|
|
try:
|
|
while True:
|
|
# Send court data every 3 seconds
|
|
db = SessionLocal()
|
|
try:
|
|
from app.api.screen import get_court_display
|
|
data = get_court_display(court_id, db)
|
|
await websocket.send_text(json.dumps(data))
|
|
finally:
|
|
db.close()
|
|
await asyncio.sleep(3)
|
|
except WebSocketDisconnect:
|
|
manager.disconnect(websocket, channel)
|
|
|
|
|
|
@app.websocket("/ws/overview")
|
|
async def websocket_overview(websocket: WebSocket):
|
|
"""WebSocket for real-time overview display"""
|
|
channel = "overview"
|
|
await manager.connect(websocket, channel)
|
|
try:
|
|
while True:
|
|
db = SessionLocal()
|
|
try:
|
|
from app.api.screen import get_overview
|
|
data = get_overview(db)
|
|
await websocket.send_text(json.dumps(data))
|
|
finally:
|
|
db.close()
|
|
await asyncio.sleep(3)
|
|
except WebSocketDisconnect:
|
|
manager.disconnect(websocket, channel)
|
|
|
|
|
|
@app.websocket("/ws/matches")
|
|
async def websocket_matches(websocket: WebSocket):
|
|
"""WebSocket for real-time match lobby updates"""
|
|
channel = "matches"
|
|
await manager.connect(websocket, channel)
|
|
try:
|
|
while True:
|
|
db = SessionLocal()
|
|
try:
|
|
from app.api.matches import get_lobby
|
|
from app.api.matches import get_active_matches
|
|
data = {
|
|
"lobby": get_lobby(db),
|
|
"active": get_active_matches(db),
|
|
}
|
|
await websocket.send_text(json.dumps(data))
|
|
finally:
|
|
db.close()
|
|
await asyncio.sleep(2)
|
|
except WebSocketDisconnect:
|
|
manager.disconnect(websocket, channel)
|
|
|
|
|
|
@app.get("/")
|
|
def root():
|
|
return {"message": "ServeSync API v1.0", "status": "running"}
|
|
|
|
|
|
@app.get("/health")
|
|
def health():
|
|
return {"status": "healthy"}
|