Session 13: Save Slot Preview (footer shows each slot's stardust, buildings, achievements, last-saved; hover to preview)

This commit is contained in:
2026-08-23 17:10:56 +00:00
parent 1b9932391c
commit 40b85f5707
5 changed files with 176 additions and 0 deletions
+76
View File
@@ -637,6 +637,82 @@ const Game = {
}
},
/**
* Build a lightweight preview of a given save slot WITHOUT mutating the
* live game state. Returns an object describing what that slot holds:
* - present: whether the slot has any saved data
* - stardust: current (live) stardust production/sec for the slot
* - totalStardust: lifetime stardust earned in the slot
* - buildings: total number of buildings owned in the slot
* - achievements: count/total of achievements unlocked in the slot
* - prestigeCount: how many times the slot has been prestiged
* - lastSaved: human-readable "time ago" string for the slot's save time
* An empty/unreadable slot returns present:false with zeroed fields.
*/
getSlotPreview(slot) {
const data = this.loadSlot(slot);
if (!data) {
return {
present: false,
stardust: 0,
totalStardust: 0,
buildings: 0,
achievements: [0, 33],
prestigeCount: 0,
lastSaved: 'never'
};
}
const buildingCount = Object.values(data.buildings || {})
.reduce((sum, c) => sum + (Number(c) || 0), 0);
let timeAgo = 'never';
if (typeof data.lastSaveTime === 'number') {
const secs = Math.max(0, Math.floor((Date.now() - data.lastSaveTime) / 1000));
timeAgo = this.formatTimeAgo(secs);
}
return {
present: true,
stardust: Number(data.stardust) || 0,
totalStardust: Number(data.totalStardust) || 0,
buildings: buildingCount,
achievements: [
Array.isArray(data.achievements) ? data.achievements.length : 0,
33
],
prestigeCount: Number(data.prestigeCount) || 0,
lastSaved: timeAgo
};
},
/**
* Format a number of seconds as a compact "time ago" string
* (e.g. "just now", "1m ago", "3h ago", "2d ago"). Used by slot previews.
*/
formatTimeAgo(secs) {
if (secs < 5) return 'just now';
// Largest units first; each entry is [thresholdSeconds, label].
const buckets = [
[365 * 86400, 'y'],
[30 * 86400, 'mo'],
[86400, 'd'],
[3600, 'h'],
[60, 'm']
];
for (const [threshold, label] of buckets) {
if (secs >= threshold) {
const value = Math.floor(secs / threshold);
return `${value}${label} ago`;
}
}
// Below one minute.
return `${Math.max(1, secs)}s ago`;
},
/**
* Switch the active save slot. Persists the selection and reloads that
* slot's data from localStorage into the live game state, preserving