edh-elo/app/routers/stats.py

64 lines
2.1 KiB
Python

from collections import defaultdict
from typing import Optional
from fastapi import APIRouter, Depends, Request
from fastapi.responses import HTMLResponse
from sqlalchemy.sql.expression import func
from app.sql import models
from ..templates import jinja_templates
from ..sql.database import get_db
api_router = APIRouter(prefix="/stats", tags=["stats"])
html_router = APIRouter(
prefix="/stats", include_in_schema=False, default_response_class=HTMLResponse
)
@api_router.get("/graph")
def stats_graph_api(deck_ids: Optional[str] = None, db=Depends(get_db)):
# TODO - parallelize? (Probably not worth it :P )
# SO Answer on row_number: https://stackoverflow.com/a/38160409/1040915
# Docs: https://docs.sqlalchemy.org/en/20/core/sqlelement.html#sqlalchemy.sql.expression.over
row_number_column = (
func.row_number()
.over(
partition_by=[models.Deck.name, models.Game.date],
order_by=models.EloScore.id.desc(),
)
.label("row_number")
)
sub_query = (
db.query(models.Deck.name, models.EloScore.score, models.Game.date)
.outerjoin(models.EloScore, models.Deck.id == models.EloScore.deck_id)
.join(models.Game, models.EloScore.after_game_id == models.Game.id)
.add_column(row_number_column)
)
if deck_ids is not None:
sub_query = sub_query.filter(models.Deck.id.in_(deck_ids.split(",")))
sub_query = sub_query.subquery()
query = db.query(sub_query).filter(sub_query.c.row_number == 1)
results = query.all()
data_grouped_by_deck = defaultdict(list)
for result in results:
# TODO - how to index results by name instead of tuple-number
data_grouped_by_deck[result[0]].append(
{"score": result[1], "date": result[2].strftime("%Y-%m-%d")}
)
return {
"datasets": [
{"label": key, "data": data_grouped_by_deck[key]}
for key in data_grouped_by_deck
]
}
@html_router.get("/graph")
def stats_graph(request: Request, db=Depends(get_db)):
return jinja_templates.TemplateResponse(request, "stats/graph.html")