Files
Trivy/backend/app/api/game.py
consultoria-as 27ac4cb0cf feat(phase2): Add achievements and replay systems
Achievement System:
- Add Achievement model with condition types (streak, steal, specialist, etc.)
- Add AchievementManager service for tracking and awarding achievements
- Add Pydantic schemas for achievements (AchievementResponse, PlayerStats, etc.)
- Seed 18 achievements from design doc
- Add GET /api/game/achievements endpoint

Replay System:
- Add ReplayManager service for saving/loading game replays
- Add GET /api/replay/{code} and /api/replay/session/{id} endpoints
- Format replays for frontend consumption

Phase 2 tasks completed:
- F2.1: Achievement model and migration
- F2.2: Pydantic schemas
- F2.3: AchievementManager service
- F2.4: ReplayManager service
- F2.5: API endpoints
- F2.6: Seed 18 achievements data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 08:24:02 +00:00

104 lines
3.5 KiB
Python

from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from datetime import date
from typing import Dict, List
from app.models.base import get_db
from app.models.question import Question
from app.models.category import Category
from app.schemas.game import RoomCreate, RoomJoin, GameState
from app.services.achievement_manager import achievement_manager
from app.schemas.achievement import AchievementResponse
router = APIRouter()
@router.get("/categories")
async def get_game_categories():
"""Get all categories for the game board."""
# Return hardcoded categories for now
# In production, these would come from the database
return [
{"id": 1, "name": "Nintendo", "icon": "🍄", "color": "#E60012"},
{"id": 2, "name": "Xbox", "icon": "🎮", "color": "#107C10"},
{"id": 3, "name": "PlayStation", "icon": "🎯", "color": "#003791"},
{"id": 4, "name": "Anime", "icon": "⛩️", "color": "#FF6B9D"},
{"id": 5, "name": "Música", "icon": "🎵", "color": "#1DB954"},
{"id": 6, "name": "Películas", "icon": "🎬", "color": "#F5C518"},
{"id": 7, "name": "Libros", "icon": "📚", "color": "#8B4513"},
{"id": 8, "name": "Historia-Cultura", "icon": "🏛️", "color": "#6B5B95"},
]
@router.get("/board/{room_code}")
async def get_game_board(room_code: str):
"""
Get the game board with questions for today.
Returns questions grouped by category.
"""
from app.services.room_manager import room_manager
room = await room_manager.get_room(room_code)
if not room:
raise HTTPException(status_code=404, detail="Room not found")
# If board already exists in room, return it
if room.get("board"):
return room["board"]
# Otherwise, this would load from database
# For now, return empty board structure
return {}
@router.get("/today-questions")
async def get_today_questions():
"""
Get all approved questions for today, grouped by category and difficulty.
This is used to build the game board.
"""
# This would query the database for questions with date_active = today
# For now, return sample structure
return {
"date": str(date.today()),
"categories": {
"1": { # Nintendo
"name": "Nintendo",
"questions": [
{"difficulty": 1, "id": 1, "points": 100},
{"difficulty": 2, "id": 2, "points": 200},
{"difficulty": 3, "id": 3, "points": 300},
{"difficulty": 4, "id": 4, "points": 400},
{"difficulty": 5, "id": 5, "points": 500},
]
}
# ... other categories
}
}
@router.get("/question/{question_id}")
async def get_question(question_id: int):
"""
Get a specific question (without the answer).
Used when a player selects a question.
"""
# This would query the database
# For now, return sample
return {
"id": question_id,
"question_text": "¿En qué año se lanzó la primera consola Nintendo Entertainment System (NES) en Japón?",
"difficulty": 3,
"points": 300,
"time_seconds": 25,
"category_id": 1
}
@router.get("/achievements", response_model=list[AchievementResponse])
async def get_achievements(db: AsyncSession = Depends(get_db)):
"""Obtiene lista de todos los logros disponibles"""
achievements = await achievement_manager.get_all_achievements(db)
return achievements