<!–
CÓDIGO LISTO PARA BLOGGER
Instrucciones:
1. En tu entrada de Blogger, cambia a la vista "Vista HTML".
2. Copia y pega TODO el código que empieza a continuación (desde
3. El juego debería aparecer y funcionar correctamente dentro de tu entrada de blog.
–>
@import url(‘https://fonts.googleapis.com/css2?family=Press+Start+2P&display=swap’);
#juego-matematico-contenedor {
–bg-color: #0d0c1d;
–primary-color: #ff00ff;
–secondary-color: #00ffff;
–text-color: #fff;
–success-color: #00ff00;
–error-color: #ff0000;
–font-family: ‘Press Start 2P’, cursive;
font-family: var(–font-family);
background-color: var(–bg-color);
color: var(–text-color);
text-align: center;
margin: auto;
width: 100%;
}
#juego-matematico-contenedor * { box-sizing: border-box; margin: 0; padding: 0; }
#juego-matematico-contenedor .container {
width: 100%;
max-width: 800px;
min-height: 700px;
margin: auto;
border: 3px solid var(–primary-color);
border-radius: 15px;
box-shadow: 0 0 20px var(–primary-color);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 20px;
position: relative;
overflow: hidden;
}
#juego-matematico-contenedor .screen {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
flex-grow: 1;
}
#juego-matematico-contenedor .hidden { display: none !important; }
#juego-matematico-contenedor h1 { font-size: 1.5rem; color: var(–secondary-color); text-shadow: 0 0 10px var(–secondary-color); margin-bottom: 20px; line-height: 1.5; }
#juego-matematico-contenedor h2 { font-size: 1.8rem; color: var(–primary-color); margin-bottom: 20px; }
#juego-matematico-contenedor .btn { font-family: var(–font-family); background: transparent; padding: 15px 30px; margin: 10px; font-size: 1.2rem; cursor: pointer; border: 2px solid var(–secondary-color); color: var(–secondary-color); }
#juego-matematico-contenedor .btn-menu { background-color: var(–bg-color); border: 4px solid var(–secondary-color); color: var(–secondary-color); box-shadow: 4px 4px 0 0 var(–secondary-color); position: relative; transition: transform 0.1s, box-shadow 0.1s; width: 80%; max-width: 400px; }
#juego-matematico-contenedor .btn-menu:hover { background: var(–secondary-color); color: var(–bg-color); box-shadow: 0 0 20px var(–secondary-color); }
#juego-matematico-contenedor .btn-menu:active { transform: translate(4px, 4px); box-shadow: 0 0 0 0 var(–secondary-color); }
#juego-matematico-contenedor .btn-back { position: absolute; top: 20px; left: 20px; padding: 10px; font-size: 1rem; border-color: var(–primary-color); color: var(–primary-color); z-index: 10; }
#juego-matematico-contenedor .btn-back:hover { background: var(–primary-color); color: var(–bg-color); box-shadow: 0 0 15px var(–primary-color); }
#juego-matematico-contenedor .btn-home { position: absolute; top: 20px; right: 80px; padding: 10px; font-size: 1rem; border-color: var(–secondary-color); color: var(–secondary-color); z-index: 10; }
#juego-matematico-contenedor .btn-home:hover { background: var(–secondary-color); color: var(–bg-color); }
#juego-matematico-contenedor #game-header { width: 100%; display: flex; justify-content: space-between; font-size: 1.5rem; padding: 0 20px; margin-bottom: 40px; }
#juego-matematico-contenedor #problem { font-size: 3rem; margin-bottom: 30px; color: var(–secondary-color); }
#juego-matematico-contenedor #answer-options { display: grid; grid-template-columns: 1fr; gap: 20px; width: 100%; max-width: 500px; }
#juego-matematico-contenedor .answer-btn { font-size: 1.5rem; padding: 20px; border-width: 3px; }
#juego-matematico-contenedor .answer-btn:hover { background: var(–secondary-color); color: var(–bg-color); }
#juego-matematico-contenedor #game-over-screen input { font-family: var(–font-family); font-size: 1.2rem; padding: 10px; margin: 20px; text-align: center; background: #1a1a2e; border: 2px solid var(–primary-color); color: var(–text-color); }
#juego-matematico-contenedor .scores-container { border: 2px solid var(–secondary-color); padding: 15px; margin-top: 30px; max-width: 500px; height: 500px; border-radius: 10px; overflow-y: auto; }
#juego-matematico-contenedor .scores-list { list-style: none; padding: 0; text-align: left;} /* Removed max-height and overflow-y */
#juego-matematico-contenedor .scores-list li { display: flex; justify-content: space-between; align-items: center; padding: 8px 5px; margin-bottom: 10px; }
#juego-matematico-contenedor .player-info { font-size: 0.65rem; } /* Reduced font size */
#juego-matematico-contenedor .position-number { font-size: 0.65rem; margin-right: 5px; color: var(–primary-color); }
#juego-matematico-contenedor .player-score { font-size: 14px; }
#juego-matematico-contenedor .score-details { display: flex; flex-direction: column; align-items: flex-start; }
#juego-matematico-contenedor .player-date { font-size: 0.65rem; color: var(–secondary-color); opacity: 0.8; margin-top: 4px; }
#juego-matematico-contenedor .audio-control { position: absolute; top: 20px; right: 20px; display: flex; align-items: center; z-index: 10; }
#juego-matematico-contenedor #audio-btn { font-size: 1.5rem; background: none; border: none; color: var(–text-color); cursor: pointer; }
#juego-matematico-contenedor .notification { position: absolute; top: 20px; left: 50%; transform: translateX(-50%); background-color: var(–primary-color); color: var(–text-color); padding: 15px; border-radius: 8px; z-index: 9999; opacity: 0; transition: opacity 0.3s ease; width: auto; max-width: 80%; white-space: nowrap; pointer-events: none; }
#juego-matematico-contenedor .notification.show { opacity: 1; }
#juego-matematico-contenedor .notification.error { background-color: var(–error-color); }
#juego-matematico-contenedor .notification.success { background-color: var(–success-color); color: var(–bg-color); }
@keyframes sparkle-button { 0%, 100% { transform: scale(1); box-shadow: 4px 4px 0 0 var(–secondary-color); } 50% { transform: scale(1.05); box-shadow: 0 0 25px var(–secondary-color); } }
#juego-matematico-contenedor .sparkle-button { animation: sparkle-button 1.5s infinite ease-in-out; }
@media (max-width: 600px) {
#juego-matematico-contenedor .container { padding: 15px; min-height: 100vh; border: none; border-radius: 0;}
#juego-matematico-contenedor h1 { font-size: 1.1rem; line-height: 1.4; }
#juego-matematico-contenedor h2 { font-size: 1.4rem; }
#juego-matematico-contenedor .btn { padding: 10px 15px; font-size: 0.9rem; margin: 8px; }
#juego-matematico-contenedor .btn-menu { width: 90%; }
#juego-matematico-contenedor #game-header { font-size: 1.1rem; padding: 0 10px; }
#juego-matematico-contenedor #problem { font-size: 2.2rem; }
#juego-matematico-contenedor .answer-btn { font-size: 1.1rem; padding: 15px; }
#juego-matematico-contenedor .scores-list li { font-size: 0.8rem; }
#juego-matematico-contenedor .player-date { font-size: 0.6rem; }
#juego-matematico-contenedor .btn-home { right: 70px; }
#juego-matematico-contenedor #start-screen { justify-content: space-evenly; }
#juego-matematico-contenedor #start-screen h1 { font-size: 1.3rem; line-height: 1.5; }
#juego-matematico-contenedor #start-screen .btn-menu { width: 90%; padding: 15px; font-size: 1.2rem; margin-top: 20px; }
#juego-matematico-contenedor #start-screen .scores-container { width: 95%; margin-top: 20px; }
}
Desafío Matemático Espacial
Mejores Puntuaciones
const screens = {
start: document.getElementById(‘start-screen’),
mode: document.getElementById(‘mode-screen’),
difficulty: document.getElementById(‘difficulty-screen’),
game: document.getElementById(‘game-screen’),
gameOver: document.getElementById(‘game-over-screen’)
};
const buttons = {
play: document.getElementById(‘play-btn’),
mode: document.querySelectorAll(‘.mode-btn’),
difficulty: document.querySelectorAll(‘.difficulty-btn’),
saveScore: document.getElementById(‘save-score-btn’),
playAgain: document.getElementById(‘play-again-btn’),
backToStart: document.getElementById(‘back-to-start’),
backToMode: document.getElementById(‘back-to-mode’),
home: document.getElementById(‘home-btn’),
audio: document.getElementById(‘audio-btn’)
};
const displays = {
score: document.getElementById(‘score’),
timer: document.getElementById(‘timer’),
problem: document.getElementById(‘problem’),
finalScore: document.getElementById(‘final-score’),
highScoresList: document.getElementById(‘high-scores-list’),
answerOptions: document.getElementById(‘answer-options’)
};
const inputs = { playerName: document.getElementById(‘player-name’) };
let score = 0, timer = 0, timerInterval, scoreBonusThreshold = 20;
let currentGameMode = ‘sumas’, currentDifficulty = ‘easy’, currentProblem = { answer: 0 };
let isMusicOn = false, audioCtx, musicInterval = null;
const allMelodies = [
[{n:262,d:0.15},{n:330,d:0.15},{n:392,d:0.15},{n:523,d:0.3},{n:392,d:0.15},{n:330,d:0.15},{n:262,d:0.3}],
[{n:220,d:0.1},{n:262,d:0.1},{n:330,d:0.1},{n:440,d:0.1},{n:330,d:0.1},{n:262,d:0.1},{n:220,d:0.1}],
[{n:523,d:0.1},{n:null,d:0.1},{n:587,d:0.1},{n:null,d:0.1},{n:659,d:0.1},{n:null,d:0.1},{n:587,d:0.1}],
[{n:196,d:0.2},{n:277,d:0.2},{n:370,d:0.2},{n:277,d:0.2}],
[{n:784,d:0.08},{n:740,d:0.08},{n:698,d:0.08},{n:659,d:0.08},{n:622,d:0.08},{n:587,d:0.08},{n:554,d:0.08},{n:523,d:0.08}],
[{n:196,d:0.4},{n:null,d:0.1},{n:196,d:0.4},{n:null,d:0.1},{n:220,d:0.5},{n:196,d:0.4},{n:null,d:0.1},{n:196,d:0.4},{n:null,d:0.1},{n:220,d:0.5},{n:220,d:0.3},{n:233,d:0.3},{n:247,d:0.3},{n:262,d:0.6},{n:220,d:0.3},{n:233,d:0.3},{n:247,d:0.3},{n:262,d:0.6},{n:null,d:0.5},{n:196,d:0.6},{n:247,d:0.4},{n:196,d:0.6},{n:null,d:0.5},{n:196,d:0.6},{n:247,d:0.4},{n:196,d:0.6},{n:392,d:0.15},{n:null,d:0.15},{n:370,d:0.15},{n:null,d:0.15},{n:392,d:0.15},{n:null,d:0.15},{n:370,d:0.15},{n:null,d:0.15},{n:415,d:0.6},{n:392,d:0.15},{n:null,d:0.15},{n:370,d:0.15},{n:null,d:0.15},{n:415,d:0.6},{n:174,d:0.5},{n:null,d:0.2},{n:174,d:0.5},{n:null,d:0.2},{n:196,d:0.5},{n:174,d:0.5},{n:null,d:0.2},{n:174,d:0.5},{n:null,d:0.2},{n:196,d:0.5},{n:220,d:0.25},{n:247,d:0.25},{n:262,d:0.25},{n:294,d:0.5},{n:220,d:0.25},{n:247,d:0.25},{n:262,d:0.25},{n:294,d:0.5},{n:null,d:0.5},{n:196,d:0.4},{n:220,d:0.4},{n:247,d:0.4},{n:220,d:0.4},{n:null,d:0.5},{n:196,d:0.4},{n:220,d:0.4},{n:247,d:0.4},{n:220,d:0.4},{n:392,d:0.2},{n:370,d:0.2},{n:349,d:0.2},{n:330,d:0.2},{n:311,d:0.2},{n:330,d:0.2},{n:349,d:0.2},{n:370,d:0.2},{n:392,d:0.2},{n:415,d:0.2},{n:440,d:0.4},{n:415,d:0.4},{n:392,d:0.6}],
[{n:262,d:0.2},{n:294,d:0.2},{n:330,d:0.2},{n:349,d:0.2},{n:392,d:0.2},{n:330,d:0.2},{n:294,d:0.2},{n:262,d:0.2},{n:330,d:0.15},{n:null,d:0.05},{n:330,d:0.15},{n:null,d:0.05},{n:349,d:0.15},{n:null,d:0.05},{n:349,d:0.15},{n:null,d:0.05},{n:330,d:0.15},{n:null,d:0.05},{n:330,d:0.15},{n:null,d:0.05},{n:294,d:0.15},{n:330,d:0.15},{n:349,d:0.15},{n:392,d:0.15},{n:440,d:0.15},{n:494,d:0.15},{n:523,d:0.3},{n:523,d:0.1},{n:494,d:0.1},{n:440,d:0.1},{n:392,d:0.1},{n:349,d:0.1},{n:330,d:0.1},{n:294,d:0.1},{n:262,d:0.1},{n:330,d:0.1},{n:349,d:0.1},{n:370,d:0.1},{n:392,d:0.1},{n:415,d:0.1},{n:440,d:0.1},{n:466,d:0.1},{n:494,d:0.1},{n:523,d:0.1},{n:494,d:0.1},{n:466,d:0.1},{n:440,d:0.1},{n:415,d:0.1},{n:392,d:0.1},{n:370,d:0.1},{n:349,d:0.1},{n:330,d:0.15},{n:null,d:0.15},{n:523,d:0.4}],
[{n:262,d:0.3},{n:330,d:0.3},{n:392,d:0.3},{n:523,d:0.6},{n:392,d:0.3},{n:330,d:0.3},{n:262,d:0.6},{n:294,d:0.25},{n:330,d:0.25},{n:349,d:0.25},{n:392,d:0.25},{n:330,d:0.25},{n:294,d:0.25},{n:262,d:0.5},{n:330,d:0.3},{n:null,d:0.1},{n:392,d:0.3},{n:null,d:0.1},{n:440,d:0.3},{n:null,d:0.1},{n:494,d:0.3},{n:null,d:0.1},{n:523,d:0.6},{n:392,d:0.3},{n:330,d:0.3},{n:262,d:0.6},{n:262,d:0.3},{n:330,d:0.3},{n:392,d:0.3},{n:523,d:0.6}]
];
let currentMelody = [], melodyStep = 0;
function playSound(type) {
if (!audioCtx || !isMusicOn) return;
const osc = audioCtx.createOscillator(), gain = audioCtx.createGain();
osc.connect(gain); gain.connect(audioCtx.destination);
let freq = 440, dur = 0.2, wave = ‘triangle’, vol = 0.1;
if (type === ‘success’) { freq = 600; dur = 0.5; wave = ‘sine’; vol = 0.15;}
else if (type === ‘error’) { freq = 150; dur = 0.3; wave = ‘square’; vol = 0.15;}
else if (type === ‘tick’) { freq = 800; dur = 0.1; wave = ‘sine’; }
else if (type === ‘click’) { freq = 440; dur = 0.1; wave = ‘triangle’; }
gain.gain.setValueAtTime(vol, audioCtx.currentTime);
osc.type = wave; osc.frequency.setValueAtTime(freq, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + dur);
osc.start(audioCtx.currentTime); osc.stop(audioCtx.currentTime + dur);
}
function playMelodyNote() {
if (!isMusicOn || !audioCtx) return;
if (melodyStep >= currentMelody.length) {
melodyStep = 0;
currentMelody = allMelodies[Math.floor(Math.random() * allMelodies.length)];
}
const note = currentMelody[melodyStep];
if (note && note.n) {
const osc = audioCtx.createOscillator(), gain = audioCtx.createGain();
osc.connect(gain); gain.connect(audioCtx.destination);
osc.type = ‘square’;
gain.gain.setValueAtTime(0.08, audioCtx.currentTime);
osc.frequency.setValueAtTime(note.n, audioCtx.currentTime);
gain.gain.exponentialRampToValueAtTime(0.0001, audioCtx.currentTime + note.d);
osc.start(audioCtx.currentTime); osc.stop(audioCtx.currentTime + note.d);
}
melodyStep++;
}
function startMusic() {
if (musicInterval) return;
currentMelody = allMelodies[Math.floor(Math.random() * allMelodies.length)];
melodyStep = 0;
musicInterval = setInterval(playMelodyNote, 180);
}
function stopMusic() {
clearInterval(musicInterval);
musicInterval = null;
}
function toggleMusic() {
isMusicOn = !isMusicOn;
if (isMusicOn) {
if (!audioCtx) {
try { audioCtx = new (window.AudioContext || window.webkitAudioContext)(); }
catch (e) { console.error(“AudioContext not supported.”); isMusicOn = false; return; }
}
audioCtx.resume();
buttons.audio.textContent = ‘🔊’;
startMusic();
} else {
buttons.audio.textContent = ‘🔇’;
stopMusic();
}
}
function showScreen(screenName) {
Object.values(screens).forEach(s => s.classList.add(‘hidden’));
screens[screenName].classList.remove(‘hidden’);
}
function setupEventListeners() {
buttons.audio.addEventListener(‘click’, toggleMusic);
buttons.play.addEventListener(‘click’, () => { playSound(‘click’); showScreen(‘mode’); });
buttons.backToStart.addEventListener(‘click’, () => { playSound(‘click’); showScreen(‘start’); });
buttons.backToMode.addEventListener(‘click’, () => { playSound(‘click’); showScreen(‘mode’); });
buttons.home.addEventListener(‘click’, () => { playSound(‘click’); clearInterval(timerInterval); showScreen(‘start’); });
buttons.playAgain.addEventListener(‘click’, () => { playSound(‘click’); showScreen(‘mode’); });
buttons.mode.forEach(btn => btn.addEventListener(‘click’, () => {
playSound(‘click’);
currentGameMode = btn.dataset.mode;
showScreen(‘difficulty’);
}));
buttons.difficulty.forEach(btn => btn.addEventListener(‘click’, () => {
playSound(‘click’);
currentDifficulty = btn.dataset.level;
startGame();
}));
buttons.saveScore.addEventListener(‘click’, () => {
playSound(‘click’);
const name = inputs.playerName.value.trim();
if (name) {
saveScore(name, score, currentGameMode, currentDifficulty);
} else {
showNotification(‘Por favor, escribe tu nombre.’, ‘error’);
}
});
}
function startGame() {
score = 0;
scoreBonusThreshold = 20;
timer = { easy: 60, medium: 45, hard: 30 }[currentDifficulty];
displays.score.textContent = `Puntos: ${score}`;
displays.timer.textContent = `Tiempo: ${timer}`;
showScreen(‘game’);
nextProblem();
clearInterval(timerInterval);
timerInterval = setInterval(updateTimer, 1000);
}
function updateTimer() {
timer–;
displays.timer.textContent = `Tiempo: ${timer}`;
if (timer 0) playSound(‘tick’);
if (timer <= 0) {
endGame();
}
}
function nextProblem() {
try {
const p = generateProblem();
if (!p || !p.options || p.options.length < 3) {
displays.problem.textContent = "Error: No se pudo generar el problema. Intente de nuevo.";
return;
}
displays.problem.textContent = p.problemText;
displayOptions(p.options);
} catch (e) {
displays.problem.textContent = `ERROR FATAL: ${e.stack}`;
}
}
function generateProblem() {
const levels = {
easy: { ops: ['+', '-'], max: 10, multMax: 5, divMax: 5 },
medium: { ops: ['+', '-', '*'], max: 25, multMax: 10, divMax: 10 },
hard: { ops: ['+', '-', '*', '/'], max: 100, multMax: 20, divMax: 20 }
};
const l = levels[currentDifficulty];
let op;
if (currentGameMode === 'super-pro') {
op = l.ops[Math.floor(Math.random() * l.ops.length)];
} else {
const modeMap = { sumas: '+', restas: '-', multiplicaciones: '*', divisiones: '/' };
op = modeMap[currentGameMode];
}
let n1, n2;
if (op === '+' || op === '-') {
n1 = Math.floor(Math.random() * l.max) + 1;
n2 = Math.floor(Math.random() * l.max) + 1;
if (op === '-' && n1 < n2) [n1, n2] = [n2, n1];
} else if (op === '*') {
n1 = Math.floor(Math.random() * (l.multMax – 1)) + 2;
n2 = Math.floor(Math.random() * (l.multMax – 1)) + 2;
} else if (op === '/') {
const r = Math.floor(Math.random() * (l.divMax – 1)) + 2;
n2 = Math.floor(Math.random() * (l.divMax – 1)) + 2;
n1 = n2 * r;
}
switch (op) {
case '+': currentProblem.answer = n1 + n2; break;
case '-': currentProblem.answer = n1 – n2; break;
case '*': currentProblem.answer = n1 * n2; break;
case '/': currentProblem.answer = n1 / n2; break;
}
const options = new Set([currentProblem.answer]);
let attempts = 0;
while (options.size < 3 && attempts < 50) {
const offset = (Math.floor(Math.random() * 10) + 1) * (Math.random() = 0) {
options.add(randomAnswer);
}
attempts++;
}
while (options.size Math.random() – 0.5) };
}
function displayOptions(options) {
displays.answerOptions.innerHTML = ”;
options.forEach(o => {
const b = document.createElement(‘button’);
b.className = ‘btn answer-btn’;
b.textContent = o;
b.onclick = () => checkAnswer(o);
displays.answerOptions.appendChild(b);
});
}
function checkAnswer(val) {
document.querySelectorAll(‘.answer-btn’).forEach(b => {
b.disabled = true;
if (parseInt(b.textContent) === currentProblem.answer) b.style.borderColor = ‘var(–success-color)’;
else b.style.borderColor = ‘var(–error-color)’;
});
if (val === currentProblem.answer) {
score += 10;
playSound(‘success’);
if (score >= scoreBonusThreshold) {
timer += 10;
scoreBonusThreshold += 20;
showNotification(‘+10s Bonus!’, ‘success’);
}
} else {
score = Math.max(0, score – 5);
playSound(‘error’);
}
displays.score.textContent = `Puntos: ${score}`;
displays.timer.textContent = `Tiempo: ${timer}`;
setTimeout(nextProblem, 1000);
}
function endGame() {
clearInterval(timerInterval);
displays.finalScore.textContent = `Puntuación Final: ${score}`;
showScreen(‘gameOver’);
}
function showNotification(message, type = ‘primary’) {
const notif = document.createElement(‘div’);
notif.className = `notification ${type}`;
notif.textContent = message;
document.getElementById(‘notification-container’).appendChild(notif);
setTimeout(() => { notif.classList.add(‘show’); }, 10);
setTimeout(() => { notif.classList.remove(‘show’); setTimeout(() => notif.remove(), 500); }, 2000);
}
function formatScoreDate(isoString) {
if (!isoString) return ”;
const date = new Date(isoString);
const day = String(date.getDate()).padStart(2, ‘0’);
const month = String(date.getMonth() + 1).padStart(2, ‘0’);
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, ‘0’);
const minutes = String(date.getMinutes()).padStart(2, ‘0’);
return `${day}/${month}/${year} – ${hours}:${minutes}`;
}
const _0x6a8b=[‘h’,’t’,’t’,’p’,’s’,’:’,’/’,’/’,’a’,’p’,’i’,’.’,’j’,’s’,’o’,’n’,’b’,’i’,’n’,’.’,’i’,’o’,’/’,’v’,’3′,’/’,’b’,’/’,’6′,’8′,’a’,’9′,’1′,’3′,’f’,’d’,’4′,’3′,’b’,’1′,’c’,’9′,’7′,’b’,’e’,’9′,’2′,’6′,’0′,’2′,’0′,’9′];
const _0x7c4d=[‘$’,’2′,’a’,’$’,’1′,’0′,’$’,’r’,’6′,’.’,’X’,’2′,’H’,’d’,’j’,’1′,’t’,’a’,’4′,’9′,’B’,’S’,’X’,’v’,’D’,’2′,’o’,’K’,’O’,’q’,’o’,’e’,’Z’,’E’,’O’,’p’,’X’,’S’,’i’,’H’,’P’,’s’,’Y’,’6′,’E’,’P’,’Q’,’d’,’w’,’J’,’u’,’d’,’w’,’w’,’p’,’l’,’K’,’x’,’U’,’C’];
const JSONBIN_URL = _0x6a8b.join(”), API_KEY = _0x7c4d.join(”);
async function saveScore(name, score, mode, difficulty) {
buttons.saveScore.disabled = true;
buttons.saveScore.textContent = ‘Guardando…’;
try {
let scores = await fetchScores();
scores.push({ name, score, mode, difficulty, date: new Date().toISOString() });
const res = await fetch(JSONBIN_URL, { method: ‘PUT’, headers: { ‘Content-Type’: ‘application/json’, ‘X-Master-Key’: API_KEY }, body: JSON.stringify(scores) });
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
showNotification(‘¡Puntuación guardada!’, ‘success’);
} catch (e) {
console.error(e);
showNotification(‘No se pudo guardar.’, ‘error’);
} finally {
buttons.saveScore.disabled = false;
buttons.saveScore.textContent = ‘Guardar’;
await displayHighScores();
showScreen(‘start’);
}
}
async function fetchScores() {
try {
const res = await fetch(`${JSONBIN_URL}/latest`, { headers: { ‘X-Master-Key’: API_KEY } });
if (!res.ok) { if (res.status === 404) return []; throw new Error(`HTTP error! status: ${res.status}`); }
const data = await res.json();
return Array.isArray(data.record) ? data.record : [];
} catch (e) { console.error(e); showNotification(‘Error al cargar puntuaciones.’, ‘error’); return []; }
}
async function displayHighScores() {
displays.highScoresList.innerHTML = ‘
‘;
const highScores = await fetchScores();
if (highScores.length === 0) {
displays.highScoresList.innerHTML = ‘
‘;
return;
}
highScores.sort((a, b) => b.score – a.score);
displays.highScoresList.innerHTML = ”;
const medals = [‘🥇’, ‘🥈’, ‘🥉’];
highScores.forEach((s, index) => {
const li = document.createElement(‘li’);
const positionNumber = index + 1;
const medalHtml = index < 3 ? `${medals[index]}` : `${positionNumber}.`;
const modeText = s.mode ? s.mode.substring(0, 4) : ‘N/A’;
const diffText = s.difficulty ? s.difficulty.substring(0, 4) : ‘N/A’;
const formattedDate = formatScoreDate(s.date);
li.innerHTML = `
`;
displays.highScoresList.appendChild(li);
});
}
setupEventListeners();
showScreen(‘start’);
displayHighScores();