147 lines
5.1 KiB
Python
147 lines
5.1 KiB
Python
"""Routes API — Base de données HSBG (héros, serviteurs, sorts)."""
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from pydantic import BaseModel
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, delete
|
|
from backend.database.db import get_db
|
|
from backend.database.models import Hero, Minion, Spell
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
# ─── Héros ────────────────────────────────────────────────────────────────────
|
|
|
|
@router.get("/heroes")
|
|
async def list_heroes(search: str | None = None, db: AsyncSession = Depends(get_db)):
|
|
q = select(Hero).where(Hero.is_active == True)
|
|
if search:
|
|
q = q.where(Hero.name.ilike(f"%{search}%"))
|
|
r = await db.execute(q)
|
|
return [
|
|
{"id": h.id, "card_id": h.card_id, "name": h.name, "hero_power": h.hero_power,
|
|
"description": h.description, "strengths": h.strengths, "weaknesses": h.weaknesses,
|
|
"synergies": h.synergies, "tier_rating": h.tier_rating, "patch_added": h.patch_added}
|
|
for h in r.scalars().all()
|
|
]
|
|
|
|
|
|
class HeroIn(BaseModel):
|
|
card_id: str
|
|
name: str
|
|
hero_power: str = ""
|
|
description: str = ""
|
|
strengths: list = []
|
|
weaknesses: list = []
|
|
synergies: list = []
|
|
tier_rating: float = 5.0
|
|
patch_added: str = ""
|
|
|
|
|
|
@router.post("/heroes", status_code=201)
|
|
async def create_hero(data: HeroIn, db: AsyncSession = Depends(get_db)):
|
|
hero = Hero(**data.model_dump())
|
|
db.add(hero)
|
|
await db.flush()
|
|
return {"id": hero.id, "name": hero.name}
|
|
|
|
|
|
@router.put("/heroes/{hero_id}")
|
|
async def update_hero(hero_id: int, data: HeroIn, db: AsyncSession = Depends(get_db)):
|
|
hero = await db.get(Hero, hero_id)
|
|
if not hero:
|
|
raise HTTPException(404, "Héros introuvable")
|
|
for k, v in data.model_dump().items():
|
|
setattr(hero, k, v)
|
|
return {"id": hero.id, "name": hero.name}
|
|
|
|
|
|
@router.delete("/heroes/{hero_id}")
|
|
async def delete_hero(hero_id: int, db: AsyncSession = Depends(get_db)):
|
|
hero = await db.get(Hero, hero_id)
|
|
if not hero:
|
|
raise HTTPException(404, "Héros introuvable")
|
|
hero.is_active = False
|
|
return {"status": "deactivated"}
|
|
|
|
|
|
# ─── Serviteurs ───────────────────────────────────────────────────────────────
|
|
|
|
@router.get("/minions")
|
|
async def list_minions(
|
|
tier: int | None = None,
|
|
race: str | None = None,
|
|
search: str | None = None,
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
q = select(Minion).where(Minion.is_active == True)
|
|
if tier:
|
|
q = q.where(Minion.tier == str(tier))
|
|
if search:
|
|
q = q.where(Minion.name.ilike(f"%{search}%"))
|
|
r = await db.execute(q)
|
|
minions = r.scalars().all()
|
|
if race:
|
|
minions = [m for m in minions if race in (m.race or [])]
|
|
return [
|
|
{"id": m.id, "card_id": m.card_id, "name": m.name, "tier": m.tier,
|
|
"race": m.race, "attack": m.attack, "health": m.health,
|
|
"has_divine": m.has_divine, "has_taunt": m.has_taunt,
|
|
"has_windfury": m.has_windfury, "has_poisonous": m.has_poisonous,
|
|
"has_reborn": m.has_reborn, "battlecry": m.battlecry,
|
|
"deathrattle": m.deathrattle, "passive": m.passive,
|
|
"synergies": m.synergies, "keywords": m.keywords, "patch_added": m.patch_added}
|
|
for m in minions
|
|
]
|
|
|
|
|
|
class MinionIn(BaseModel):
|
|
card_id: str
|
|
name: str
|
|
tier: str = "1"
|
|
race: list = []
|
|
attack: int = 0
|
|
health: int = 0
|
|
tavern_cost: int = 3
|
|
has_divine: bool = False
|
|
has_taunt: bool = False
|
|
has_windfury: bool = False
|
|
has_poisonous: bool = False
|
|
has_reborn: bool = False
|
|
battlecry: str = ""
|
|
deathrattle: str = ""
|
|
on_attack: str = ""
|
|
passive: str = ""
|
|
synergies: list = []
|
|
keywords: list = []
|
|
patch_added: str = ""
|
|
|
|
|
|
@router.post("/minions", status_code=201)
|
|
async def create_minion(data: MinionIn, db: AsyncSession = Depends(get_db)):
|
|
minion = Minion(**data.model_dump())
|
|
db.add(minion)
|
|
await db.flush()
|
|
return {"id": minion.id, "name": minion.name}
|
|
|
|
|
|
@router.put("/minions/{minion_id}")
|
|
async def update_minion(minion_id: int, data: MinionIn, db: AsyncSession = Depends(get_db)):
|
|
minion = await db.get(Minion, minion_id)
|
|
if not minion:
|
|
raise HTTPException(404, "Serviteur introuvable")
|
|
for k, v in data.model_dump().items():
|
|
setattr(minion, k, v)
|
|
return {"id": minion.id, "name": minion.name}
|
|
|
|
|
|
# ─── Sorts ────────────────────────────────────────────────────────────────────
|
|
|
|
@router.get("/spells")
|
|
async def list_spells(db: AsyncSession = Depends(get_db)):
|
|
r = await db.execute(select(Spell).where(Spell.is_active == True))
|
|
return [
|
|
{"id": s.id, "card_id": s.card_id, "name": s.name, "tier": s.tier,
|
|
"cost": s.cost, "effect": s.effect, "target": s.target}
|
|
for s in r.scalars().all()
|
|
]
|