"""Screen Display API - for TV/display views""" from fastapi import APIRouter, Depends from sqlalchemy.orm import Session from sqlalchemy import desc from app.database import get_db from app.models.court import Court from app.models.match import Match, MatchPlayer, MatchStatus from app.models.player import Player from app.models.tournament import Tournament, TournamentStatus from app.services.tournament import get_bracket_data from datetime import datetime, timezone router = APIRouter(prefix="/screen", tags=["screen"]) @router.get("/court/{court_id}") def get_court_display(court_id: int, db: Session = Depends(get_db)): """Full court display data for TV screen (court_id = court_number)""" # Try by court_number first (friendlier URLs), then by id court = db.query(Court).filter(Court.court_number == court_id).first() if not court: court = db.query(Court).filter(Court.id == court_id).first() if not court: return {"error": "Court not found"} # Current active match active_match = db.query(Match).filter( Match.court_id == court_id, Match.status == MatchStatus.IN_PROGRESS ).first() match_data = None if active_match: team1_players = [] team2_players = [] for mp in active_match.match_players: p = db.query(Player).filter(Player.id == mp.player_id).first() if p: pd = { "id": p.id, "name": p.name, "elo": round(p.elo_rating, 1), "avatar_color": p.avatar_color, "membership_tier": p.membership_tier.value, } if mp.team == 1: team1_players.append(pd) else: team2_players.append(pd) elapsed = None if active_match.started_at: now = datetime.now(timezone.utc) started = active_match.started_at if started.tzinfo is None: started = started.replace(tzinfo=timezone.utc) elapsed = int((now - started).total_seconds()) match_data = { "id": active_match.id, "stage": active_match.stage.value, "match_type": active_match.match_type.value, "team1": team1_players, "team2": team2_players, "team1_score": active_match.team1_score, "team2_score": active_match.team2_score, "elapsed_seconds": elapsed, } # Recent completed matches on this court recent_matches = db.query(Match).filter( Match.court_id == court_id, Match.status == MatchStatus.COMPLETED ).order_by(desc(Match.ended_at)).limit(3).all() recent = [] for m in recent_matches: team1 = [db.query(Player).filter(Player.id == mp.player_id).first().name for mp in m.match_players if mp.team == 1] team2 = [db.query(Player).filter(Player.id == mp.player_id).first().name for mp in m.match_players if mp.team == 2] recent.append({ "team1": team1, "team2": team2, "team1_score": m.team1_score, "team2_score": m.team2_score, "winner": "team1" if m.team1_score > m.team2_score else "team2", }) return { "court": { "id": court.id, "name": court.name, "court_number": court.court_number, "surface_type": court.surface_type, }, "active_match": match_data, "recent_matches": recent, "timestamp": datetime.now(timezone.utc).isoformat(), } @router.get("/overview") def get_overview(db: Session = Depends(get_db)): """All courts overview for main display""" courts = db.query(Court).filter(Court.is_active == True).order_by(Court.court_number).all() result = [] for court in courts: active_match = db.query(Match).filter( Match.court_id == court.id, Match.status == MatchStatus.IN_PROGRESS ).first() court_data = { "id": court.id, "name": court.name, "court_number": court.court_number, "status": "occupied" if active_match else "available", } if active_match: team1 = [mp.player.name for mp in active_match.match_players if mp.team == 1] team2 = [mp.player.name for mp in active_match.match_players if mp.team == 2] court_data["match"] = { "team1_names": team1, "team2_names": team2, "team1_score": active_match.team1_score, "team2_score": active_match.team2_score, "stage": active_match.stage.value, } result.append(court_data) # Active tournament tournament_data = None active_tournament = db.query(Tournament).filter( Tournament.status == TournamentStatus.IN_PROGRESS ).first() if active_tournament: tournament_data = get_bracket_data(db, active_tournament.id) # Leaderboard top 5 top_players = db.query(Player).filter(Player.is_active == True).order_by( Player.elo_rating.desc() ).limit(5).all() return { "courts": result, "tournament": tournament_data, "leaderboard": [ { "rank": i + 1, "name": p.name, "elo": round(p.elo_rating, 1), "tier": p.membership_tier.value, "wins": p.wins, "losses": p.losses, "avatar_color": p.avatar_color, } for i, p in enumerate(top_players) ], "timestamp": datetime.now(timezone.utc).isoformat(), }