50 lines
1.5 KiB
JavaScript
50 lines
1.5 KiB
JavaScript
import { STORAGE_KEY } from '../config.js';
|
|
|
|
function readAll() {
|
|
try {
|
|
const raw = localStorage.getItem(STORAGE_KEY);
|
|
return raw ? JSON.parse(raw) : {};
|
|
} catch (e) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
function writeAll(all) {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(all));
|
|
} catch (e) {
|
|
// localStorage unavailable (e.g. private browsing) - progress just won't persist
|
|
}
|
|
}
|
|
|
|
export function isLevelComplete(levelId) {
|
|
return Boolean(readAll()[levelId]);
|
|
}
|
|
|
|
// Records a completed run. kidsSaved/kidsTotal are kept (they're how
|
|
// "isLevelComplete" and any legacy saves work), and bestScore is the
|
|
// player's highest final score - the level select map shows it under each
|
|
// cleared node. A run only "counts" if it improves the best on either
|
|
// axis, but whichever axis improved wins; both are kept at their max.
|
|
export function markLevelComplete(levelId, kidsSaved, kidsTotal, score = null) {
|
|
const all = readAll();
|
|
const existing = all[levelId] || {};
|
|
all[levelId] = {
|
|
kidsSaved: Math.max(existing.kidsSaved || 0, kidsSaved),
|
|
kidsTotal,
|
|
bestScore: Math.max(existing.bestScore || 0, score || 0),
|
|
};
|
|
writeAll(all);
|
|
}
|
|
|
|
export function getLevelResult(levelId) {
|
|
return readAll()[levelId] || null;
|
|
}
|
|
|
|
// The player's best score for a level, or null if none has been recorded
|
|
// yet (e.g. a legacy save from before best scores existed).
|
|
export function getBestScore(levelId) {
|
|
const result = readAll()[levelId];
|
|
return result && typeof result.bestScore === 'number' && result.bestScore > 0 ? result.bestScore : null;
|
|
}
|