Add stats screen with backend endpoint and frontend page

Implements a dedicated /stats page showing cross-run aggregate statistics:
run overview with win rate, runs by game bar chart, encounter breakdowns,
top caught/encountered pokemon rankings, mortality analysis with death
causes, and type distribution. Backend endpoint uses aggregate SQL queries
to avoid N+1 fetching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 20:46:36 +01:00
parent 78d31f2856
commit fb90410055
12 changed files with 700 additions and 13 deletions

View File

@@ -0,0 +1,58 @@
from app.schemas.base import CamelModel
class GameRunCount(CamelModel):
game_id: int
game_name: str
game_color: str | None
count: int
class PokemonRanking(CamelModel):
pokemon_id: int
name: str
sprite_url: str | None
count: int
class DeathCause(CamelModel):
cause: str
count: int
class TypeCount(CamelModel):
type: str
count: int
class StatsResponse(CamelModel):
# Run overview
total_runs: int
active_runs: int
completed_runs: int
failed_runs: int
win_rate: float | None
avg_duration_days: float | None
# Runs by game
runs_by_game: list[GameRunCount]
# Encounter stats
total_encounters: int
caught_count: int
fainted_count: int
missed_count: int
catch_rate: float | None
avg_encounters_per_run: float | None
# Pokemon rankings
top_caught_pokemon: list[PokemonRanking]
top_encountered_pokemon: list[PokemonRanking]
# Team & deaths
total_deaths: int
mortality_rate: float | None
top_death_causes: list[DeathCause]
avg_catch_level: float | None
avg_faint_level: float | None
type_distribution: list[TypeCount]