Files
cluedo-hp-webapp/backend/app/routes/games.py
2026-02-03 08:22:21 +01:00

98 lines
3.3 KiB
Python

import hashlib, random
from fastapi import APIRouter, Depends, HTTPException, Request
from sqlalchemy.orm import Session
from ..db import get_db
from ..models import Game, Entry, SheetState, Category
from ..security import get_session_user_id
router = APIRouter(prefix="/games", tags=["games"])
def require_user(req: Request, db: Session):
uid = get_session_user_id(req)
if not uid:
raise HTTPException(status_code=401, detail="not logged in")
return uid
def stable_order(seed: int, user_id: str, entry_id: str) -> str:
s = f"{seed}:{user_id}:{entry_id}".encode()
return hashlib.sha256(s).hexdigest()
@router.post("")
def create_game(req: Request, data: dict, db: Session = Depends(get_db)):
uid = require_user(req, db)
name = data.get("name") or "Neues Spiel"
seed = random.randint(1, 2_000_000_000)
g = Game(owner_user_id=uid, name=name, seed=seed)
db.add(g); db.commit()
return {"id": g.id, "name": g.name}
@router.get("")
def list_games(req: Request, db: Session = Depends(get_db)):
uid = require_user(req, db)
games = db.query(Game).filter(Game.owner_user_id == uid).order_by(Game.created_at.desc()).all()
return [{"id": g.id, "name": g.name, "seed": g.seed} for g in games]
@router.get("/{game_id}/sheet")
def get_sheet(req: Request, game_id: str, db: Session = Depends(get_db)):
uid = require_user(req, db)
g = db.query(Game).filter(Game.id == game_id, Game.owner_user_id == uid).first()
if not g:
raise HTTPException(404, "game not found")
entries = db.query(Entry).all()
states = db.query(SheetState).filter(SheetState.game_id == g.id, SheetState.owner_user_id == uid).all()
state_map = {st.entry_id: st for st in states}
out = {"suspect": [], "item": [], "location": []}
for e in entries:
st = state_map.get(e.id)
item = {
"entry_id": e.id,
"label": e.label,
"status": st.status if st else 0,
"note_tag": st.note_tag if st else None,
"order": stable_order(g.seed, uid, e.id),
}
out[e.category].append(item)
# sort within category
for k in out:
out[k].sort(key=lambda x: x["order"])
for i in out[k]:
del i["order"]
return out
@router.patch("/{game_id}/sheet/{entry_id}")
def patch_sheet(req: Request, game_id: str, entry_id: str, data: dict, db: Session = Depends(get_db)):
uid = require_user(req, db)
g = db.query(Game).filter(Game.id == game_id, Game.owner_user_id == uid).first()
if not g:
raise HTTPException(404, "game not found")
status = data.get("status")
note_tag = data.get("note_tag")
if note_tag not in (None, "i", "m", "s"):
raise HTTPException(400, "invalid note_tag")
if status is not None and status not in (0, 1, 2):
raise HTTPException(400, "invalid status")
st = db.query(SheetState).filter(
SheetState.game_id == g.id,
SheetState.owner_user_id == uid,
SheetState.entry_id == entry_id
).first()
if not st:
st = SheetState(game_id=g.id, owner_user_id=uid, entry_id=entry_id, status=0, note_tag=None)
db.add(st)
if status is not None:
st.status = status
if "note_tag" in data:
st.note_tag = note_tag
db.commit()
return {"ok": True}