/** * highscore.js * High-score screen: displays final score(s), persists top-10 to localStorage, * shows leaderboard, offers back-to-start button. * * show(names, scores, playerCount) * names — string (1P) or array of strings (2P) * scores — number (1P) or array of numbers (2P) * playerCount — 1 or 2 */ const HighScoreScreen = (() => { const STORAGE_KEY = 'kidneylab_scores'; /* ── Persistence ─────────────────────────────────────────────── */ function loadScores() { try { return JSON.parse(localStorage.getItem(STORAGE_KEY)) || []; } catch { return []; } } function saveScore(name, score) { const scores = loadScores(); scores.push({ name: name.toUpperCase().slice(0, 12), score, date: new Date().toLocaleDateString() }); scores.sort((a, b) => b.score - a.score); const top10 = scores.slice(0, 10); localStorage.setItem(STORAGE_KEY, JSON.stringify(top10)); return top10; } /* ── Helpers ─────────────────────────────────────────────────── */ function rankLabel(rank) { if (rank === 1) return '🏆 NEW HIGH SCORE!'; if (rank === 2) return '🥈 2nd place!'; if (rank === 3) return '🥉 3rd place!'; return `Rank #${rank}`; } function resultCardHTML(playerName, finalScore, scores, myRank) { const isTop = myRank === 1; return `
${rankLabel(myRank)}
${playerName.toUpperCase()}
${finalScore >= 0 ? finalScore : 0}
POINTS
`; } function tableHTML(scores, highlightNames, highlightScores) { const rowsHTML = scores.map((s, i) => { // highlight any entry that matches one of the just-played players const isMe = highlightNames.some((n, ni) => s.name === n.toUpperCase().slice(0, 12) && s.score === highlightScores[ni] ); return ` ${i + 1} ${s.name} ${s.score} ${s.date} `; }).join(''); return `

HALL OF FAME

${rowsHTML}
#NAMESCOREDATE
`; } /* ── Public show ─────────────────────────────────────────────── */ function show(names, scores, playerCount) { // Normalise to arrays const nameArr = Array.isArray(names) ? names : [names]; const scoreArr = Array.isArray(scores) ? scores : [scores]; const count = playerCount || nameArr.length; // Switch screen document.querySelectorAll('.screen').forEach(s => s.classList.remove('active')); document.getElementById('highscore-screen').classList.add('active'); // Save all players' scores; last save wins for the leaderboard table let leaderboard; nameArr.forEach((n, i) => { leaderboard = saveScore(n, scoreArr[i]); }); // Build rank info for each player const rankInfo = nameArr.map((n, i) => { const rank = leaderboard.findIndex( s => s.name === n.toUpperCase().slice(0, 12) && s.score === scoreArr[i] ) + 1; return { name: n, score: scoreArr[i], rank }; }); render(rankInfo, leaderboard, nameArr, scoreArr); } function render(rankInfo, leaderboard, nameArr, scoreArr) { const el = document.getElementById('highscore-screen'); // One result card per player const cardsHTML = rankInfo.map(r => resultCardHTML(r.name, r.score, leaderboard, r.rank) ).join(''); // Cards side-by-side for 2P, centred for 1P const cardsWrap = rankInfo.length > 1 ? `
${cardsHTML}
` : cardsHTML; el.innerHTML = `
${cardsWrap} ${tableHTML(leaderboard, nameArr, scoreArr)}
`; el.querySelector('#back-btn').addEventListener('click', () => { IntroScreen.show(); }); } return { show }; })();