diff --git a/README.md b/README.md index 0b89d61..6248b86 100644 --- a/README.md +++ b/README.md @@ -186,6 +186,18 @@ El módulo SCORM (`src/scorm/scorm.ts`) implementa todas las funciones estándar > En desarrollo, `scorm-again` simula el `window.API` del LMS automáticamente. +### Integración con el flujo del juego + +`useSCORM` se inicializa en `App.tsx` al montar la aplicación. Al terminar las 10 preguntas (`handleGameEnd`): + +```ts +setScore(correctas * 10, 100, 0) // Escala el puntaje a 100 +setLessonStatus(aprobado ? 'passed' : 'failed') +finishSCORM() // Envía session_time y cierra +``` + +> El score se envía escalado a 100 para que coincida con el `masteryscore: 80` del manifiesto. + --- ## 🧩 Componente Button @@ -233,6 +245,12 @@ Para publicar en un LMS (Moodle, Cornerstone, etc.): ## 📋 Pendientes - [ ] Reemplazar categorías y preguntas de cultura general por el contenido real del cliente -- [ ] Integrar `setScore` y `completeLesson` con SCORM al finalizar la actividad -- [ ] Pruebas en LMS real (Moodle) - [ ] Definir diseño visual final (colores, logo, imágenes del cliente) + +## ✅ Resuelto + +- [x] Integrar `setScore` y `setLessonStatus` con SCORM al finalizar la actividad +- [x] Llamar `finishSCORM` al terminar el juego +- [x] Configurar `base: './'` en Vite para rutas relativas en Moodle +- [x] Rutas de audios relativas (`./audios/...`) para compatibilidad con LMS +- [x] Pruebas en LMS real (Moodle) diff --git a/src/App.tsx b/src/App.tsx index 425a19c..ad25f32 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,8 @@ import Cover from './components/screens/Cover' import Game from './components/screens/Game' import Result from './components/screens/Result' import { consumirIntento, intentosAgotados } from './hooks/useIntentos' +import { setScore, setLessonStatus, finishSCORM } from './scorm/scorm' +import { useSCORM } from './hooks/useSCORM' type Screen = 'cover' | 'game' | 'result' @@ -13,6 +15,7 @@ interface ResultState { } export default function App() { + useSCORM() const [screen, setScreen] = useState(() => intentosAgotados() ? 'result' : 'cover' ) @@ -26,7 +29,10 @@ export default function App() { setScreen('game') } - function handleGameEnd(aprobado: boolean) { + function handleGameEnd(aprobado: boolean, correctas: number) { + setScore(correctas * 10, 100, 0) + setLessonStatus(aprobado ? 'passed' : 'failed') + finishSCORM() setResultState({ aprobado, sinIntentos: intentosAgotados() }) setScreen('result') } diff --git a/src/audio/audios.ts b/src/audio/audios.ts index 28cde97..c61ae9b 100644 --- a/src/audio/audios.ts +++ b/src/audio/audios.ts @@ -1,6 +1,6 @@ export const AUDIOS = { - click: '/audios/click.mp3', - wheelSpin: '/audios/wheel-spin.mp3', - correct: '/audios/feedback-correct.mpeg', - incorrect: '/audios/feedback-incorrect.mpeg', + click: './audios/click.mp3', + wheelSpin: './audios/wheel-spin.mp3', + correct: './audios/feedback-correct.mpeg', + incorrect: './audios/feedback-incorrect.mpeg', } as const diff --git a/src/components/screens/Game.tsx b/src/components/screens/Game.tsx index 943222f..35cb84b 100644 --- a/src/components/screens/Game.tsx +++ b/src/components/screens/Game.tsx @@ -5,14 +5,14 @@ import QuestionModal from '../game/QuestionModal' import RuletaSVG from '../game/Ruleta/RuletaSVG' interface GameProps { - onEnd: (aprobado: boolean) => void + onEnd: (aprobado: boolean, correctas: number) => void } export default function Game({ onEnd }: GameProps) { const { estado, categorias, girar, responder, cerrarFeedback, MAX_PREGUNTAS } = useRuleta() useEffect(() => { - if (estado.completado) onEnd(estado.aprobado) + if (estado.completado) onEnd(estado.aprobado, estado.correctas) }, [estado.completado]) function handleGirar() { diff --git a/vite.config.js b/vite.config.js index 0616e59..e8b8247 100644 --- a/vite.config.js +++ b/vite.config.js @@ -4,4 +4,5 @@ import tailwindcss from '@tailwindcss/vite' export default defineConfig({ plugins: [react(), tailwindcss()], + base: './', })