- README.md: descripción general, stack, instalación rápida - docs/API.md: referencia completa de API REST y WebSocket - docs/ARCHITECTURE.md: arquitectura del sistema con diagramas - docs/INSTALLATION.md: guía detallada de instalación - backend/.env.example: plantilla de configuración Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
345 lines
9.1 KiB
Markdown
345 lines
9.1 KiB
Markdown
# Trivy - Trivia Multiplayer en Tiempo Real
|
||
|
||
<p align="center">
|
||
<img src="docs/logo.png" alt="Trivy Logo" width="200">
|
||
</p>
|
||
|
||
**Trivy** es un juego de trivia multijugador en tiempo real inspirado en Jeopardy. Dos equipos compiten respondiendo preguntas de diferentes categorías, con mecánicas de robo y validación de respuestas por IA.
|
||
|
||
## Características
|
||
|
||
- **Multijugador en tiempo real** - Hasta 8 jugadores (2 equipos × 4 jugadores)
|
||
- **8 categorías temáticas** - Nintendo, Xbox, PlayStation, Anime, Música, Películas, Libros, Historia
|
||
- **5 categorías por partida** - Rotación aleatoria entre partidas
|
||
- **Pool de 200 preguntas** - 5 opciones por cada categoría/dificultad
|
||
- **Validación de respuestas por IA** - Claude API para respuestas flexibles
|
||
- **Sistema de robo** - Oportunidad de robar puntos cuando el equipo contrario falla
|
||
- **Múltiples temas visuales** - DRRR, Retro Arcade, Minimal, Gaming RGB, Anime 90s
|
||
- **Efectos de sonido** - Sonidos personalizados por tema
|
||
- **Chat de equipo** - Comunicación privada entre compañeros
|
||
- **Reacciones emoji** - Expresiones en tiempo real
|
||
- **Panel de administración** - Gestión de preguntas, categorías y monitoreo
|
||
|
||
## Stack Tecnológico
|
||
|
||
### Backend
|
||
- **FastAPI** - Framework web async de alto rendimiento
|
||
- **Python-SocketIO** - WebSockets para comunicación en tiempo real
|
||
- **PostgreSQL** - Base de datos principal
|
||
- **Redis** - Estado de salas y sesiones en tiempo real
|
||
- **SQLAlchemy** - ORM async
|
||
- **Anthropic Claude API** - Validación inteligente de respuestas
|
||
|
||
### Frontend
|
||
- **React 18** - UI declarativa
|
||
- **TypeScript** - Tipado estático
|
||
- **Vite** - Build tool rápido
|
||
- **Zustand** - Estado global ligero
|
||
- **Framer Motion** - Animaciones fluidas
|
||
- **Tailwind CSS** - Estilos utilitarios
|
||
- **Socket.IO Client** - Comunicación WebSocket
|
||
- **Howler.js** - Gestión de audio
|
||
|
||
## Requisitos
|
||
|
||
- Python 3.11+
|
||
- Node.js 18+
|
||
- PostgreSQL 15+
|
||
- Redis 7+
|
||
- API Key de Anthropic (Claude)
|
||
|
||
## Instalación
|
||
|
||
### 1. Clonar repositorio
|
||
|
||
```bash
|
||
git clone https://gitea.local/frank/Trivy.git
|
||
cd Trivy
|
||
```
|
||
|
||
### 2. Configurar Backend
|
||
|
||
```bash
|
||
cd backend
|
||
|
||
# Crear entorno virtual
|
||
python -m venv venv
|
||
source venv/bin/activate # Linux/Mac
|
||
# o: venv\Scripts\activate # Windows
|
||
|
||
# Instalar dependencias
|
||
pip install -r requirements.txt
|
||
|
||
# Configurar variables de entorno
|
||
cp .env.example .env
|
||
# Editar .env con tus credenciales
|
||
```
|
||
|
||
### 3. Configurar Frontend
|
||
|
||
```bash
|
||
cd frontend
|
||
|
||
# Instalar dependencias
|
||
npm install
|
||
|
||
# Configurar variables de entorno
|
||
cp .env.example .env
|
||
# Editar .env con la URL del backend
|
||
```
|
||
|
||
### 4. Base de datos
|
||
|
||
```bash
|
||
# Con Docker
|
||
docker-compose up -d db redis
|
||
|
||
# O configurar PostgreSQL y Redis manualmente
|
||
# Crear base de datos: trivy
|
||
```
|
||
|
||
### 5. Migraciones
|
||
|
||
```bash
|
||
cd backend
|
||
alembic upgrade head
|
||
```
|
||
|
||
### 6. Datos iniciales
|
||
|
||
```bash
|
||
# Crear usuario admin
|
||
python -c "
|
||
from app.models.base import get_async_session
|
||
from app.models.admin import Admin
|
||
import asyncio
|
||
|
||
async def create_admin():
|
||
async with get_async_session()() as db:
|
||
admin = Admin(username='admin')
|
||
admin.set_password('admin123')
|
||
db.add(admin)
|
||
await db.commit()
|
||
|
||
asyncio.run(create_admin())
|
||
"
|
||
|
||
# Crear categorías y preguntas iniciales
|
||
python scripts/seed_data.py
|
||
```
|
||
|
||
## Ejecución
|
||
|
||
### Desarrollo
|
||
|
||
```bash
|
||
# Terminal 1 - Backend
|
||
cd backend
|
||
source venv/bin/activate
|
||
uvicorn app.main:socket_app --host 0.0.0.0 --port 8000 --reload
|
||
|
||
# Terminal 2 - Frontend
|
||
cd frontend
|
||
npm run dev -- --host
|
||
```
|
||
|
||
### Producción
|
||
|
||
```bash
|
||
# Backend con Gunicorn
|
||
gunicorn app.main:socket_app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000
|
||
|
||
# Frontend build
|
||
cd frontend
|
||
npm run build
|
||
# Servir dist/ con nginx o similar
|
||
```
|
||
|
||
## Configuración
|
||
|
||
### Variables de entorno - Backend (.env)
|
||
|
||
```env
|
||
# Base de datos
|
||
DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/trivy
|
||
|
||
# Redis
|
||
REDIS_URL=redis://localhost:6379
|
||
|
||
# Anthropic API
|
||
ANTHROPIC_API_KEY=sk-ant-...
|
||
|
||
# Configuración del juego
|
||
STEAL_PENALTY_MULTIPLIER=0.5
|
||
STEAL_TIME_MULTIPLIER=0.5
|
||
ROOM_TTL_HOURS=3
|
||
```
|
||
|
||
### Variables de entorno - Frontend (.env)
|
||
|
||
```env
|
||
VITE_API_URL=http://localhost:8000
|
||
VITE_WS_URL=http://localhost:8000
|
||
```
|
||
|
||
## Arquitectura
|
||
|
||
```
|
||
Trivy/
|
||
├── backend/
|
||
│ ├── app/
|
||
│ │ ├── api/ # Endpoints REST
|
||
│ │ │ ├── admin.py # Panel de administración
|
||
│ │ │ ├── auth.py # Autenticación
|
||
│ │ │ └── game.py # Datos del juego
|
||
│ │ ├── models/ # Modelos SQLAlchemy
|
||
│ │ ├── schemas/ # Schemas Pydantic
|
||
│ │ ├── services/ # Lógica de negocio
|
||
│ │ │ ├── room_manager.py # Gestión de salas (Redis)
|
||
│ │ │ ├── game_manager.py # Lógica del juego
|
||
│ │ │ ├── ai_validator.py # Validación con Claude
|
||
│ │ │ └── question_service.py # Carga de preguntas
|
||
│ │ ├── sockets/ # Eventos WebSocket
|
||
│ │ │ └── game_events.py
|
||
│ │ ├── config.py # Configuración
|
||
│ │ └── main.py # Aplicación ASGI
|
||
│ ├── alembic/ # Migraciones
|
||
│ └── requirements.txt
|
||
│
|
||
├── frontend/
|
||
│ ├── src/
|
||
│ │ ├── components/ # Componentes React
|
||
│ │ │ ├── chat/ # Chat y reacciones
|
||
│ │ │ ├── game/ # Componentes del juego
|
||
│ │ │ ├── lobby/ # Sala de espera
|
||
│ │ │ └── ui/ # Componentes UI genéricos
|
||
│ │ ├── hooks/ # Custom hooks
|
||
│ │ │ ├── useSocket.ts
|
||
│ │ │ └── useSound.ts
|
||
│ │ ├── pages/ # Páginas/rutas
|
||
│ │ ├── services/ # Servicios (socket)
|
||
│ │ ├── stores/ # Estado Zustand
|
||
│ │ ├── themes/ # Temas visuales
|
||
│ │ └── types/ # Tipos TypeScript
|
||
│ ├── public/
|
||
│ │ └── sounds/ # Archivos de audio
|
||
│ └── package.json
|
||
│
|
||
└── docs/ # Documentación
|
||
```
|
||
|
||
## Flujo del Juego
|
||
|
||
```
|
||
1. CREAR SALA
|
||
Host → create_room → Código de 6 caracteres
|
||
|
||
2. UNIRSE
|
||
Jugadores → join_room(código) → Asignación a equipo A/B
|
||
|
||
3. INICIAR
|
||
Host → start_game → Backend carga 5 categorías aleatorias
|
||
|
||
4. TURNO
|
||
Jugador actual → Selecciona pregunta del tablero
|
||
|
||
5. RESPONDER
|
||
30 segundos para escribir respuesta
|
||
Claude valida si es correcta
|
||
|
||
6. ROBO (si falla)
|
||
Equipo contrario puede intentar robar
|
||
Si falla el robo, pierde puntos
|
||
|
||
7. SIGUIENTE TURNO
|
||
Rotación de jugadores y equipos
|
||
|
||
8. FIN
|
||
Cuando todas las preguntas están contestadas
|
||
Equipo con más puntos gana
|
||
```
|
||
|
||
## API REST
|
||
|
||
### Autenticación
|
||
- `POST /api/auth/login` - Login admin
|
||
- `POST /api/auth/logout` - Logout
|
||
|
||
### Juego
|
||
- `GET /api/game/categories` - Lista de categorías
|
||
- `GET /api/game/today-questions` - Preguntas del día
|
||
|
||
### Admin
|
||
- `GET /api/admin/questions` - Listar preguntas
|
||
- `POST /api/admin/questions` - Crear pregunta
|
||
- `PUT /api/admin/questions/{id}` - Actualizar pregunta
|
||
- `DELETE /api/admin/questions/{id}` - Eliminar pregunta
|
||
- `GET /api/admin/categories` - Listar categorías
|
||
- `GET /api/admin/rooms/active` - Salas activas
|
||
|
||
## Eventos WebSocket
|
||
|
||
### Cliente → Servidor
|
||
- `create_room` - Crear nueva sala
|
||
- `join_room` - Unirse a sala existente
|
||
- `start_game` - Iniciar partida (solo host)
|
||
- `select_question` - Seleccionar pregunta
|
||
- `submit_answer` - Enviar respuesta
|
||
- `steal_decision` - Decidir si robar
|
||
- `chat_message` - Mensaje de chat
|
||
- `team_message` - Mensaje de equipo
|
||
- `send_reaction` - Enviar emoji
|
||
|
||
### Servidor → Cliente
|
||
- `room_created` - Sala creada
|
||
- `player_joined` - Jugador se unió
|
||
- `game_started` - Juego iniciado
|
||
- `question_selected` - Pregunta seleccionada
|
||
- `answer_result` - Resultado de respuesta
|
||
- `steal_prompt` - Oportunidad de robo
|
||
- `game_finished` - Juego terminado
|
||
- `error` - Error
|
||
|
||
## Temas Disponibles
|
||
|
||
| Tema | Descripción |
|
||
|------|-------------|
|
||
| DRRR | Inspirado en Durarara!! - Oscuro con acentos amarillos |
|
||
| Retro Arcade | Estética arcade 80s - Neón sobre negro |
|
||
| Minimal | Diseño limpio y moderno - Blanco con acentos |
|
||
| Gaming RGB | Gradientes RGB animados - Estilo gamer |
|
||
| Anime 90s | Colores pasteles - Nostalgia anime |
|
||
|
||
## Categorías
|
||
|
||
1. **Nintendo** 🍄 - Mario, Zelda, Pokémon, etc.
|
||
2. **Xbox** 🎮 - Halo, Forza, Game Pass, etc.
|
||
3. **PlayStation** 🎯 - God of War, Uncharted, etc.
|
||
4. **Anime** ⛩️ - Naruto, One Piece, Dragon Ball, etc.
|
||
5. **Música** 🎵 - Artistas, géneros, historia musical
|
||
6. **Películas** 🎬 - Cine clásico y moderno
|
||
7. **Libros** 📚 - Literatura universal
|
||
8. **Historia** 🏛️ - Historia y cultura general
|
||
|
||
## Contribuir
|
||
|
||
1. Fork el repositorio
|
||
2. Crear rama feature (`git checkout -b feature/nueva-funcionalidad`)
|
||
3. Commit cambios (`git commit -m 'feat: descripción'`)
|
||
4. Push a la rama (`git push origin feature/nueva-funcionalidad`)
|
||
5. Crear Pull Request
|
||
|
||
## Licencia
|
||
|
||
MIT License - ver [LICENSE](LICENSE)
|
||
|
||
## Créditos
|
||
|
||
Desarrollado por Frank con asistencia de Claude (Anthropic)
|
||
|
||
---
|
||
|
||
<p align="center">
|
||
<strong>¡Que gane el mejor equipo!</strong> 🏆
|
||
</p>
|