---
id: "RF-EDU-002"
title: "Sistema de Lecciones"
type: "Requirement"
status: "Done"
priority: "Alta"
module: "education"
epic: "OQI-002"
version: "1.0"
created_date: "2025-12-05"
updated_date: "2026-01-04"
---

# RF-EDU-002: Sistema de Lecciones

**Versión:** 1.0.0
**Fecha:** 2025-12-05
**Épica:** OQI-002 - Módulo Educativo
**Prioridad:** P0
**Story Points:** 8

---

## Descripción

El sistema debe proporcionar un reproductor multimedia completo que permita a los usuarios consumir contenido educativo en múltiples formatos (video, texto, código interactivo, quizzes) con controles de navegación, seguimiento de progreso y experiencia de aprendizaje optimizada.

---

## Requisitos Funcionales

### RF-EDU-002.1: Tipos de Lecciones

El sistema debe soportar:

| Tipo | Descripción | Características |
|------|-------------|-----------------|
| **Video** | Contenido en video | Reproductor, subtítulos, velocidad |
| **Artículo** | Contenido de texto | Markdown, imágenes, código |
| **Quiz** | Evaluación interactiva | Preguntas, feedback inmediato |
| **Código** | Ejercicio práctico | Editor, ejecución, validación |
| **Recursos** | Descargables | PDFs, hojas de cálculo, código |

### RF-EDU-002.2: Reproductor de Video

El sistema debe:
- Reproducir videos desde CDN (Vimeo/YouTube/S3)
- Controles: play/pause, volumen, pantalla completa
- Velocidades: 0.5x, 0.75x, 1x, 1.25x, 1.5x, 2x
- Subtítulos en español e inglés (opcional)
- Recordar posición de reproducción
- Saltar 10s adelante/atrás con teclas de flecha
- Atajos de teclado (espacio=play/pause, f=fullscreen, m=mute)
- Barra de progreso con preview al hover
- Marcadores de secciones importantes
- Calidad adaptativa según ancho de banda

### RF-EDU-002.3: Lecciones de Artículo

El sistema debe:
- Renderizar Markdown con syntax highlighting
- Soportar: headers, listas, tablas, imágenes, videos embebidos
- Mostrar tabla de contenidos (TOC) para artículos largos
- Estimación de tiempo de lectura
- Resaltar código con Prism.js o similar
- Copiar código con un click
- Modo oscuro/claro para lectura
- Marcar artículo como completado con checkbox al final

### RF-EDU-002.4: Navegación entre Lecciones

El sistema debe:
- Mostrar sidebar con estructura del curso (módulos > lecciones)
- Indicar lección actual destacada
- Mostrar checkmarks en lecciones completadas
- Mostrar progreso en módulos (X/Y lecciones)
- Botones "Anterior" y "Siguiente" lección
- Bloquear lecciones futuras si curso es secuencial
- Permitir saltar libremente si curso es no-secuencial
- Collapse/expand de módulos en sidebar

### RF-EDU-002.5: Recursos Descargables

El sistema debe:
- Listar recursos disponibles para la lección
- Mostrar: nombre, tipo de archivo, tamaño
- Permitir descargar con un click
- Trackear descargas para analytics
- Validar acceso antes de descargar
- Soportar: PDF, XLSX, CSV, ZIP, código fuente

### RF-EDU-002.6: Notas del Usuario

El sistema debe:
- Permitir tomar notas durante lección
- Editor de texto enriquecido (bold, italic, listas)
- Guardar automáticamente (debounce 2s)
- Timestamp de la nota (para videos)
- Listar todas las notas del curso
- Buscar en notas
- Exportar notas a PDF/Markdown

### RF-EDU-002.7: Marcadores y Favoritos

El sistema debe:
- Permitir marcar timestamp en videos
- Agregar comentario al marcador
- Listar marcadores en sidebar
- Saltar a marcador con click
- Exportar marcadores

---

## Datos de Entrada

| Campo | Tipo | Descripción |
|-------|------|-------------|
| courseId | string | UUID del curso |
| lessonId | string | UUID de la lección |
| timestamp | number | Posición en video (segundos) |

---

## Datos de Salida

```typescript
interface Lesson {
  id: string;
  moduleId: string;
  title: string;
  slug: string;
  description: string;
  type: 'video' | 'article' | 'quiz' | 'code' | 'resource';
  order: number;
  duration: number; // minutos
  isFree: boolean;
  isCompleted: boolean;

  // Video específico
  videoUrl?: string;
  videoProvider?: 'vimeo' | 'youtube' | 's3';
  videoId?: string;
  subtitles?: {
    language: string;
    url: string;
  }[];

  // Artículo específico
  content?: string; // Markdown
  readingTime?: number; // minutos

  // Quiz específico
  quizId?: string;
  questionsCount?: number;
  passingScore?: number;

  // Recursos
  resources?: {
    id: string;
    name: string;
    type: string;
    url: string;
    size: number;
  }[];

  // Progreso del usuario
  userProgress?: {
    startedAt: string;
    completedAt?: string;
    lastPosition: number; // Para videos
    timeSpent: number; // segundos
    notes?: string;
  };
}

interface LessonNavigation {
  currentLesson: Lesson;
  previousLesson?: {
    id: string;
    title: string;
    slug: string;
  };
  nextLesson?: {
    id: string;
    title: string;
    slug: string;
  };
  module: {
    id: string;
    title: string;
    lessons: {
      id: string;
      title: string;
      isCompleted: boolean;
      isLocked: boolean;
    }[];
  };
}
```

---

## Reglas de Negocio

1. **Orden secuencial:** Si curso requiere orden, solo lección actual y anteriores están desbloqueadas
2. **Completar lección:** Video: ver 90%, Artículo: scroll al final, Quiz: aprobar
3. **Acceso Premium:** Lecciones no-free requieren suscripción activa
4. **Auto-save progreso:** Guardar posición cada 10 segundos
5. **Marcado manual:** Usuario puede marcar completado manualmente
6. **Recursos solo para enrollados:** No se pueden descargar recursos sin estar inscrito
7. **Notas privadas:** Solo visibles para el usuario que las creó
8. **Tiempo mínimo:** Video debe reproducirse al menos 30s para contar progreso

---

## Criterios de Aceptación

```gherkin
Escenario: Usuario visualiza lección de video
  DADO que el usuario está inscrito en curso
  Y está en /education/courses/:slug/lessons/:lessonSlug
  CUANDO la lección es tipo video
  ENTONCES se muestra reproductor de video
  Y se muestran controles de reproducción
  Y se muestra sidebar con estructura del curso
  Y se carga la posición guardada anteriormente

Escenario: Usuario completa lección de video
  DADO que el usuario está viendo un video
  CUANDO el video alcanza el 90% de reproducción
  ENTONCES la lección se marca como completada
  Y se muestra checkmark en sidebar
  Y se actualiza barra de progreso del curso
  Y se habilita siguiente lección si estaba bloqueada

Escenario: Usuario lee artículo
  DADO que la lección es tipo artículo
  CUANDO el usuario accede a la lección
  ENTONCES se muestra contenido renderizado desde Markdown
  Y se muestra tabla de contenidos si artículo >500 palabras
  Y se muestra tiempo estimado de lectura
  Y se muestra checkbox "Marcar como completado"

Escenario: Usuario toma notas
  DADO que el usuario está en una lección
  CUANDO hace click en pestaña "Mis notas"
  ENTONCES se muestra editor de texto
  Y puede escribir notas
  Y las notas se guardan automáticamente
  Y para videos se guarda timestamp actual

Escenario: Navegación entre lecciones
  DADO que el usuario completó una lección
  CUANDO hace click en "Siguiente lección"
  ENTONCES navega a la siguiente lección
  Y se carga el contenido correspondiente
  Y se actualiza sidebar destacando nueva lección

Escenario: Descargar recursos
  DADO que la lección tiene recursos descargables
  CUANDO el usuario hace click en "Descargar"
  ENTONCES se descarga el archivo
  Y se registra la descarga en analytics
```

---

## Dependencias

- Video CDN (Vimeo/YouTube/AWS S3 + CloudFront)
- PostgreSQL para metadata de lecciones
- Redis para caché de progreso
- S3 para archivos descargables

---

## Notas Técnicas

- Usar React Player o Video.js para reproductor
- Implementar PIP (Picture-in-Picture) para videos
- Considerar HLS para streaming adaptativo
- Implementar lazy loading de módulos en sidebar
- Guardar progreso en IndexedDB local como backup
- Usar Web Workers para procesamiento de Markdown pesado
- Implementar analytics de engagement (pausas, rewinds, abandono)

---

## Referencias

- Schema: `/backend/src/database/schemas/education.sql`
- API: `/backend/src/modules/courses/lessons.routes.ts`
- Frontend: `/frontend/src/pages/LessonPlayer.tsx`

---

## Tareas Técnicas

**Database:**
- [ ] Verificar schema education.lessons
- [ ] Tabla user_lesson_progress con campos: started_at, completed_at, last_position
- [ ] Tabla user_notes con FK a lesson
- [ ] Tabla user_bookmarks para marcadores

**Backend:**
- [ ] Endpoint GET /education/courses/:id/lessons/:lessonId
- [ ] Endpoint POST /education/lessons/:id/progress (guardar posición)
- [ ] Endpoint POST /education/lessons/:id/complete
- [ ] Endpoint GET/POST/PUT/DELETE /education/lessons/:id/notes
- [ ] Endpoint GET /education/lessons/:id/resources/:resourceId/download
- [ ] Implementar signed URLs para videos privados
- [ ] Rate limiting en download de recursos

**Frontend:**
- [ ] Crear LessonPlayerPage.tsx
- [ ] Crear componente VideoPlayer.tsx
- [ ] Crear componente ArticleViewer.tsx
- [ ] Crear componente LessonSidebar.tsx
- [ ] Crear componente NotesEditor.tsx
- [ ] Crear componente ResourcesList.tsx
- [ ] Implementar lessonStore para progreso
- [ ] Auto-save de posición cada 10s
- [ ] Atajos de teclado para navegación

**Tests:**
- [ ] Test unitario LessonService
- [ ] Test integración actualización de progreso
- [ ] Test E2E completar lección y desbloquear siguiente

---

**Creado por:** Requirements-Analyst
**Fecha:** 2025-12-05
**Última actualización:** 2025-12-05
