Files
Trivy/docs/plans/2026-01-26-webtriviasmulti-design.md
consultoria-as 43021b9c3c feat: Initial project structure for WebTriviasMulti
- Backend: FastAPI + Python-SocketIO + SQLAlchemy
  - Models for categories, questions, game sessions, events
  - AI services for answer validation and question generation (Claude)
  - Room management with Redis
  - Game logic with stealing mechanics
  - Admin API for question management

- Frontend: React + Vite + TypeScript + Tailwind
  - 5 visual themes (DRRR, Retro, Minimal, RGB, Anime 90s)
  - Real-time game with Socket.IO
  - Achievement system
  - Replay functionality
  - Sound effects per theme

- Docker Compose for deployment
- Design documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 07:50:48 +00:00

22 KiB
Raw Blame History

WebTriviasMulti - Documento de Diseño

Fecha: 2026-01-26 Versión: 1.0 Estado: Aprobado


1. Visión General

1.1 Descripción

WebTriviasMulti es una aplicación web de trivia multiplayer en tiempo real, inspirada en el formato de Jeopardy. Permite partidas entre 2 equipos de hasta 4 jugadores cada uno, con preguntas organizadas por categorías y niveles de dificultad.

1.2 Características Principales

  • Partidas en tiempo real con WebSockets
  • 8 categorías temáticas: Nintendo, Xbox, PlayStation, Anime, Música, Películas, Libros, Historia-Cultura
  • Tablero estilo Jeopardy (5 niveles de dificultad por categoría)
  • Sistema de "robo" de puntos entre equipos
  • Validación de respuestas mediante IA (Claude)
  • Generación automática de preguntas con aprobación de administrador
  • 5 temas visuales intercambiables
  • Sistema de logros
  • Replays de partidas
  • Sonidos temáticos

2. Mecánicas del Juego

2.1 Flujo de Partida

  1. Creación de sala: Un jugador crea sala y recibe código de 6 caracteres
  2. Lobby: Jugadores se unen con el código, eligen equipo (máx 4 por equipo), ingresan nombre
  3. Inicio: El host inicia cuando hay al menos 1 jugador por equipo
  4. Tablero: Se muestra el tablero con 8 categorías × 5 preguntas (100-500 pts)
  5. Turno: El jugador en rotación del equipo activo selecciona una pregunta
  6. Respuesta: Tiene X segundos (según dificultad) para escribir respuesta
  7. Validación IA: Claude valida si la respuesta es correcta
  8. Robo opcional: Si falla, equipo contrario decide si intenta robar
  9. Siguiente turno: El equipo ganador elige siguiente pregunta
  10. Final: Partida termina cuando se agotan las preguntas

2.2 Sistema de Turnos

  • Rotación obligatoria: Cada pregunta la responde un miembro diferente del equipo
  • El que acierta elige: El equipo que responde correctamente (o roba) elige la siguiente pregunta

2.3 Sistema de Puntos y Tiempo

Dificultad Puntos Tiempo
1 (Fácil) 100 15 seg
2 200 20 seg
3 (Media) 300 25 seg
4 400 35 seg
5 (Difícil) 500 45 seg

2.4 Mecánica de Robo

  • Voluntario: El equipo contrario decide si intenta robar o pasar
  • Penalización: Si fallan el robo, pierden la mitad de los puntos de la pregunta
  • Tiempo reducido: El equipo que roba tiene la mitad del tiempo original

2.5 Formato de Respuestas

  • Respuesta abierta (el jugador escribe libremente)
  • Validación semántica con IA (acepta sinónimos, variaciones, errores de ortografía menores)

3. Arquitectura Técnica

3.1 Stack Tecnológico

┌─────────────────────────────────────────────────────────────┐
│                      FRONTEND (React)                        │
│  - Vite + React 18 + TypeScript                             │
│  - Tailwind CSS + Framer Motion (animaciones)               │
│  - Socket.io-client (tiempo real)                           │
│  - Zustand (estado global)                                  │
│  - 5 temas visuales intercambiables                         │
└─────────────────────────────────────────────────────────────┘
                              │
                              ▼
┌─────────────────────────────────────────────────────────────┐
│                   BACKEND (Python FastAPI)                   │
│  - FastAPI + Uvicorn                                        │
│  - python-socketio (WebSockets)                             │
│  - SQLAlchemy (ORM)                                         │
│  - Anthropic SDK (validación IA)                            │
│  - APScheduler (tareas programadas)                         │
└─────────────────────────────────────────────────────────────┘
                              │
              ┌───────────────┼───────────────┐
              ▼               ▼               ▼
        ┌──────────┐   ┌──────────┐   ┌──────────┐
        │PostgreSQL│   │  Redis   │   │  Claude  │
        │(datos)   │   │ (estado) │   │  (IA)    │
        └──────────┘   └──────────┘   └──────────┘

3.2 Responsabilidades por Componente

  • PostgreSQL: Preguntas, categorías, historial de partidas, configuración, logros
  • Redis: Estado de salas activas, turnos, temporizadores, sesiones WebSocket
  • Claude API: Validar respuestas, generar preguntas nuevas

4. Modelo de Datos

4.1 PostgreSQL

-- Categorías
CREATE TABLE categories (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    icon VARCHAR(50),
    color VARCHAR(7)
);

-- Preguntas
CREATE TABLE questions (
    id SERIAL PRIMARY KEY,
    category_id INTEGER REFERENCES categories(id),
    question_text TEXT NOT NULL,
    correct_answer VARCHAR(500) NOT NULL,
    alt_answers TEXT[], -- Respuestas alternativas válidas
    difficulty INTEGER CHECK (difficulty BETWEEN 1 AND 5),
    points INTEGER NOT NULL,
    time_seconds INTEGER NOT NULL,
    date_active DATE,
    status VARCHAR(20) DEFAULT 'pending', -- pending, approved, used
    fun_fact TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);

-- Sesiones de juego
CREATE TABLE game_sessions (
    id SERIAL PRIMARY KEY,
    room_code VARCHAR(6) UNIQUE NOT NULL,
    status VARCHAR(20) DEFAULT 'waiting', -- waiting, playing, finished
    team_a_score INTEGER DEFAULT 0,
    team_b_score INTEGER DEFAULT 0,
    current_team VARCHAR(1), -- 'A' o 'B'
    questions_used INTEGER[],
    created_at TIMESTAMP DEFAULT NOW(),
    finished_at TIMESTAMP
);

-- Eventos de juego (para replays)
CREATE TABLE game_events (
    id SERIAL PRIMARY KEY,
    session_id INTEGER REFERENCES game_sessions(id),
    event_type VARCHAR(50) NOT NULL,
    player_name VARCHAR(100),
    team VARCHAR(1),
    question_id INTEGER REFERENCES questions(id),
    answer_given TEXT,
    was_correct BOOLEAN,
    was_steal BOOLEAN DEFAULT FALSE,
    points_earned INTEGER,
    timestamp TIMESTAMP DEFAULT NOW()
);

-- Administradores
CREATE TABLE admins (
    id SERIAL PRIMARY KEY,
    username VARCHAR(100) UNIQUE NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

4.2 Redis (Estado Volátil)

room:{code} → {
    players: [{name, team, position, socketId}],
    teams: {A: [], B: []},
    currentTeam: 'A',
    currentPlayerIndex: {A: 0, B: 0},
    status: 'waiting|playing|finished',
    timer: timestamp,
    canSteal: false,
    currentQuestion: questionId
}

player:{socket_id} → {name, room, team, position}

5. Sistema de IA

5.1 Validación de Respuestas

VALIDATION_PROMPT = """
Eres un validador de trivia. Determina si la respuesta del jugador
es correcta comparándola con la respuesta oficial.

Pregunta: {question}
Respuesta correcta: {correct_answer}
Respuestas alternativas válidas: {alt_answers}
Respuesta del jugador: {player_answer}

Considera válido si:
- Es sinónimo o variación de la respuesta correcta
- Tiene errores menores de ortografía
- Usa abreviaciones comunes (ej: "BOTW" = "Breath of the Wild")
- Es conceptualmente equivalente

Responde SOLO con JSON: {"valid": true/false, "reason": "breve explicación"}
"""

5.2 Generación de Preguntas

GENERATION_PROMPT = """
Genera 5 preguntas de trivia para la categoría {category}.
Dificultad: {difficulty} (1=muy fácil, 5=muy difícil)

Formato JSON por pregunta:
{
  "question": "texto de la pregunta",
  "correct_answer": "respuesta principal",
  "alt_answers": ["variación1", "variación2"],
  "fun_fact": "dato curioso opcional"
}

Requisitos:
- Las preguntas deben ser verificables y precisas
- Evitar ambigüedades
- Ajustar complejidad según dificultad
- Para gaming: incluir referencias a juegos, personajes, mecánicas
- Para cultura: hechos históricos, arte, literatura
"""

5.3 Flujo de Aprobación

  1. Admin solicita generar preguntas desde panel
  2. Claude genera batch de preguntas
  3. Quedan en estado pending
  4. Admin revisa, edita si necesario, aprueba o rechaza
  5. Preguntas aprobadas se asignan a fecha futura

6. Temas Visuales

6.1 Temas Disponibles

Tema Paleta Principal Características
DRRR (Dollars) Negro, amarillo neón (#FFE135), cyan (#00FFFF) Chat estilo Dollars, efectos glitch, tipografía urbana, bordes neón pulsantes
Retro Arcade Púrpura (#9B59B6), rosa (#E91E63), cyan pixelado Pixel art UI, tipografía 8-bit (Press Start 2P), scanlines, efectos CRT
Moderno Minimalista Blanco (#FFFFFF), grises, acento azul (#3498DB) Limpio, sombras suaves, tipografía sans-serif, transiciones elegantes
Gaming RGB Negro (#0D0D0D) con gradientes RGB Efectos de luz LED, gradientes animados, bordes brillantes, estilo "gamer"
Anime Clásico 90s Pasteles, rosa (#FFB6C1), lavanda (#E6E6FA) Estrellas brillantes, efectos sparkle, bordes redondeados, estilo shoujo

6.2 Implementación

/src/themes/
  ├── ThemeProvider.tsx    # Context para tema activo
  ├── index.ts             # Exporta todos los temas
  ├── drrr/
  │   ├── variables.css
  │   ├── components.tsx
  │   └── sounds/
  ├── retro-arcade/
  ├── minimal/
  ├── gaming-rgb/
  └── anime-90s/

7. Sistema de Sonidos

7.1 Eventos con Sonido

Evento DRRR Retro Minimal RGB Anime 90s
Correcto Glitch digital 8-bit coin Soft chime Synth rise Sparkle
Incorrecto Static buzz 8-bit fail Low tone Bass drop Comedic
Robo Suspense Power-up Click Laser Drama sting
Timer (tick) Heartbeat Beeps Ticks Pulse Tension
Timer (urgente) Fast heartbeat Fast beeps Fast ticks Fast pulse Panic
Victoria Epic synth Fanfare Elegant EDM drop Anime victory
Derrota Glitch fade Game over Soft close Power down Sad piano
Selección Click neón 8-bit select Pop RGB sweep Cute pop

7.2 Almacenamiento

  • Archivos en formato WebM/OGG para compatibilidad
  • Precargados al seleccionar tema
  • Volumen configurable por usuario

8. Sistema de Logros

8.1 Lista de Logros

ID Nombre Condición Icono
1 Primera Victoria Ganar tu primera partida 🏆
2 Racha de 3 Responder 3 correctas seguidas 🔥
3 Racha de 5 Responder 5 correctas seguidas 🔥🔥
4 Ladrón Novato Primer robo exitoso 🦝
5 Ladrón Maestro 5 robos exitosos en una partida 🦝👑
6 Especialista Nintendo 10 correctas en Nintendo 🍄
7 Especialista Xbox 10 correctas en Xbox 🎮
8 Especialista PlayStation 10 correctas en PlayStation 🎯
9 Especialista Anime 10 correctas en Anime ⛩️
10 Especialista Música 10 correctas en Música 🎵
11 Especialista Películas 10 correctas en Películas 🎬
12 Especialista Libros 10 correctas en Libros 📚
13 Especialista Historia 10 correctas en Historia-Cultura 🏛️
14 Invicto Ganar sin fallar ninguna pregunta
15 Velocista Responder correctamente en menos de 3 segundos
16 Comeback Ganar estando 500+ puntos abajo 🔄
17 Dominio Total Responder las 5 preguntas de una categoría correctamente 👑
18 Arriesgado Responder correctamente 3 preguntas de 500 pts 🎰

8.2 Almacenamiento

  • localStorage por navegador (sin cuentas)
  • Estructura: {odooId: {achievements: [...], stats: {...}}}
  • Mostrados al final de cada partida (nuevos desbloqueados)

9. Sistema de Replays

9.1 Datos Capturados

Usando la tabla game_events, cada evento registra:

  • Tipo de evento (question_selected, answer_submitted, steal_attempted, etc.)
  • Jugador y equipo
  • Pregunta seleccionada
  • Respuesta dada
  • Resultado (correcto/incorrecto)
  • Puntos ganados/perdidos
  • Timestamp preciso

9.2 Reproducción

  1. Al finalizar partida, opción "Ver Replay"
  2. Carga eventos ordenados por timestamp
  3. Reproduce animación acelerada (x2, x4, x8)
  4. Muestra:
    • Tablero con preguntas revelándose
    • Respuestas de jugadores
    • Marcador actualizándose
    • Momentos de robo
  5. Controles: Play/Pause, velocidad, timeline scrubber

9.3 Compartir

  • Código único de replay (basado en session_id)
  • URL compartible: /replay/{code}

10. Panel de Administración

10.1 Funcionalidades

┌─────────────────────────────────────────────────────────────┐
│                    PANEL ADMINISTRADOR                       │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  📊 Dashboard                                                │
│     - Partidas activas en tiempo real                       │
│     - Estadísticas del día                                  │
│     - Preguntas pendientes de aprobación                    │
│                                                              │
│  ❓ Gestión de Preguntas                                     │
│     - CRUD de preguntas por categoría                       │
│     - Generar con IA (botón por categoría/dificultad)       │
│     - Cola de aprobación                                    │
│     - Asignar a fechas                                      │
│     - Importar/exportar CSV                                  │
│                                                              │
│  📅 Calendario                                               │
│     - Vista mensual de preguntas programadas                │
│     - Alertas de días sin contenido                         │
│                                                              │
│  🎮 Monitor                                                  │
│     - Salas activas                                         │
│     - Cerrar salas problemáticas                            │
│                                                              │
│  ⚙️ Configuración                                            │
│     - Tiempos y puntos por dificultad                       │
│     - Penalización de robo                                  │
│     - API keys                                              │
│                                                              │
└─────────────────────────────────────────────────────────────┘

10.2 Autenticación

  • Login con usuario/contraseña
  • JWT para sesiones
  • Rutas protegidas /admin/*

11. Comunicación en Partida

11.1 Chat de Equipo

  • Visible solo para miembros del mismo equipo
  • Mensajes en tiempo real via WebSocket
  • Historial durante la partida

11.2 Reacciones Globales

  • Emojis predefinidos que todos pueden ver
  • Limitado para evitar spam (1 cada 3 segundos)
  • Emojis disponibles: 👏 😮 😂 🔥 💀 🎉 😭 🤔

12. Estructura del Proyecto

WebTriviasMulti/
├── backend/
│   ├── app/
│   │   ├── __init__.py
│   │   ├── main.py
│   │   ├── config.py
│   │   ├── models/
│   │   │   ├── __init__.py
│   │   │   ├── category.py
│   │   │   ├── question.py
│   │   │   ├── game_session.py
│   │   │   ├── game_event.py
│   │   │   └── admin.py
│   │   ├── schemas/
│   │   │   ├── __init__.py
│   │   │   ├── question.py
│   │   │   ├── game.py
│   │   │   └── admin.py
│   │   ├── services/
│   │   │   ├── __init__.py
│   │   │   ├── ai_validator.py
│   │   │   ├── ai_generator.py
│   │   │   ├── game_manager.py
│   │   │   └── room_manager.py
│   │   ├── api/
│   │   │   ├── __init__.py
│   │   │   ├── admin.py
│   │   │   ├── game.py
│   │   │   └── replay.py
│   │   └── sockets/
│   │       ├── __init__.py
│   │       └── game_events.py
│   ├── requirements.txt
│   ├── Dockerfile
│   ├── alembic.ini
│   └── alembic/
│       └── versions/
│
├── frontend/
│   ├── src/
│   │   ├── components/
│   │   │   ├── game/
│   │   │   │   ├── Board.tsx
│   │   │   │   ├── QuestionCard.tsx
│   │   │   │   ├── Timer.tsx
│   │   │   │   ├── ScoreBoard.tsx
│   │   │   │   └── AnswerInput.tsx
│   │   │   ├── lobby/
│   │   │   │   ├── CreateRoom.tsx
│   │   │   │   ├── JoinRoom.tsx
│   │   │   │   ├── TeamSelect.tsx
│   │   │   │   └── PlayerList.tsx
│   │   │   ├── chat/
│   │   │   │   ├── TeamChat.tsx
│   │   │   │   └── EmojiReactions.tsx
│   │   │   ├── replay/
│   │   │   │   ├── ReplayPlayer.tsx
│   │   │   │   └── ReplayControls.tsx
│   │   │   ├── achievements/
│   │   │   │   ├── AchievementPopup.tsx
│   │   │   │   └── AchievementList.tsx
│   │   │   └── ui/
│   │   │       ├── Button.tsx
│   │   │       ├── Modal.tsx
│   │   │       ├── Input.tsx
│   │   │       └── Toast.tsx
│   │   ├── themes/
│   │   │   ├── ThemeProvider.tsx
│   │   │   ├── index.ts
│   │   │   ├── drrr/
│   │   │   ├── retro-arcade/
│   │   │   ├── minimal/
│   │   │   ├── gaming-rgb/
│   │   │   └── anime-90s/
│   │   ├── hooks/
│   │   │   ├── useSocket.ts
│   │   │   ├── useGame.ts
│   │   │   ├── useSound.ts
│   │   │   └── useAchievements.ts
│   │   ├── stores/
│   │   │   ├── gameStore.ts
│   │   │   ├── themeStore.ts
│   │   │   └── soundStore.ts
│   │   ├── pages/
│   │   │   ├── Home.tsx
│   │   │   ├── Lobby.tsx
│   │   │   ├── Game.tsx
│   │   │   ├── Replay.tsx
│   │   │   ├── Results.tsx
│   │   │   └── admin/
│   │   │       ├── Dashboard.tsx
│   │   │       ├── Questions.tsx
│   │   │       ├── Calendar.tsx
│   │   │       ├── Monitor.tsx
│   │   │       └── Settings.tsx
│   │   ├── services/
│   │   │   ├── socket.ts
│   │   │   └── api.ts
│   │   ├── types/
│   │   │   └── index.ts
│   │   ├── App.tsx
│   │   └── main.tsx
│   ├── public/
│   │   └── sounds/
│   ├── package.json
│   ├── Dockerfile
│   ├── vite.config.ts
│   ├── tailwind.config.js
│   └── tsconfig.json
│
├── docker-compose.yml
├── .env.example
├── .gitignore
├── README.md
└── docs/
    └── plans/
        └── 2026-01-26-webtriviasmulti-design.md

13. Despliegue

13.1 Docker Compose

version: '3.8'

services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    environment:
      - VITE_API_URL=http://localhost:8000
      - VITE_WS_URL=ws://localhost:8000

  backend:
    build: ./backend
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://trivia:trivia@db:5432/trivia
      - REDIS_URL=redis://redis:6379
      - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      - db
      - redis

  db:
    image: postgres:15
    volumes:
      - postgres_data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=trivia
      - POSTGRES_USER=trivia
      - POSTGRES_PASSWORD=trivia

  redis:
    image: redis:7-alpine
    volumes:
      - redis_data:/data

  cloudflared:
    image: cloudflare/cloudflared:latest
    command: tunnel run
    environment:
      - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}
    depends_on:
      - frontend
      - backend

volumes:
  postgres_data:
  redis_data:

13.2 Variables de Entorno

# Backend
DATABASE_URL=postgresql://trivia:trivia@db:5432/trivia
REDIS_URL=redis://redis:6379
ANTHROPIC_API_KEY=sk-ant-...
JWT_SECRET=your-secret-key

# Frontend
VITE_API_URL=https://trivia.tudominio.com/api
VITE_WS_URL=wss://trivia.tudominio.com

# Cloudflare
CLOUDFLARE_TUNNEL_TOKEN=your-tunnel-token

14. Roadmap Futuro

Fase 3 - Competitivo

  • Ranking global (requiere cuentas opcionales)
  • Torneos programados
  • Temporadas con recompensas

Fase 4 - Social

  • Compartir resultados en redes
  • Salas recurrentes
  • Desafíos diarios

Fase 5 - Contenido

  • Categorías rotativas por eventos
  • Preguntas de la comunidad
  • Modo "Experto"

Fase 6 - Técnico

  • PWA instalable
  • API pública
  • Modo offline

15. Referencias


Documento generado el 2026-01-26