from __future__ import annotations from fastapi import APIRouter, HTTPException from web.api import db router = APIRouter() @router.get("/api/tss/player/{uid}") async def player(uid: str) -> dict: bp = db.battles_path() summary = await db.query_one(bp, """ SELECT COUNT(*) battles, SUM(CASE WHEN victor_bool='Win' THEN 1 ELSE 0 END) wins, SUM(CASE WHEN victor_bool!='Win' THEN 1 ELSE 0 END) losses, SUM(ground_kills) ground_kills, SUM(air_kills) air_kills, SUM(assists) assists, SUM(captures) captures, SUM(deaths) deaths, SUM(score) score, AVG(pvp_ratio) avg_pvp_ratio FROM player_games_hist WHERE UID = ?""", (uid,)) if not summary or summary["battles"] == 0: raise HTTPException(status_code=404, detail=f"player {uid} not found") vehicles = await db.query(bp, """ SELECT vehicle, vehicle_internal, COUNT(*) battles, SUM(air_kills+ground_kills) kills, SUM(deaths) deaths, SUM(score) score FROM player_games_hist WHERE UID = ? GROUP BY vehicle_internal ORDER BY battles DESC""", (uid,)) nicks = await db.query(bp, """ SELECT nick, MIN(endtime_unix) first_seen, MAX(endtime_unix) last_seen FROM player_games_hist WHERE UID = ? GROUP BY nick ORDER BY last_seen DESC""", (uid,)) team_history = await db.query(bp, """ SELECT team_id, team_name, tss_role, COUNT(*) battles, MIN(endtime_unix) first_seen, MAX(endtime_unix) last_seen FROM player_games_hist WHERE UID = ? GROUP BY team_id, team_name, tss_role ORDER BY last_seen DESC""", (uid,)) win_rate = round(summary["wins"] / summary["battles"], 4) if summary["battles"] else 0.0 return {"uid": str(uid), "summary": {**summary, "win_rate": win_rate}, "vehicles": vehicles, "nicks": nicks, "team_history": team_history} @router.get("/api/tss/player/{uid}/games") async def player_games(uid: str, limit: int = 100, time_from: int | None = None, time_to: int | None = None) -> dict: clauses = ["p.UID = ?"] params: list = [uid] if time_from is not None: clauses.append("p.endtime_unix >= ?"); params.append(time_from) if time_to is not None: clauses.append("p.endtime_unix <= ?"); params.append(time_to) params.append(max(1, min(limit, 1000))) rows = await db.query(db.battles_path(), f""" SELECT p.*, m.mission_name, m.tournament_name FROM player_games_hist p LEFT JOIN match_summary m ON m.session_id = p.session_id WHERE {' AND '.join(clauses)} ORDER BY p.endtime_unix DESC LIMIT ?""", tuple(params)) return {"uid": str(uid), "total": len(rows), "games": rows} @router.get("/api/tss/player/{uid}/history") async def player_history(uid: str) -> dict: rows = await db.query(db.battles_path(), """ SELECT date(endtime_unix, 'unixepoch') day, COUNT(*) battles, SUM(CASE WHEN victor_bool='Win' THEN 1 ELSE 0 END) wins, SUM(air_kills+ground_kills) kills, SUM(deaths) deaths, SUM(score) score FROM player_games_hist WHERE UID = ? GROUP BY day ORDER BY day DESC""", (uid,)) return {"uid": str(uid), "days_with_battles_only": True, "history": rows} @router.get("/api/tss/search/{nick}") async def search(nick: str, limit: int = 25) -> dict: rows = await db.query(db.battles_path(), """ SELECT UID uid, nick, MAX(endtime_unix) last_seen, COUNT(*) battles FROM player_games_hist WHERE nick LIKE ? COLLATE NOCASE GROUP BY UID, nick ORDER BY last_seen DESC LIMIT ?""", (f"%{nick}%", max(1, min(limit, 100)))) for r in rows: r["uid"] = str(r["uid"]) return {"query": nick, "players": rows}