deckhearth/backend/app/routers/decks.py

228 lines
No EOL
5.8 KiB
Python

"""
Deck management routes
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from pydantic import BaseModel
from typing import List, Optional
from app.database import get_db
from app.models.deck import Deck, DeckCard
from app.models.card import Card
from app.models.user import User
from app.routers.auth import get_current_user
router = APIRouter()
# Pydantic models
class DeckResponse(BaseModel):
id: int
name: str
description: Optional[str]
format: Optional[str]
game: str
is_public: bool
is_complete: bool
is_favorite: bool
total_cards: int
avg_mana_cost: Optional[float]
estimated_value: Optional[float]
commander_card_id: Optional[int]
class Config:
from_attributes = True
class DeckCreate(BaseModel):
name: str
game: str
description: Optional[str] = None
format: Optional[str] = None
is_public: bool = False
commander_card_id: Optional[int] = None
class DeckCardResponse(BaseModel):
id: int
card_id: int
card_name: str
quantity: int
is_sideboard: bool
is_commander: bool
category: Optional[str]
notes: Optional[str]
owned: bool
need_to_acquire: bool
class Config:
from_attributes = True
class DeckCardCreate(BaseModel):
card_id: int
quantity: int = 1
is_sideboard: bool = False
is_commander: bool = False
category: Optional[str] = None
notes: Optional[str] = None
# Routes
@router.get("/", response_model=List[DeckResponse])
async def get_my_decks(
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get current user's decks"""
decks = db.query(Deck).filter(Deck.owner_id == current_user.id).all()
return decks
@router.get("/{deck_id}", response_model=DeckResponse)
async def get_deck(
deck_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get a specific deck"""
deck = db.query(Deck).filter(
Deck.id == deck_id,
Deck.owner_id == current_user.id
).first()
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")
return deck
@router.post("/", response_model=DeckResponse)
async def create_deck(
deck_data: DeckCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Create a new deck"""
new_deck = Deck(
**deck_data.dict(),
owner_id=current_user.id
)
db.add(new_deck)
db.commit()
db.refresh(new_deck)
return new_deck
@router.get("/{deck_id}/cards", response_model=List[DeckCardResponse])
async def get_deck_cards(
deck_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Get all cards in a deck"""
# Verify deck ownership
deck = db.query(Deck).filter(
Deck.id == deck_id,
Deck.owner_id == current_user.id
).first()
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")
# Get deck cards with card names
cards = db.query(DeckCard, Card.name.label('card_name')).join(
Card, DeckCard.card_id == Card.id
).filter(DeckCard.deck_id == deck_id).all()
result = []
for dc, card_name in cards:
dc_dict = dc.__dict__.copy()
dc_dict['card_name'] = card_name
result.append(DeckCardResponse(**dc_dict))
return result
@router.post("/{deck_id}/cards", response_model=DeckCardResponse)
async def add_card_to_deck(
deck_id: int,
card_data: DeckCardCreate,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Add a card to a deck"""
# Verify deck ownership
deck = db.query(Deck).filter(
Deck.id == deck_id,
Deck.owner_id == current_user.id
).first()
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")
# Verify card exists
card = db.query(Card).filter(Card.id == card_data.card_id).first()
if not card:
raise HTTPException(status_code=404, detail="Card not found")
# Check if card already exists in deck (same sideboard status)
existing_card = db.query(DeckCard).filter(
DeckCard.deck_id == deck_id,
DeckCard.card_id == card_data.card_id,
DeckCard.is_sideboard == card_data.is_sideboard
).first()
if existing_card:
# Update quantity if card already exists
existing_card.quantity += card_data.quantity
db.commit()
db.refresh(existing_card)
# Add card name for response
existing_card_dict = existing_card.__dict__.copy()
existing_card_dict['card_name'] = card.name
return DeckCardResponse(**existing_card_dict)
else:
# Create new deck card entry
new_deck_card = DeckCard(
deck_id=deck_id,
**card_data.dict()
)
db.add(new_deck_card)
db.commit()
db.refresh(new_deck_card)
# Recalculate deck stats
deck.calculate_stats()
db.commit()
# Add card name for response
new_card_dict = new_deck_card.__dict__.copy()
new_card_dict['card_name'] = card.name
return DeckCardResponse(**new_card_dict)
@router.put("/{deck_id}/calculate-stats")
async def calculate_deck_stats(
deck_id: int,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Recalculate deck statistics"""
deck = db.query(Deck).filter(
Deck.id == deck_id,
Deck.owner_id == current_user.id
).first()
if not deck:
raise HTTPException(status_code=404, detail="Deck not found")
deck.calculate_stats()
db.commit()
return {"message": "Deck statistics updated"}