# Tutoria360 — Documentación para desarrolladores

Demo funcional de la plataforma educativa **"Aprende Viajando por México"**.
Su objetivo es enseñarle al equipo la idea completa y servir de **base técnica**:
una *cáscara* (plataforma) que ya resuelve mapa, progresión, recompensas, analítica
y un *contrato* claro para que el equipo conecte sus juegos.

> Resumen en una frase: **el equipo no reescribe la plataforma; produce juegos que
> cumplen el contrato (`CONTRATO.md`) y se registran en un catálogo.**

---

## 1. Cómo correrlo localmente

Requiere un servidor HTTP (por los módulos ES y el Service Worker). No necesita build.

```bash
cd Tutoria360-Demo
node serve.js          # sirve en http://localhost:8090 (soporta Range para video)
# alternativa: npx serve  /  python3 -m http.server
```

Abrir `http://localhost:8090`. **Código de acceso (PIN): `6100`** (ver §10).

> `serve.js` es solo para desarrollo local. En producción se sirven los archivos
> estáticos tal cual (Netlify, Azure, etc.).

---

## 2. Arquitectura: cáscara + juegos

```
┌──────────────────────── CÁSCARA (este repo) ────────────────────────┐
│  Mapa de México · progresión por dominio · economía (monedas/        │
│  estrellas) · recompensas/tienda · pasaportes · motor analítico ·     │
│  PWA/offline · PIN                                                    │
│                                                                       │
│   ┌─────────── CONTRATO (postMessage) ───────────┐                    │
│   │  Cada juego corre en un <iframe> y se comunica │                   │
│   │  con la cáscara con mensajes (ver CONTRATO.md) │                   │
│   └────────────────────────────────────────────────┘                  │
│         ▲                         ▲                                    │
│   juegos NUEVOS            juegos EXISTENTES (Azure, "legacy")          │
│   (cumplen contrato)       embebidos con barra "modo demo"             │
└───────────────────────────────────────────────────────────────────────┘
```

- **Juegos nuevos**: hablan el contrato → la cáscara sabe cuándo se ganó la estrella, mide tiempo/errores, etc. (Ejemplos: `games/ejemplo-suma`, `games/ejemplo-caza-sonidos`.)
- **Juegos legacy** (los ~174 de Azure ya desarrollados): aún NO hablan el contrato. Se embeben y la cáscara muestra una barra **"modo demo"** para marcar el dominio a mano. Cuando el equipo les agregue `GAME_COMPLETE`, se quita `legacy:true` y todo es automático.

---

## 3. Estructura de carpetas

```
index.html                 Punto de entrada (carga js/app.js como módulo)
juegos.html                Catálogo jugable de los 174 juegos de Azure (modo demo/distribución)
serve.js                   Servidor estático local (dev) con soporte Range (video)
manifest.webmanifest       Manifiesto PWA
sw.js                      Service Worker (offline-first). Subir CACHE al cambiar archivos
CONTRATO.md                Contrato del juego (lo único que necesita el equipo de juegos)
DOCUMENTACION.md           Este documento

css/styles.css             Todos los estilos

js/
  app.js                   Orquestador: vistas, router, mapa, tienda, pasaporte, PIN
  state.js                 Estado + persistencia (localStorage seguro)
  gamehost.js              Puente del CONTRATO (postMessage) + economía + dominio + dificultad
  analytics.js             Motor analítico (eventos + veredictos + resumen)
  data/
    estados.js             32 estados + monumentos (orden de la ruta)
    catalogo.js            Reparte los juegos en los 32 estados (5–6 por estado)
    juegos_reales.js       AUTO-GENERADO: los 174 juegos de Azure mapeados a materia/tema
    pasaportes.js          AUTO-GENERADO: posición del recuadro de foto en cada pasaporte
    programa.js            Programa SEP completo: 160 temas (preescolar→6°), estado y cobertura
    secuencias.js          Secuencias de juegos por tema (un tema = N juegos encadenados)

assets/
  mexico.svg               Mapa SVG de México (Simplemaps, libre uso comercial)
  nav/*.png                Íconos 3D de la barra inferior
  ninos/nino1..20.png      20 avatares (recortes con fondo transparente)
  pasaportes/<ID>.png      32 pasaportes (uno por estado)
  svg/                     explorador (placeholder caminante), sombrero, moneda, estrella, icono

games/
  ejemplo-suma/            Juego de referencia (contrato) — Matemáticas
  ejemplo-caza-sonidos/    Juego de referencia (contrato) — Lenguaje

recompensas/
  caricatura.html          Reproductor (en prod: YouTube; en local: video)
  cuento-mexico.html       Libro interactivo (autocontenido)
  axolote.html             Caricatura interactiva educativa
  aventuras-mar.html       Caricatura interactiva educativa
  leyendas-oaxaca.html     Libro de 6 páginas

teacher/
  dashboard.html           Tablero del maestro (motor analítico, por niño)
  cobertura.html           Cobertura del Programa SEP (institucional): 160 temas, brechas

docs/                      Documentación de diseño y producción de contenido
  GDD_ESTANDAR.md          Estándar de GDD: 10 características + contrato + IDs + assets
  gdd/                     GDD por tema (un .md por tema con cada juego + sus assets)
    README.md              Índice de los GDD por bloque
    A-prerrequisitos/      Bloque A: 11 temas / 56 juegos documentados
  pdf/                     PDFs de avance por bloque (generados desde los datos)
  Catalogo-Juegos.csv      Los 174 juegos (materia, tema, URL de Azure) para repartir
```

---

## 4. Modelo de estado (`js/state.js`)

Todo el progreso vive en `localStorage` (clave `tutoria360_demo_v1`), envuelto en
`try/catch` (en panes de preview/incógnito el acceso directo revienta).

```js
{
  perfil: { idNino, nombre, grado, escuela, avatar } | null,
  monedas: number,          // arranca en 100 (bienvenida)
  estrellas: number,        // estrellas de dominio ganadas
  completados: { [gameId]: { estrella, intentos, aciertos, errores, reintentos, tiempoMs, mejorTiempo } },
  comprados: [ id_tienda ],
  equipado: "sombrero" | null,
  eventos: [ { t, tipo, ... } ]   // telemetría cruda
}
```

API: `get()`, `set(parcial)`, `guardar()`, `reset()`. El análisis corre sobre
`idNino` (seudónimo), NUNCA sobre el nombre real.

---

## 5. El contrato del juego (resumen — detalle en `CONTRATO.md`)

La cáscara → juego: `TUTORIA360_INIT { idNino, gameId, tema, dificultad, locale, audioOn }`.
Juego → cáscara (`window.parent.postMessage`):

| Evento | Mensaje |
|---|---|
| Listo | `GAME_READY` |
| Empieza | `GAME_START` |
| Avance | `GAME_PROGRESS { aciertos, errores }` |
| Abandona | `GAME_ABANDON` |
| **Termina** | `GAME_COMPLETE { exito, estrella, aciertos, errores, reintentos, tiempoMs }` |

**Regla de oro:** la cáscara solo desbloquea el siguiente tema si `estrella === true`
(avance por dominio). `gamehost.js` aplica monedas, estrellas, candado, dificultad
adaptativa y telemetría. El juego solo manda mensajes.

### Cómo agregar un juego nuevo
1. Construir el juego (HTML o Unity/WebGL) que cumpla el contrato. Copiar `games/ejemplo-suma/` como molde.
2. Registrarlo en `js/data/catalogo.js` / `juegos_reales.js` con `{ materia, tema, src, dificultad, tiempoMs }` (sin `legacy:true`).
3. Aparece solo en el mapa, en el estado/tema que le toca por orden.

---

## 6. Catálogo y distribución (`js/data/`)

- `estados.js`: 32 estados en orden de ruta + su monumento.
- `juegos_reales.js`: los 174 juegos de Azure mapeados a `{materia, tema, src}`. **Auto-generado** (ver §12 cómo regenerarlo).
- `catalogo.js`: `construirCatalogo()` toma 2 juegos del contrato + los 174 reales y los reparte en 32 estados (5 o 6 por estado). `rutaPlana()` da la lista en orden.
- IDs de juego: `${ESTADO}-${MAT}-${i}` (ej. `BCN-MAT-1`). Los juegos de ejemplo dependen de ese ID (`games/ejemplo-suma` usa `GAME_ID = "BCN-MAT-1"`).

> Hoy el reparto es temático/de muestra. Para producción conviene reordenarlo según
> el temario pedagógico real (preescolar → 6°).

---

## 6.5 Programa SEP y plan de contenido (`programa.js`, `secuencias.js`, `docs/gdd/`)

Además de la cáscara, el repo documenta **qué juegos hay que construir** para cubrir
el programa oficial:

- **`js/data/programa.js`** — los **160 temas** del programa (preescolar→6°), cada uno con
  `{ n, nivel, materia, area, tema, sep, tier, prereq, estado, juegosEst, tieneJuego }`.
  `estado`: `EXISTE | PARCIAL | FALTA | FUERA`. `tieneJuego`: a qué juego construido se mapea.
- **`teacher/cobertura.html`** — tablero institucional que lee `programa.js`: muestra la
  cobertura (24/160 temas con juego), las brechas y "qué agregar". Diferencia de SEP vs
  enriquecimiento ("Más allá").
- **`js/data/secuencias.js`** — la **secuencia de juegos por tema** (un tema = N juegos
  encadenados por dominio). Cada juego: `{ orden, nombre, sub, motor, estado }`.
  Enlaza a `programa.js` por el número de tema `n`.
- **`docs/GDD_ESTANDAR.md` + `docs/gdd/`** — el GDD de cada juego (ID `T{n}-J{orden}`,
  mecánica, controles, audio, criterios de aceptación) **+ su lista de assets**.
- **`docs/pdf/`** — PDF de avance por bloque (resumen + estado + análisis de gaps),
  generado desde `programa.js` + `secuencias.js`.

> Flujo de producción: **programa.js** (qué temas) → **secuencias.js** (qué juegos por tema)
> → **docs/gdd/** (cómo es cada juego + assets) → construir el juego que cumpla `CONTRATO.md`
> → actualizar su `estado` a `construido` → el tablero y el PDF reflejan el avance.

## 7. Mapa (`app.js` → `pintarMapa`)

- Carga `assets/mexico.svg` y colorea cada estado con una paleta de identidad.
- Estatus por estado: ⭐ conquistado (todas sus estrellas), 🚩 en progreso, sin marca = por jugar. **Todos los estados son entrables**; dentro de cada uno los temas siguen en orden por dominio.
- **Caminante**: personaje (el avatar elegido) que se para en el estado actual y "viaja" animado al siguiente al conquistar uno. Intercambiable por sprite-sheet (ver `kidEl()` y `PERSONAJE`).
- Decoraciones del océano (emojis) + tarjetas flotantes (título, leyenda, "sigue aprendiendo", progreso).

---

## 8. Avatares y pasaportes

- **Avatares**: `assets/ninos/nino1..20.png`. El niño elige uno en el login; se usa como caminante, foto del pasaporte y mini-avatar del header. Para cambiarlos/agregarlos, reemplazar los PNG (mismos nombres) y ajustar `AVATARES` en `app.js`.
- **Pasaportes**: `assets/pasaportes/<ID>.png` (32, uno por estado). En la vista Pasaporte, el avatar se incrusta en el recuadro blanco (posición uniforme `FP` en `vistaPasaporte`). Conquistado → ⭐.

---

## 9. Recompensas / Tienda (`app.js` → `TIENDA`, `vistaTienda`, `abrirVisor`)

Cada artículo: `{ id, tipo, nombre, costo, emoji, src?, verbo?, cosmetico? }`.
- Con `src`: al comprarlo se abre a pantalla completa (`abrirVisor`) — libros/caricaturas/video.
- `cosmetico: "sombrero"`: equipable. Al ponerlo, se superpone en el caminante (`equipado` en el estado).
- Las **estrellas de dominio NO se compran**; solo monedas.

Para agregar una recompensa: añadir un objeto a `TIENDA` y crear su `recompensas/<archivo>.html`.

---

## 10. PIN de acceso

En `app.js`: `const PIN = "6100";`. Pantalla de candado antes de entrar; se recuerda
por sesión (`sessionStorage`). Es un candado **ligero** (client-side), suficiente para
un demo privado; para seguridad real usar protección a nivel servidor (Netlify Pro / auth).

---

## 11. Motor analítico (`js/analytics.js` + `teacher/dashboard.html`)

- `registrar(tipo, datos)`: guarda eventos con timestamp.
- `veredicto(reg, tiempoEsperado)`: matriz tiempo × precisión → **FORTALEZA / EN CAMINO / DEBILIDAD / FRUSTRACIÓN**.
- `resumen()`: KPIs (iniciados, terminados, abandonos, estrellas, % de abandono).
- El **tablero del maestro** (`teacher/dashboard.html`) lo muestra. Acceso discreto desde el engrane ⚙️ (no está en la navegación del niño).
- **Privacidad (LFPDPPP)**: solo nombre de pila + grado + escuela; el análisis usa el seudónimo `idNino`. Para uso real: consentimiento del tutor, acceso por rol, cifrado, sin uso comercial de datos de menores.

---

## 12. Activos auto-generados (scripts)

Algunas piezas se generaron con Python (PIL/numpy/scipy) a partir de imágenes:
- `assets/ninos/*` (recorte de avatares con transparencia)
- `assets/pasaportes/*` + `js/data/pasaportes.js`
- `assets/nav/*` (íconos de la barra)
- `js/data/juegos_reales.js` (enumerando los juegos de `https://www.ari.group/aprende-jugando` → URLs de Azure)

> Estos scripts no están versionados (eran one-off). Si se necesita regenerar, ver el
> historial de la conversación o recrearlos: la fuente de juegos es la página de Aprende
> Jugando; los juegos viven en `https://aidigital.z19.web.core.windows.net/jugando/...`.

---

## 13. PWA / Offline (`sw.js`, `manifest.webmanifest`)

- App instalable (manifiesto + service worker). En móvil: "Agregar a pantalla de inicio".
- `sw.js` precachea la cáscara (offline-first). El **video .mp4 NO se cachea** (se transmite por red). Los juegos de Azure necesitan internet.
- **IMPORTANTE:** al cambiar cualquier archivo, subir la versión `const CACHE = "tutoria360-vN"` en `sw.js` para que los navegadores tomen lo nuevo.

---

## 14. Despliegue

- **Estático** (Netlify / Cloudflare Pages / Azure Static Web Apps). Requiere **HTTPS** (PWA + iframes de Azure son https).
- **Video** (822 MB): NO va en hosting estático ni en git → YouTube/Vimeo (no listado) o Azure Blob; `recompensas/caricatura.html` lo apunta por ID/URL.
- **Dominio**: `www.tutoria360.mx` (GoDaddy → DNS apuntando al host; Netlify emite SSL).
- Ver `PUBLICAR.md` para el paso a paso.

---

## 15. Camino a "app"

1. **PWA instalable** (gratis): pulir íconos del manifiesto; se instala desde el sitio.
2. **Google Play**: empaquetar con **PWABuilder** (TWA) apuntando a tutoria360.mx. Cuenta dev ~$25 USD.
3. **App Store**: envolver con **Capacitor**. Cuenta Apple $99/año.

---

## 16. Pendientes / roadmap sugerido

- Reordenar el catálogo según el temario pedagógico real (preescolar → 6°).
- Que el equipo agregue `GAME_COMPLETE` a los juegos de Azure (quitar `legacy`).
- Backend real para la analítica (hoy es client-side/localStorage) + privacidad de menores.
- Secciones "Retos", "Amigos", "Experiencias" (hoy placeholders).
- Personaje caminante con sprite-sheet animado (hoy pose fija con brinco).
- Íconos PNG del manifiesto para instalación/tiendas.
```
