feat: 5 categorías rotativas por partida + pool de 200 preguntas + mejoras UI
Cambios principales: - Tablero ahora muestra 5 categorías aleatorias (de 8 disponibles) - Pool de 200 preguntas (8 cats × 5 diffs × 5 opciones) - Preguntas rotan aleatoriamente entre partidas - Diseño mejorado estilo Jeopardy con efectos visuales - Socket singleton para conexión persistente - Nuevos sonidos: game_start, player_join, question_reveal, hover, countdown - Control de volumen vertical - Barra de progreso del timer en modal de preguntas - Animaciones mejoradas con Framer Motion Backend: - question_service: selección aleatoria de 5 categorías - room_manager: fix retorno de create_room - game_events: carga board desde DB, await en enter_room Frontend: - Game.tsx: tablero dinámico, efectos hover, mejor scoreboard - useSocket: singleton service, eventos con sonidos - SoundControl: slider vertical - soundStore: 5 nuevos efectos de sonido Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
from typing import Optional, List, Dict
|
||||
from datetime import date
|
||||
from sqlalchemy import select, and_
|
||||
import random
|
||||
from sqlalchemy import select, and_, func
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.models.question import Question
|
||||
from app.models.category import Category
|
||||
|
||||
# Number of categories per game
|
||||
CATEGORIES_PER_GAME = 5
|
||||
|
||||
|
||||
class QuestionService:
|
||||
async def get_daily_questions(
|
||||
@@ -64,16 +68,49 @@ class QuestionService:
|
||||
target_date: Optional[date] = None
|
||||
) -> Dict[str, List[dict]]:
|
||||
"""
|
||||
Genera el tablero 8×5 para el juego.
|
||||
Si no hay suficientes preguntas, retorna lo disponible.
|
||||
Genera el tablero 5×5 para el juego.
|
||||
Selecciona 5 categorías aleatorias y 1 pregunta por dificultad.
|
||||
|
||||
Returns:
|
||||
Dict con category_id como string (para JSON) -> lista de preguntas
|
||||
"""
|
||||
board = await self.get_daily_questions(db, target_date)
|
||||
full_board = await self.get_daily_questions(db, target_date)
|
||||
|
||||
# Convertir keys a string para JSON
|
||||
return {str(k): v for k, v in board.items()}
|
||||
if not full_board:
|
||||
return {}
|
||||
|
||||
# Get available category IDs that have questions
|
||||
available_categories = list(full_board.keys())
|
||||
|
||||
# Select random categories (up to CATEGORIES_PER_GAME)
|
||||
num_categories = min(CATEGORIES_PER_GAME, len(available_categories))
|
||||
selected_categories = random.sample(available_categories, num_categories)
|
||||
|
||||
# Build the game board with selected categories
|
||||
game_board: Dict[str, List[dict]] = {}
|
||||
|
||||
for cat_id in selected_categories:
|
||||
questions_by_difficulty: Dict[int, List[dict]] = {}
|
||||
|
||||
# Group questions by difficulty
|
||||
for q in full_board[cat_id]:
|
||||
diff = q["difficulty"]
|
||||
if diff not in questions_by_difficulty:
|
||||
questions_by_difficulty[diff] = []
|
||||
questions_by_difficulty[diff].append(q)
|
||||
|
||||
# Select one random question per difficulty
|
||||
selected_questions = []
|
||||
for difficulty in range(1, 6): # 1-5
|
||||
if difficulty in questions_by_difficulty:
|
||||
questions = questions_by_difficulty[difficulty]
|
||||
selected_q = random.choice(questions)
|
||||
selected_questions.append(selected_q)
|
||||
|
||||
if selected_questions:
|
||||
game_board[str(cat_id)] = selected_questions
|
||||
|
||||
return game_board
|
||||
|
||||
async def get_question_by_id(
|
||||
self,
|
||||
|
||||
@@ -59,9 +59,9 @@ class RoomManager:
|
||||
)
|
||||
|
||||
# Add player to room
|
||||
await self.add_player(room_code, player_name, "A", socket_id)
|
||||
room = await self.add_player(room_code, player_name, "A", socket_id)
|
||||
|
||||
return room_state
|
||||
return room
|
||||
|
||||
async def get_room(self, room_code: str) -> Optional[dict]:
|
||||
"""Get room state by code."""
|
||||
|
||||
Reference in New Issue
Block a user