Changes include: - Updated architecture documentation - Enhanced module definitions (OQI-001 to OQI-008) - ML integration documentation updates - Trading strategies documentation - Orchestration and inventory updates - Docker configuration updates 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
12 KiB
12 KiB
| id | title | type | status | priority | module | epic | version | created_date | updated_date |
|---|---|---|---|---|---|---|---|---|---|
| RF-EDU-004 | Sistema de Quizzes | Requirement | Done | Alta | education | OQI-002 | 1.0 | 2025-12-05 | 2026-01-04 |
RF-EDU-004: Sistema de Quizzes
Versión: 1.0.0 Fecha: 2025-12-05 Épica: OQI-002 - Módulo Educativo Prioridad: P1 Story Points: 8
Descripción
El sistema debe proporcionar un sistema completo de evaluaciones interactivas (quizzes) que permita validar el conocimiento adquirido por los usuarios, con soporte para múltiples tipos de preguntas, feedback inmediato, intentos limitados, calificaciones y análisis de resultados.
Requisitos Funcionales
RF-EDU-004.1: Tipos de Preguntas
El sistema debe soportar:
| Tipo | Descripción | Características |
|---|---|---|
| Multiple Choice | Una respuesta correcta | 2-6 opciones |
| Multiple Select | Varias respuestas correctas | Checkbox, puntuación parcial |
| True/False | Verdadero o falso | 2 opciones |
| Fill in the Blank | Completar espacios | Input de texto, validación |
| Matching | Emparejar elementos | Drag & drop opcional |
| Ordering | Ordenar elementos | Secuencia correcta |
RF-EDU-004.2: Estructura de Quiz
Cada quiz debe tener:
- Título y descripción
- Tiempo límite (opcional)
- Número de preguntas
- Puntuación mínima para aprobar (% o puntos)
- Número de intentos permitidos (ilimitado, 1, 2, 3...)
- Modo: Práctica (sin límite) o Evaluación (formal)
- Mostrar respuestas correctas: Inmediato, Al finalizar, Nunca
- Barajear preguntas (randomizar orden)
- Barajear opciones de respuesta
RF-EDU-004.3: Interfaz de Quiz
El sistema debe mostrar:
- Contador de preguntas (Pregunta 1 de 10)
- Barra de progreso del quiz
- Timer countdown si hay límite de tiempo
- Pregunta actual con opciones
- Botones: "Anterior", "Siguiente", "Marcar para revisión"
- Navegador de preguntas (minimap con estado: respondida, marcada, pendiente)
- Botón "Finalizar quiz" (requiere confirmación)
- Auto-submit cuando expira el tiempo
RF-EDU-004.4: Navegación y Estados
Estados de pregunta:
- No respondida: Sin respuesta seleccionada
- Respondida: Respuesta seleccionada
- Marcada: Flagged para revisión posterior
- Correcta: Solo visible después de submit (si configurado)
- Incorrecta: Solo visible después de submit (si configurado)
El usuario debe poder:
- Navegar libremente entre preguntas antes de submit
- Cambiar respuestas antes de finalizar
- Marcar preguntas para revisar después
- Ver resumen antes de enviar
RF-EDU-004.5: Calificación y Resultados
Al finalizar el quiz, mostrar:
- Puntuación obtenida (X/Y puntos o %)
- Estado: Aprobado / Reprobado
- Tiempo invertido
- Feedback general basado en score
- Desglose por pregunta (si configurado):
- Pregunta
- Tu respuesta
- Respuesta correcta
- Explicación
- Intentos restantes
- Botón "Reintentar" si aplica
- Botón "Continuar al siguiente contenido"
RF-EDU-004.6: Historial de Intentos
El sistema debe:
- Guardar todos los intentos del usuario
- Mostrar tabla con: fecha, puntuación, tiempo, estado
- Permitir ver detalle de intento anterior
- Mostrar mejor intento destacado
- Calcular promedio de intentos
- Guardar última puntuación como oficial
RF-EDU-004.7: Feedback y Explicaciones
El sistema debe permitir:
- Explicación de respuesta correcta (markdown)
- Explicación de por qué otras opciones son incorrectas
- Links a recursos relacionados
- Video explicativo opcional
- Sugerencias de lecciones para repasar
RF-EDU-004.8: Analítica de Quiz
Para cada pregunta, rastrear:
- Número de veces respondida
- Número de respuestas correctas
- Número de respuestas incorrectas
- Tasa de éxito global (%)
- Tiempo promedio de respuesta
- Opción más elegida (para detectar confusión)
Para cada quiz, rastrear:
- Número de intentos totales
- Tasa de aprobación (%)
- Puntuación promedio
- Tiempo promedio de completitud
- Pregunta más difícil (menor % acierto)
- Pregunta más fácil (mayor % acierto)
Datos de Entrada
| Campo | Tipo | Descripción |
|---|---|---|
| quizId | string | UUID del quiz |
| answers | object | Mapa de questionId -> respuesta |
Datos de Salida
interface Quiz {
id: string;
title: string;
description: string;
lessonId?: string;
courseId: string;
timeLimit?: number; // minutos
passingScore: number; // 0-100
maxAttempts: number; // 0 = ilimitado
questionCount: number;
totalPoints: number;
shuffleQuestions: boolean;
shuffleOptions: boolean;
showAnswers: 'immediate' | 'after_submit' | 'never';
mode: 'practice' | 'assessment';
}
interface Question {
id: string;
quizId: string;
type: 'multiple_choice' | 'multiple_select' | 'true_false' | 'fill_blank' | 'matching' | 'ordering';
question: string; // Markdown
points: number;
order: number;
// Para multiple choice/select
options?: {
id: string;
text: string;
isCorrect: boolean;
explanation?: string;
}[];
// Para fill in the blank
correctAnswers?: string[];
caseSensitive?: boolean;
// Para matching
pairs?: {
left: string;
right: string;
}[];
// Para ordering
correctOrder?: string[];
explanation?: string; // Explicación general
hint?: string;
relatedResources?: {
type: 'lesson' | 'article' | 'video';
id: string;
title: string;
}[];
}
interface QuizAttempt {
id: string;
quizId: string;
userId: string;
attemptNumber: number;
startedAt: string;
submittedAt?: string;
timeSpent: number; // segundos
answers: {
questionId: string;
userAnswer: any;
isCorrect: boolean;
pointsEarned: number;
}[];
score: number; // 0-100
pointsEarned: number;
totalPoints: number;
passed: boolean;
analytics: {
questionsCorrect: number;
questionsIncorrect: number;
questionsSkipped: number;
avgTimePerQuestion: number;
};
}
interface QuizResults {
attempt: QuizAttempt;
quiz: Quiz;
questions: (Question & {
userAnswer: any;
isCorrect: boolean;
pointsEarned: number;
})[];
feedback: {
title: string;
message: string;
suggestions?: string[];
};
attemptsRemaining: number;
canRetake: boolean;
nextContent?: {
type: 'lesson' | 'quiz' | 'module';
id: string;
title: string;
};
}
Reglas de Negocio
- Puntuación mínima: Default 70% para aprobar
- Intentos: Si se agotan intentos, usuario debe esperar 24h o contactar soporte
- Tiempo límite: Si expira, se auto-submit con respuestas actuales
- Preguntas obligatorias: No se puede submit sin responder todas (modo evaluación)
- Modo práctica: Sin límite de intentos, sin guardar en historial oficial
- Partial credit: Multiple select otorga puntos parciales (50% si elige 2/4 correctas)
- Shuffle: Si está activado, orden diferente en cada intento
- Feedback inmediato: Solo en modo práctica
- Certificación: Quiz final de curso debe aprobarse para certificado
Criterios de Aceptación
Escenario: Usuario inicia quiz
DADO que el usuario está en una lección con quiz
CUANDO hace click en "Iniciar quiz"
ENTONCES se muestra pantalla de introducción del quiz
Y se muestra título, descripción, número de preguntas
Y se muestra tiempo límite si aplica
Y se muestra intentos disponibles
Y se muestra puntuación requerida para aprobar
Y se muestra botón "Comenzar"
Escenario: Usuario responde preguntas
DADO que el usuario comenzó el quiz
CUANDO selecciona una respuesta
ENTONCES la opción se marca como seleccionada
Y la pregunta se marca como "respondida"
Y puede navegar a siguiente pregunta
Y puede volver a preguntas anteriores
Y puede cambiar respuesta antes de submit
Escenario: Usuario finaliza quiz exitosamente
DADO que el usuario respondió todas las preguntas
CUANDO hace click en "Finalizar quiz"
Y confirma en el modal
ENTONCES se calcula la puntuación
Y se muestra pantalla de resultados
Y se muestra "Aprobado" si score >= passing score
Y se desbloquea siguiente contenido
Y se otorga XP por aprobar
Escenario: Usuario reprueba quiz
DADO que el usuario envió el quiz
Y la puntuación es < passing score
ENTONCES se muestra pantalla de resultados
Y se muestra "Reprobado"
Y se muestra feedback con áreas a mejorar
Y se muestra "Intentos restantes: X"
Y se muestra botón "Reintentar"
Y siguiente contenido permanece bloqueado
Escenario: Quiz con tiempo límite expira
DADO que el quiz tiene tiempo límite de 30 minutos
Y el usuario está en la pregunta 5 de 10
CUANDO el tiempo llega a 0
ENTONCES el quiz se envía automáticamente
Y se califica con respuestas hasta el momento
Y preguntas sin responder cuentan como incorrectas
Escenario: Ver explicación de respuestas
DADO que el quiz permite ver respuestas
Y el usuario envió el quiz
CUANDO ve los resultados
ENTONCES se muestran todas las preguntas
Y se destacan respuestas correctas en verde
Y se destacan respuestas incorrectas en rojo
Y se muestra explicación de cada respuesta
Y se muestran recursos relacionados
Escenario: Reintentar quiz
DADO que el usuario reprobó un quiz
Y tiene intentos disponibles
CUANDO hace click en "Reintentar"
ENTONCES se inicia nuevo intento
Y preguntas pueden estar en diferente orden
Y respuestas anteriores no están pre-seleccionadas
Y contador de intentos se decrementa
Dependencias
- PostgreSQL para quizzes y resultados
- Redis para cachear quizzes activos
- WebSocket para timer en tiempo real (opcional)
Notas Técnicas
- Implementar auto-save cada 30s para evitar pérdida de progreso
- Usar WebSockets para sincronizar timer entre tabs
- Encriptar respuestas correctas en frontend
- Validar respuestas en backend (nunca confiar en frontend)
- Implementar rate limiting para prevenir brute force
- Usar optimistic updates para mejor UX
- Considerar adaptive quizzes (ajustar dificultad según respuestas)
Referencias
- Schema:
/backend/src/database/schemas/education.sql - API:
/backend/src/modules/courses/quizzes.routes.ts - Frontend:
/frontend/src/pages/QuizPlayer.tsx
Tareas Técnicas
Database:
- Tabla education.quizzes
- Tabla education.questions con FK a quiz
- Tabla education.question_options
- Tabla education.quiz_attempts
- Tabla education.quiz_answers
- Índices para queries por usuario y quiz
Backend:
- Endpoint GET /education/quizzes/:id (sin respuestas correctas)
- Endpoint POST /education/quizzes/:id/start
- Endpoint POST /education/quizzes/:id/submit
- Endpoint GET /education/quizzes/:id/attempts (historial)
- Endpoint GET /education/quizzes/:id/results/:attemptId
- Implementar QuizService.gradeAttempt()
- Implementar shuffle de preguntas y opciones
- Rate limiting en submit
Frontend:
- Crear QuizIntroPage.tsx
- Crear QuizPlayerPage.tsx
- Crear componente QuestionRenderer.tsx (soporta todos los tipos)
- Crear componente QuizNavigator.tsx
- Crear componente QuizTimer.tsx
- Crear QuizResultsPage.tsx
- Crear componente QuestionExplanation.tsx
- Auto-save de respuestas cada 30s
- Implementar quizStore
- Confirmación antes de salir (window.onbeforeunload)
Tests:
- Test calificación de quiz con diferentes tipos de preguntas
- Test partial credit en multiple select
- Test expiración de tiempo
- Test E2E completar quiz y aprobar
Creado por: Requirements-Analyst Fecha: 2025-12-05 Última actualización: 2025-12-05