Added kidney_labe and Cyste_kid
This commit is contained in:
144
kidney_lab/js/highscore.js
Normal file
144
kidney_lab/js/highscore.js
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* 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 `
|
||||
<div class="hs-result ${isTop ? 'hs-gold' : ''}">
|
||||
<div class="hs-rank-label">${rankLabel(myRank)}</div>
|
||||
<div class="hs-player">${playerName.toUpperCase()}</div>
|
||||
<div class="hs-score-display">${finalScore >= 0 ? finalScore : 0}</div>
|
||||
<div class="hs-score-label">POINTS</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
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 `<tr class="${isMe ? 'my-row' : ''}">
|
||||
<td class="rank-col">${i + 1}</td>
|
||||
<td class="name-col">${s.name}</td>
|
||||
<td class="score-col">${s.score}</td>
|
||||
<td class="date-col">${s.date}</td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
|
||||
return `
|
||||
<div class="hs-table-wrap">
|
||||
<h2 class="hs-heading">HALL OF FAME</h2>
|
||||
<table class="hs-table">
|
||||
<thead><tr><th>#</th><th>NAME</th><th>SCORE</th><th>DATE</th></tr></thead>
|
||||
<tbody>${rowsHTML}</tbody>
|
||||
</table>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
/* ── 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
|
||||
? `<div style="display:flex;gap:16px;justify-content:center;flex-wrap:wrap;">${cardsHTML}</div>`
|
||||
: cardsHTML;
|
||||
|
||||
el.innerHTML = `
|
||||
<div class="hs-inner">
|
||||
<div class="hs-logo">
|
||||
<span class="logo-gw">GAME & WATCH</span>
|
||||
<span class="logo-title">KIDNEY LAB</span>
|
||||
</div>
|
||||
|
||||
${cardsWrap}
|
||||
|
||||
${tableHTML(leaderboard, nameArr, scoreArr)}
|
||||
|
||||
<div class="hs-actions">
|
||||
<button id="back-btn" class="btn-primary">PLAY AGAIN</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
el.querySelector('#back-btn').addEventListener('click', () => {
|
||||
IntroScreen.show();
|
||||
});
|
||||
}
|
||||
|
||||
return { show };
|
||||
})();
|
||||
Reference in New Issue
Block a user