- /categories: Query categories from database instead of hardcoded list
- /today-questions: Query approved questions with date_active = today
- /question/{id}: Query specific question from database
- /board/{room_code}: Load board from database if not in Redis
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
147 lines
4.4 KiB
Python
147 lines
4.4 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(db: AsyncSession = Depends(get_db)):
|
|
"""Get all categories for the game board."""
|
|
result = await db.execute(select(Category).order_by(Category.id))
|
|
categories = result.scalars().all()
|
|
|
|
return [
|
|
{
|
|
"id": cat.id,
|
|
"name": cat.name,
|
|
"icon": cat.icon,
|
|
"color": cat.color
|
|
}
|
|
for cat in categories
|
|
]
|
|
|
|
|
|
@router.get("/board/{room_code}")
|
|
async def get_game_board(room_code: str, db: AsyncSession = Depends(get_db)):
|
|
"""
|
|
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"]
|
|
|
|
# Load today's questions from database
|
|
today = date.today()
|
|
result = await db.execute(
|
|
select(Question, Category)
|
|
.join(Category, Question.category_id == Category.id)
|
|
.where(Question.date_active == today)
|
|
.where(Question.status == "approved")
|
|
.order_by(Category.id, Question.difficulty)
|
|
)
|
|
rows = result.all()
|
|
|
|
board = {}
|
|
for question, category in rows:
|
|
cat_id = str(category.id)
|
|
if cat_id not in board:
|
|
board[cat_id] = []
|
|
board[cat_id].append({
|
|
"id": question.id,
|
|
"difficulty": question.difficulty,
|
|
"points": question.points,
|
|
"time_seconds": question.time_seconds,
|
|
"answered": False
|
|
})
|
|
|
|
return board
|
|
|
|
|
|
@router.get("/today-questions")
|
|
async def get_today_questions(db: AsyncSession = Depends(get_db)):
|
|
"""
|
|
Get all approved questions for today, grouped by category and difficulty.
|
|
This is used to build the game board.
|
|
"""
|
|
today = date.today()
|
|
|
|
# Get all approved questions for today
|
|
result = await db.execute(
|
|
select(Question, Category)
|
|
.join(Category, Question.category_id == Category.id)
|
|
.where(Question.date_active == today)
|
|
.where(Question.status == "approved")
|
|
.order_by(Category.id, Question.difficulty)
|
|
)
|
|
rows = result.all()
|
|
|
|
categories = {}
|
|
for question, category in rows:
|
|
cat_id = str(category.id)
|
|
if cat_id not in categories:
|
|
categories[cat_id] = {
|
|
"name": category.name,
|
|
"icon": category.icon,
|
|
"color": category.color,
|
|
"questions": []
|
|
}
|
|
categories[cat_id]["questions"].append({
|
|
"difficulty": question.difficulty,
|
|
"id": question.id,
|
|
"points": question.points
|
|
})
|
|
|
|
return {
|
|
"date": str(today),
|
|
"categories": categories
|
|
}
|
|
|
|
|
|
@router.get("/question/{question_id}")
|
|
async def get_question(question_id: int, db: AsyncSession = Depends(get_db)):
|
|
"""
|
|
Get a specific question (without the answer).
|
|
Used when a player selects a question.
|
|
"""
|
|
result = await db.execute(
|
|
select(Question).where(Question.id == question_id)
|
|
)
|
|
question = result.scalar_one_or_none()
|
|
|
|
if not question:
|
|
raise HTTPException(status_code=404, detail="Question not found")
|
|
|
|
return {
|
|
"id": question.id,
|
|
"question_text": question.question_text,
|
|
"difficulty": question.difficulty,
|
|
"points": question.points,
|
|
"time_seconds": question.time_seconds,
|
|
"category_id": question.category_id,
|
|
"fun_fact": question.fun_fact
|
|
}
|
|
|
|
|
|
@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
|