Spaces:
Sleeping
Sleeping
| """Expose authenticated server-side statistics endpoints. | |
| Probabilities and ranks are computed in Python, never by the model. | |
| """ | |
| from datetime import date, datetime, timezone | |
| from fastapi import APIRouter, Depends, Query, Request | |
| from app.deps import require_login | |
| from app.models import ApiEnvelope, ok | |
| from app.stats_math import build_stats, by_remedy | |
| router = APIRouter( | |
| prefix="/api/stats", | |
| tags=["stats"], | |
| dependencies=[Depends(require_login)], | |
| ) | |
| def _entry_dicts(request: Request) -> list[dict]: | |
| return [e.model_dump(mode="json") for e in request.app.state.entry_store._load()] | |
| def _daily_dicts( | |
| request: Request, | |
| start: date | None, | |
| end: date | None, | |
| ) -> list[dict]: | |
| rows = request.app.state.daily_store._load() | |
| out = [] | |
| for row in rows: | |
| if start and row.date < start: | |
| continue | |
| if end and row.date > end: | |
| continue | |
| out.append(row.model_dump(mode="json")) | |
| return out | |
| def _filter_entries( | |
| entries: list[dict], | |
| start: date | None, | |
| end: date | None, | |
| ) -> list[dict]: | |
| if start is None and end is None: | |
| return entries | |
| filtered = [] | |
| for entry in entries: | |
| ts = entry.get("ts") | |
| if isinstance(ts, str): | |
| day = date.fromisoformat(ts[:10]) | |
| else: | |
| continue | |
| if start and day < start: | |
| continue | |
| if end and day > end: | |
| continue | |
| filtered.append(entry) | |
| return filtered | |
| def get_stats( | |
| request: Request, | |
| start: date | None = None, | |
| end: date | None = None, | |
| min_n: int | None = Query(default=None, ge=1), | |
| ) -> dict[str, object]: | |
| """Return aggregate statistics for entries and daily rows.""" | |
| settings = request.app.state.settings | |
| effective_min_n = settings.min_stats_n if min_n is None else min_n | |
| entries = _filter_entries(_entry_dicts(request), start, end) | |
| daily = _daily_dicts(request, start, end) | |
| payload = build_stats( | |
| entries, | |
| daily, | |
| min_n=effective_min_n, | |
| shrink_k=settings.stats_shrink_k, | |
| generated_at=datetime.now(timezone.utc).isoformat(), | |
| ) | |
| return ok(payload) | |
| def get_remedy_leaderboard( | |
| request: Request, | |
| start: date | None = None, | |
| end: date | None = None, | |
| min_n: int | None = Query(default=None, ge=1), | |
| ) -> dict[str, object]: | |
| """Return remedies sorted by shrinkage rank.""" | |
| settings = request.app.state.settings | |
| effective_min_n = settings.min_stats_n if min_n is None else min_n | |
| entries = _filter_entries(_entry_dicts(request), start, end) | |
| rows = by_remedy( | |
| entries, | |
| min_n=effective_min_n, | |
| shrink_k=settings.stats_shrink_k, | |
| ) | |
| return ok({"items": rows, "min_n": effective_min_n}) | |