2025-09-24 11:59:46 -06:00
< style >
. fake {
2026-07-01 15:47:43 -06:00
background-image : url ( 'img/bg11.jpg' ) ;
2025-09-24 11:59:46 -06:00
background-size : cover ;
background-repeat : no-repeat ;
}
2025-09-24 22:51:53 -06:00
. hr-style {
opacity : 1 ;
width : 52 % ;
}
2025-09-24 11:59:46 -06:00
. wruleta {
transition : transform 4 s cubic-bezier ( 0.25 , 0.1 , 0.25 , 1 ) ;
cursor : pointer ;
}
. wruleta . spinning {
pointer-events : none ;
}
# spin-btn {
border : none ;
color : white ;
padding : 15 px 30 px ;
font-size : 18 px ;
font-weight : bold ;
2025-09-24 22:51:53 -06:00
border-radius : 12 px ;
2025-09-24 11:59:46 -06:00
cursor : pointer ;
box-shadow : 0 4 px 15 px rgba ( 0 , 0 , 0 , 0.2 ) ;
transition : all 0.3 s ease ;
}
# spin-btn : hover {
transform : translateY ( -2 px ) ;
box-shadow : 0 6 px 20 px rgba ( 0 , 0 , 0 , 0.3 ) ;
}
# spin-btn : disabled {
opacity : 0.6 ;
cursor : not-allowed ;
transform : none ;
}
. avance {
width : calc ( 100 % / 6 ) ;
}
. avance img {
width : 70 % ;
aspect-ratio : 16 / 9 ;
object-fit : contain ;
filter : grayscale ( 1 ) ;
transition : all 0.5 s ease-in-out ;
}
. avance img . visited {
filter : grayscale ( 0 ) ;
}
. no-overflow {
overflow : hidden ;
}
/* Estilos para SweetAlert de preguntas */
. swal2-popup {
border-radius : 20 px !important ;
border : 4 px solid #28a745 !important ;
}
. swal2-title {
color : #2c5530 !important ;
font-weight : bold !important ;
font-size : 1.3 rem !important ;
}
. opcion-btn {
background : #f8f9fa !important ;
color : #333 !important ;
border : 1 px solid #dee2e6 !important ;
border-radius : 8 px !important ;
padding : 12 px 20 px !important ;
margin-bottom : 10 px !important ;
font-weight : 500 !important ;
position : relative !important ;
transition : all 0.3 s ease !important ;
}
. opcion-btn : hover ,
. opcion-btn : focus ,
. opcion-btn . selected {
transform : translateY ( -2 px ) !important ;
box-shadow : 0 4 px 12 px rgba ( 0 , 0 , 0 , 0.1 ) !important ;
}
. opcion-btn :: before {
content : attr ( data - letter ) !important ;
position : absolute !important ;
left : 0 px !important ;
top : 0 % !important ;
background : #28a745 !important ;
color : white !important ;
width : 28 px !important ;
height : 100 % !important ;
border-radius : 6 px 0 px 0 px 6 px !important ;
display : flex !important ;
align-items : center !important ;
justify-content : center !important ;
font-weight : bold !important ;
font-size : 14 px !important ;
transition : background-color 0.3 s ease !important ;
}
. opcion-btn : hover :: before ,
. opcion-btn . selected :: before {
background : #8e44ad !important ;
}
. opcion-btn span {
margin-left : 35 px !important ;
text-align : left !important ;
display : block !important ;
}
2026-07-01 15:47:43 -06:00
. pop_html_style {
2025-09-24 11:59:46 -06:00
width : 100 % ;
}
@ media ( min-width : 768px ) {
2026-07-01 15:47:43 -06:00
. pop_html_style {
2025-09-24 11:59:46 -06:00
width : 700 px ;
}
}
< / style >
< div class = "page-sco py-2 py-md-0 h-100" >
< div class = "container h-100 m-0 g-0 p-0" >
< div class = "row justify-content-center align-items-center h-100 m-0 g-0 p-0" >
< div class = "col-12 m-0 g-0 p-0" >
< div class = "row justify-content-center m-0 g-0 p-0 animate__animated animate__fadeInDown" >
2025-09-24 22:51:53 -06:00
< div class = "col-7 mb-3" >
2025-09-24 11:59:46 -06:00
< h2 class = "text-center fw-bold text-primary" > Alimentación y medicación< / h2 >
< hr class = "border border-3 border-verde-oscuro hr-style mx-auto my-0" / >
< / div >
< / div >
< div class = "row animate__animated animate__slideInLeft" >
< div class = "col-7" >
2026-07-01 15:47:43 -06:00
< div class = "d-flex flex-row align-items-center bg-morado-claro py-3 text-white rounded-15" style = "border-radius: 15px; border-top-left-radius: 0; border-bottom-left-radius: 0" >
2025-09-24 11:59:46 -06:00
< div class = "mx-3" >
< img src = "img/2.1.png" alt = "" class = "img-fluid" / >
< / div >
2026-07-01 15:47:43 -06:00
< div > < b > Instrucciones:< / b > Da clic en la ruleta y contesta correctamente la pregunta acerca de la alimentación o medicación en diálisis peritoneal para ganar los puntos.< / div >
2025-09-24 11:59:46 -06:00
< / div >
< / div >
< / div >
< div class = "row justify-content-center align-items-center animate__animated animate__slideInRight" >
< div class = "col-6" >
2025-09-24 22:51:53 -06:00
< div class = "card custom-card bg-secondary border-0 shadow" >
2025-09-24 11:59:46 -06:00
< div class = "card-body" >
< div class = "row justify-content-center" >
< div class = "col-4 text-center" >
< img src = "img/ruleta/per1.png" alt = "" class = "img-fluid" / >
< / div >
< div class = "col-8 text-white text-center" >
2025-09-25 13:03:23 -06:00
< h4 > Puntos acumulados:< / h4 >
< h2 class = "puntos" > 0< / h2 >
2025-09-24 11:59:46 -06:00
< div class = "card flat" >
< img src = "img/ruleta/progress.png" alt = "" class = "img-fluid" / >
2025-09-24 22:51:53 -06:00
< div class = "wavance position-absolute d-flex flex-row align-items-center justify-content-start w-100" style = "top: 22%" >
2025-09-24 11:59:46 -06:00
< div class = "avance" > < img src = "img/ruleta/pr.png" class = "img-fluid" alt = "" / > < / div >
< div class = "avance" > < img src = "img/ruleta/pr.png" class = "img-fluid" alt = "" / > < / div >
< div class = "avance" > < img src = "img/ruleta/pr.png" class = "img-fluid" alt = "" / > < / div >
< div class = "avance" > < img src = "img/ruleta/pr.png" class = "img-fluid" alt = "" / > < / div >
< div class = "avance" > < img src = "img/ruleta/pr.png" class = "img-fluid" alt = "" / > < / div >
< div class = "avance" > < img src = "img/ruleta/pr.png" class = "img-fluid" alt = "" / > < / div >
< / div >
< / div >
< / div >
2025-09-24 22:51:53 -06:00
< / div >
< / div >
< / div >
< div class = "position-relative w-100" >
< div class = "row" >
< div class = "col-12 text-center" >
< div class = "mt-3" >
2025-09-25 13:03:23 -06:00
< button id = "spin-btn" class = "bg-verde-oscuro text-white border border-4 border-white animate__animated animate__pulse animate__infinite" > ¡GIRAR RULETA!< / button >
2025-09-24 11:59:46 -06:00
< / div >
< / div >
< / div >
< / div >
< / div >
2026-07-01 15:47:43 -06:00
< div class = "col-4 text-center" style = "margin-top: -30px" >
2025-09-24 11:59:46 -06:00
< div class = "card flat justify-content-center align-items-center d-inline-flex" >
< div class = "indicador position-absolute start-50 translate-middle-x" style = "z-index: 9999 !important; top: -1em" >
< img src = "img/ruleta/indicador.png" alt = "" style = "transform: rotate(90deg)" / >
< / div >
< div class = "wruleta z-2" id = "ruleta-wheel" >
< img src = "img/ruleta/ruleta.png" alt = "" / >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< / div >
< div class = "d-none" >
< div id = "pop0" >
< div class = "container-fluid" >
2026-07-01 15:47:43 -06:00
< div class = "w-100 text-center" >
< img src = "img/3.5.png" class = "img-fluid" / >
2025-09-24 11:59:46 -06:00
< / div >
< div class = "row justify-content-center" >
< div class = "col-12 text-center mb-2" >
< h3 class = "text-secondary-dark fw-bold" > ¡Bien hecho!< / h3 >
< / div >
< div class = "col-12 text-center" >
< p class = "mb-0" > Has concluido la actividad.< / p >
< / div >
< / div >
< / div >
< / div >
< / div >
< script >
$ ( function ( ) {
2026-07-01 15:47:43 -06:00
'use strict' ;
$ ( '.wrap-course-content' ) . addClass ( 'fake' ) ;
2025-09-24 11:59:46 -06:00
// Puntajes de la ruleta en orden horario (empezando desde arriba)
const puntajes = [ 100 , 200 , 300 , 400 , 500 , 600 , 700 , 600 , 500 , 400 , 300 , 200 ] ;
let isSpinning = false ;
let totalPuntos = 0 ;
let rotacionActual = 0 ;
let girosRealizados = 0 ;
const maxGiros = 6 ;
2026-07-01 15:47:43 -06:00
const ruletaWheel = document . getElementById ( 'ruleta-wheel' ) ;
const spinBtn = document . getElementById ( 'spin-btn' ) ;
const puntosDisplay = document . querySelector ( '.puntos' ) ;
const avanceImages = document . querySelectorAll ( '.avance img' ) ;
2025-09-24 11:59:46 -06:00
function girarRuleta ( ) {
if ( isSpinning || girosRealizados >= maxGiros ) return ;
isSpinning = true ;
spinBtn . disabled = true ;
2026-07-01 15:47:43 -06:00
spinBtn . classList . remove ( 'animate__animated' , 'animate__pulse' , 'animate__infinite' ) ;
ruletaWheel . classList . add ( 'spinning' ) ;
document . getElementById ( 'coursenav-main-content' ) . classList . add ( 'no-overflow' ) ;
2025-09-24 11:59:46 -06:00
// Mínimo 3 vueltas + ángulo aleatorio (siempre hacia la derecha)
const vueltas = 3 + Math . random ( ) * 2 ; // 3-5 vueltas
const anguloFinal = Math . random ( ) * 360 ;
const rotacionTotal = rotacionActual + vueltas * 360 + anguloFinal ;
// Aplicar rotación
ruletaWheel . style . transform = ` rotate( ${ rotacionTotal } deg) ` ;
rotacionActual = rotacionTotal ;
// Calcular puntaje después de la animación
setTimeout ( ( ) => {
const anguloNormalizado = rotacionActual % 360 ;
const segmento = Math . floor ( ( anguloNormalizado + 15 ) / 30 ) % 12 ;
const puntajeObtenido = puntajes [ segmento ] ;
// Remover puntos automáticos - solo se ganan si responde correctamente
// Mostrar pregunta
setTimeout ( ( ) => {
mostrarPregunta ( puntajeObtenido ) ;
} , 500 ) ;
} , 4000 ) ;
}
2026-07-01 15:47:43 -06:00
spinBtn . addEventListener ( 'click' , girarRuleta ) ;
2025-09-24 11:59:46 -06:00
2026-07-01 15:47:43 -06:00
const bad = CourseNav . createSound ( 'audio/feedback-incorrect.mpeg' ) ;
const good = CourseNav . createSound ( 'audio/feedback-correct.mpeg' ) ;
2025-09-24 11:59:46 -06:00
2026-07-01 15:47:43 -06:00
const urlExcelFile = 'Actividades_Rotafolio_Vantive.xlsx' ;
2025-09-24 11:59:46 -06:00
function readExcelFile ( url , callback ) {
var xhr = new XMLHttpRequest ( ) ;
2026-07-01 15:47:43 -06:00
xhr . open ( 'GET' , url , true ) ;
xhr . responseType = 'arraybuffer' ;
2025-09-24 11:59:46 -06:00
xhr . onload = function ( e ) {
var arrayBuffer = xhr . response ;
var data = new Uint8Array ( arrayBuffer ) ;
2026-07-01 15:47:43 -06:00
var workbook = XLSX . read ( data , { type : 'array' } ) ;
2025-09-24 11:59:46 -06:00
var result = { } ;
workbook . SheetNames . forEach ( ( sheetName ) => {
var sheet = workbook . Sheets [ sheetName ] ;
result [ sheetName ] = XLSX . utils . sheet _to _json ( sheet ) ;
} ) ;
callback ( result ) ;
} ;
xhr . send ( ) ;
}
function procesarPreguntas ( data ) {
const preguntas = data . map ( ( fila ) => {
const opciones = [ ] ;
Object . keys ( fila ) . forEach ( ( key ) => {
2026-07-01 15:47:43 -06:00
if ( key . startsWith ( 'opcion' ) ) {
2025-09-24 11:59:46 -06:00
opciones . push ( {
text : fila [ key ] . trim ( ) ,
2026-07-01 15:47:43 -06:00
correct : key === 'opcion_c' ,
2025-09-24 11:59:46 -06:00
} ) ;
}
} ) ;
return {
pregunta : fila . pregunta . trim ( ) ,
opciones : opciones ,
2026-07-01 15:47:43 -06:00
retroalimentacion _correcta : fila . retroalimentacion _correcta ? fila . retroalimentacion _correcta . trim ( ) : '' ,
retroalimentacion _incorrecta : fila . retroalimentacion _incorrecta ? fila . retroalimentacion _incorrecta . trim ( ) : '' ,
2025-09-24 11:59:46 -06:00
} ;
} ) ;
return preguntas ;
}
function shuffleArray ( array ) {
for ( let i = array . length - 1 ; i > 0 ; i -- ) {
const j = Math . floor ( Math . random ( ) * ( i + 1 ) ) ;
[ array [ i ] , array [ j ] ] = [ array [ j ] , array [ i ] ] ;
}
return array ;
}
// Variables para preguntas
let questions = [ ] ;
let preguntasUsadas = [ ] ;
function mostrarPregunta ( puntajeEnJuego ) {
if ( questions . length === 0 ) {
2026-07-01 15:47:43 -06:00
console . error ( 'No hay preguntas cargadas' ) ;
2025-09-24 11:59:46 -06:00
return ;
}
// Seleccionar pregunta aleatoria no usada
const preguntasDisponibles = questions . filter ( ( _ , index ) => ! preguntasUsadas . includes ( index ) ) ;
if ( preguntasDisponibles . length === 0 ) {
preguntasUsadas = [ ] ; // Reiniciar si se agotaron
}
const preguntaIndex = Math . floor ( Math . random ( ) * preguntasDisponibles . length ) ;
const pregunta = preguntasDisponibles [ preguntaIndex ] ;
const originalIndex = questions . indexOf ( pregunta ) ;
preguntasUsadas . push ( originalIndex ) ;
// Crear HTML para opciones
2026-07-01 15:47:43 -06:00
let opcionesHTML = '' ;
2025-09-24 11:59:46 -06:00
pregunta . opciones . forEach ( ( opcion , index ) => {
const letra = String . fromCharCode ( 97 + index ) ; // 97 = 'a'
opcionesHTML += ` <button class="opcion-btn d-block w-100" data-correct=" ${ opcion . correct } " data-letter=" ${ letra } "><span> ${ opcion . text } </span></button> ` ;
} ) ;
Swal . fire ( {
title : pregunta . pregunta ,
2026-07-01 15:47:43 -06:00
html : ` <div class="text-start mb-3"> ${ opcionesHTML } </div>
<div class="col-12 text-center">
<p class="small mb-0">"Estos son casos hipotéticos basados en las referencias bibliográficas."</p>
</div>
` ,
2025-09-24 11:59:46 -06:00
showConfirmButton : false ,
allowOutsideClick : false ,
target : document . getElementById ( 'wrap-course-content' ) ,
customClass : {
2026-07-01 15:47:43 -06:00
popup : 'pop_html_style border border-3 border-primary rounded-4' ,
confirmButton : 'btn text-white bg-primary amor fw-semibold animate__animated animate__pulse animate__infinite' ,
2025-09-24 11:59:46 -06:00
} ,
didOpen : ( ) => {
2026-07-01 15:47:43 -06:00
document . querySelectorAll ( '.opcion-btn' ) . forEach ( ( btn ) => {
btn . addEventListener ( 'mouseenter' , ( ) => {
btn . classList . add ( 'selected' ) ;
2025-09-24 11:59:46 -06:00
} ) ;
2026-07-01 15:47:43 -06:00
btn . addEventListener ( 'mouseleave' , ( ) => {
btn . classList . remove ( 'selected' ) ;
2025-09-24 11:59:46 -06:00
} ) ;
2026-07-01 15:47:43 -06:00
btn . addEventListener ( 'click' , ( e ) => {
const target = e . target . closest ( '.opcion-btn' ) ;
const esCorrecta = target . dataset . correct === 'true' ;
2025-09-24 11:59:46 -06:00
manejarRespuesta ( esCorrecta , puntajeEnJuego , pregunta ) ;
} ) ;
} ) ;
} ,
} ) ;
}
function manejarRespuesta ( esCorrecta , puntajeEnJuego , pregunta ) {
if ( esCorrecta ) {
2025-09-24 22:51:53 -06:00
CourseNav . audioController . stopAllSoundsAndPlay ( good ) ;
2025-09-24 11:59:46 -06:00
totalPuntos += puntajeEnJuego ;
puntosDisplay . textContent = totalPuntos ;
2025-09-24 22:51:53 -06:00
// Marcar imagen como visitada solo cuando responde correctamente
if ( girosRealizados < maxGiros ) {
2026-07-01 15:47:43 -06:00
avanceImages [ girosRealizados ] . classList . add ( 'visited' ) ;
2025-09-24 22:51:53 -06:00
girosRealizados ++ ;
}
2025-09-24 11:59:46 -06:00
Swal . fire ( {
2026-07-01 15:47:43 -06:00
title : '¡Correcto!' ,
2025-09-24 11:59:46 -06:00
text : ` Has ganado ${ puntajeEnJuego } puntos. ${ pregunta . retroalimentacion _correcta } ` ,
2026-07-01 15:47:43 -06:00
icon : 'success' ,
2025-09-24 11:59:46 -06:00
target : document . getElementById ( 'wrap-course-content' ) ,
2026-07-01 15:47:43 -06:00
confirmButtonText : 'Continuar' ,
2025-09-25 13:03:23 -06:00
} ) . then ( ( ) => {
finalizarTurno ( ) ;
if ( girosRealizados < maxGiros ) {
2026-07-01 15:47:43 -06:00
spinBtn . classList . add ( 'animate__animated' , 'animate__pulse' , 'animate__infinite' ) ;
2025-09-25 13:03:23 -06:00
}
} ) ;
2025-09-24 11:59:46 -06:00
} else {
2025-09-24 22:51:53 -06:00
CourseNav . audioController . stopAllSoundsAndPlay ( bad ) ;
2025-09-25 13:03:23 -06:00
// Solo sonido, el usuario puede seguir intentando
2025-09-24 11:59:46 -06:00
}
}
function finalizarTurno ( ) {
isSpinning = false ;
2026-07-01 15:47:43 -06:00
document . getElementById ( 'coursenav-main-content' ) . classList . remove ( 'no-overflow' ) ;
2025-09-24 11:59:46 -06:00
if ( girosRealizados >= maxGiros ) {
spinBtn . disabled = true ;
2026-07-01 15:47:43 -06:00
spinBtn . textContent = '¡Juego Completado!' ;
2025-09-24 11:59:46 -06:00
CourseNav . setSlideVisited ( ) ;
2025-09-24 22:51:53 -06:00
setTimeout ( ( ) => {
Completed ( ) ;
} , 300 ) ;
2025-09-24 11:59:46 -06:00
} else {
spinBtn . disabled = false ;
spinBtn . textContent = ` ¡GIRAR RULETA! ( ${ maxGiros - girosRealizados } restantes) ` ;
}
2026-07-01 15:47:43 -06:00
ruletaWheel . classList . remove ( 'spinning' ) ;
2025-09-24 11:59:46 -06:00
}
function Completed ( ) {
2026-07-01 15:47:43 -06:00
const html = $ ( '#pop0' ) . html ( ) ;
2025-09-24 11:59:46 -06:00
Swal . fire ( {
html : html ,
target : document . getElementById ( 'wrap-course-content' ) ,
customClass : {
popup : 'pop_html_style border border-3 border-primary rounded-4' ,
2026-07-01 15:47:43 -06:00
confirmButton : 'btn text-white bg-primary amor fw-semibold animate__animated animate__pulse animate__infinite' ,
2025-09-24 11:59:46 -06:00
} ,
2026-07-01 15:47:43 -06:00
confirmButtonText : 'Cerrar' ,
2025-09-24 11:59:46 -06:00
showConfirmButton : true ,
allowOutsideClick : false ,
allowEscapeKey : false ,
focusConfirm : false ,
2026-07-01 15:47:43 -06:00
backdrop : 'rgba(65, 60, 60, .95)' ,
width : '35em' ,
didOpen : ( ) => { } ,
2025-09-24 11:59:46 -06:00
didClose : ( ) => {
CourseNav . audioController . stopAudio ( ) ;
CourseNav . setSlideVisited ( ) ;
} ,
} ) ;
}
// Cargar preguntas de "Diapositiva 19"
readExcelFile ( urlExcelFile , function ( data ) {
2026-07-01 15:47:43 -06:00
const sheetData = data [ 'Diapositiva 19' ] ;
2025-09-24 11:59:46 -06:00
if ( sheetData ) {
questions = procesarPreguntas ( sheetData ) ;
2026-07-01 15:47:43 -06:00
console . log ( 'Preguntas cargadas de Diapositiva 19:' , questions ) ;
2025-09-24 11:59:46 -06:00
} else {
console . error ( 'No se encontró la hoja "Diapositiva 19"' ) ;
2026-07-01 15:47:43 -06:00
console . log ( 'Hojas disponibles:' , Object . keys ( data ) ) ;
2025-09-24 11:59:46 -06:00
}
} ) ;
} ) ;
< / script >