multi-game/static/js/game.js
2025-07-16 17:57:35 +02:00

186 lines
6.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// static/js/game.js
document.addEventListener("DOMContentLoaded", () => {
const TIEMPO_TOTAL = 60; // segundos
let segundosRestantes = TIEMPO_TOTAL;
let puntuacion = 0;
const barraTiempo = document.getElementById("barra-tiempo");
const tiempoTexto = document.getElementById("tiempo-texto");
const contadorAciertos = document.getElementById("contador-aciertos");
const enunciado = document.getElementById("enunciado");
const inputRespuesta = document.getElementById("input-respuesta");
const feedback = document.getElementById("feedback");
const botonFinal = document.getElementById("boton-final");
const verRankingBtn = document.getElementById("ver-ranking");
const jugarOtraBtn = document.getElementById("jugar-otra");
const formNombre = document.getElementById("form-nombre");
const inputNombre = document.getElementById("input-nombre");
const guardarNombreBtn = document.getElementById("guardar-nombre");
const mensajeGuardar = document.getElementById("mensaje-guardar");
let numeroA = 0;
let numeroB = 0;
let temporizadorInterval = null;
// Genera un par aleatorio (dos números entre 10 y 99)
function generarPregunta() {
numeroA = Math.floor(Math.random() * 90) + 10; // 10…99
numeroB = Math.floor(Math.random() * 90) + 10;
enunciado.textContent = `¿Cuánto es ${numeroA} × ${numeroB}?`;
inputRespuesta.value = "";
inputRespuesta.focus();
}
// Inicia el cronómetro y actualiza cada segundo
function iniciarTemporizador() {
barraTiempo.style.width = "100%";
tiempoTexto.textContent = `${segundosRestantes} segundos restantes`;
temporizadorInterval = setInterval(() => {
segundosRestantes--;
if (segundosRestantes < 0) {
clearInterval(temporizadorInterval);
terminarJuego();
return;
}
// Actualiza texto y barra de progreso
tiempoTexto.textContent = `${segundosRestantes} segundos restantes`;
const porcentaje = (segundosRestantes / TIEMPO_TOTAL) * 100;
barraTiempo.style.width = `${porcentaje}%`;
// Cambiar color de barra si queda poco tiempo
if (segundosRestantes <= 10) {
barraTiempo.classList.remove("bg-success");
barraTiempo.classList.add("bg-danger");
} else if (segundosRestantes <= 30) {
barraTiempo.classList.remove("bg-success");
barraTiempo.classList.add("bg-warning");
}
}, 1000);
}
// Función que maneja el envío de la respuesta al presionar Enter
inputRespuesta.addEventListener("keydown", (e) => {
if (e.key === "Enter" && segundosRestantes > 0) {
e.preventDefault();
validarRespuesta();
}
});
function validarRespuesta() {
const valor = parseInt(inputRespuesta.value);
const correcta = numeroA * numeroB;
if (!isNaN(valor)) {
if (valor === correcta) {
puntuacion++;
contadorAciertos.textContent = puntuacion;
feedback.innerHTML = `<span class="text-success">Correcto!</span>`;
} else {
feedback.innerHTML = `<span class="text-danger">Incorrecto. Era ${correcta}.</span>`;
}
// Mostrar feedback por 800ms y luego limpiarlo
setTimeout(() => {
feedback.textContent = "";
}, 800);
} else {
feedback.innerHTML = `<span class="text-warning">Ingresa un número válido.</span>`;
setTimeout(() => {
feedback.textContent = "";
}, 800);
}
generarPregunta();
}
function terminarJuego() {
// Deshabilitar input
inputRespuesta.disabled = true;
feedback.innerHTML = `
<div class="alert alert-info p-2">
¡Tiempo terminado! Tu puntuación es: <strong>${puntuacion}</strong>
</div>
`;
// Enviar puntuación al servidor
fetch('/api/score', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ puntuacion })
})
.then(res => res.json())
.then(data => {
if (data.error) {
feedback.innerHTML += `<div class="text-danger">Error: ${data.error}</div>`;
botonFinal.classList.remove("d-none");
return;
}
if (data.entra_en_top) {
// Muestra formulario para nombre
formNombre.classList.remove("d-none");
} else {
// No entra en top10: mostrar botón para ver ranking
botonFinal.classList.remove("d-none");
}
// Guarda el top10 actual en data.top10 para mostrar más tarde si hace falta
window.top10_actual = data.top10;
})
.catch(err => {
feedback.innerHTML += `<div class="text-danger">Error conectando al servidor.</div>`;
botonFinal.classList.remove("d-none");
});
}
// Botón “Ver Ranking” (si no entró en top 10)
verRankingBtn.addEventListener("click", () => {
// Redirigir a la página /ranking
window.location.href = "/ranking";
});
// Botón “Jugar otra vez”
jugarOtraBtn.addEventListener("click", () => {
window.location.href = "/juego";
});
// Al hacer clic en “Guardar” nombre (si entró en top 10)
guardarNombreBtn.addEventListener("click", () => {
const nombre = inputNombre.value.trim();
if (nombre.length === 0) {
mensajeGuardar.innerHTML = `<small class="text-danger">El nombre no puede estar vacío.</small>`;
return;
}
// Enviar nombre + puntuación al servidor
fetch('/api/score/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nombre, puntuacion })
})
.then(res => res.json())
.then(data => {
if (data.error) {
mensajeGuardar.innerHTML = `<small class="text-danger">Error: ${data.error}</small>`;
return;
}
mensajeGuardar.innerHTML = `<div class="alert alert-success p-2">
¡Puntuación guardada! Puedes ver el ranking actualizado.</div>`;
// Opcional: mostrar tabla de top10 recibida en data.top10
setTimeout(() => {
window.location.href = "/ranking";
}, 1500);
})
.catch(err => {
mensajeGuardar.innerHTML = `<small class="text-danger">Error guardando el nombre.</small>`;
});
});
// Iniciar todo
function iniciarJuego() {
generarPregunta();
iniciarTemporizador();
inputRespuesta.disabled = false;
inputRespuesta.focus();
}
// Esperar 300ms para que el usuario vea la primera pregunta
setTimeout(iniciarJuego, 300);
});