Files
servesync-demo/backend/app/api/screen.py

164 lines
5.6 KiB
Python

"""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(),
}