modificaciones de scorm reporte de calificacion y cambio de rutas absolutas a relativas

This commit is contained in:
2026-07-25 02:03:53 -06:00
parent 3ce44d7aac
commit ba8f7e5059
5 changed files with 34 additions and 9 deletions
+20 -2
View File
@@ -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. > 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 ## 🧩 Componente Button
@@ -233,6 +245,12 @@ Para publicar en un LMS (Moodle, Cornerstone, etc.):
## 📋 Pendientes ## 📋 Pendientes
- [ ] Reemplazar categorías y preguntas de cultura general por el contenido real del cliente - [ ] 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) - [ ] 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)
+7 -1
View File
@@ -4,6 +4,8 @@ import Cover from './components/screens/Cover'
import Game from './components/screens/Game' import Game from './components/screens/Game'
import Result from './components/screens/Result' import Result from './components/screens/Result'
import { consumirIntento, intentosAgotados } from './hooks/useIntentos' import { consumirIntento, intentosAgotados } from './hooks/useIntentos'
import { setScore, setLessonStatus, finishSCORM } from './scorm/scorm'
import { useSCORM } from './hooks/useSCORM'
type Screen = 'cover' | 'game' | 'result' type Screen = 'cover' | 'game' | 'result'
@@ -13,6 +15,7 @@ interface ResultState {
} }
export default function App() { export default function App() {
useSCORM()
const [screen, setScreen] = useState<Screen>(() => const [screen, setScreen] = useState<Screen>(() =>
intentosAgotados() ? 'result' : 'cover' intentosAgotados() ? 'result' : 'cover'
) )
@@ -26,7 +29,10 @@ export default function App() {
setScreen('game') 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() }) setResultState({ aprobado, sinIntentos: intentosAgotados() })
setScreen('result') setScreen('result')
} }
+4 -4
View File
@@ -1,6 +1,6 @@
export const AUDIOS = { export const AUDIOS = {
click: '/audios/click.mp3', click: './audios/click.mp3',
wheelSpin: '/audios/wheel-spin.mp3', wheelSpin: './audios/wheel-spin.mp3',
correct: '/audios/feedback-correct.mpeg', correct: './audios/feedback-correct.mpeg',
incorrect: '/audios/feedback-incorrect.mpeg', incorrect: './audios/feedback-incorrect.mpeg',
} as const } as const
+2 -2
View File
@@ -5,14 +5,14 @@ import QuestionModal from '../game/QuestionModal'
import RuletaSVG from '../game/Ruleta/RuletaSVG' import RuletaSVG from '../game/Ruleta/RuletaSVG'
interface GameProps { interface GameProps {
onEnd: (aprobado: boolean) => void onEnd: (aprobado: boolean, correctas: number) => void
} }
export default function Game({ onEnd }: GameProps) { export default function Game({ onEnd }: GameProps) {
const { estado, categorias, girar, responder, cerrarFeedback, MAX_PREGUNTAS } = useRuleta() const { estado, categorias, girar, responder, cerrarFeedback, MAX_PREGUNTAS } = useRuleta()
useEffect(() => { useEffect(() => {
if (estado.completado) onEnd(estado.aprobado) if (estado.completado) onEnd(estado.aprobado, estado.correctas)
}, [estado.completado]) }, [estado.completado])
function handleGirar() { function handleGirar() {
+1
View File
@@ -4,4 +4,5 @@ import tailwindcss from '@tailwindcss/vite'
export default defineConfig({ export default defineConfig({
plugins: [react(), tailwindcss()], plugins: [react(), tailwindcss()],
base: './',
}) })