Add game category and region metadata for genlocke presets

Add `category` field (original/remake/enhanced/sequel/spinoff) to the
Game model and tag all 38 games. Create regions.json with generation
mapping, ordering, and genlocke preset defaults per region. Add
GET /games/by-region endpoint returning games grouped by region.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Julian Tabel
2026-02-09 09:06:15 +01:00
parent dab0cf986f
commit aaaeb2146e
9 changed files with 237 additions and 9 deletions

View File

@@ -1,3 +1,6 @@
import json
from pathlib import Path
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import delete, select
from sqlalchemy.ext.asyncio import AsyncSession
@@ -14,6 +17,7 @@ from app.schemas.game import (
GameDetailResponse,
GameResponse,
GameUpdate,
RegionResponse,
RouteCreate,
RouteReorderRequest,
RouteResponse,
@@ -46,6 +50,38 @@ async def list_games(session: AsyncSession = Depends(get_session)):
return result.scalars().all()
@router.get("/by-region", response_model=list[RegionResponse])
async def list_games_by_region(session: AsyncSession = Depends(get_session)):
"""Return games grouped by region with generation metadata and genlocke preset defaults."""
regions_path = Path(__file__).parent.parent / "seeds" / "data" / "regions.json"
with open(regions_path) as f:
regions_data = json.load(f)
result = await session.execute(select(Game).order_by(Game.release_year, Game.name))
all_games = result.scalars().all()
games_by_region: dict[str, list[Game]] = {}
for game in all_games:
games_by_region.setdefault(game.region, []).append(game)
response = []
for region in regions_data:
region_games = games_by_region.get(region["name"], [])
defaults = region["genlocke_defaults"]
response.append({
"name": region["name"],
"generation": region["generation"],
"order": region["order"],
"genlocke_defaults": {
"true_genlocke": defaults["true"],
"normal_genlocke": defaults["normal"],
},
"games": region_games,
})
return response
@router.get("/{game_id}", response_model=GameDetailResponse)
async def get_game(game_id: int, session: AsyncSession = Depends(get_session)):
game = await _get_game_or_404(session, game_id)
@@ -66,6 +102,7 @@ async def get_game(game_id: int, session: AsyncSession = Depends(get_session)):
"slug": game.slug,
"generation": game.generation,
"region": game.region,
"category": game.category,
"box_art_url": game.box_art_url,
"release_year": game.release_year,
"color": game.color,