/**
* Cosmic Garden - Statistics Panel
* Tracks and displays game statistics
*/
const Stats = {
/**
* Initialize the stats panel
*/
init() {
this.render();
},
/**
* Render the stats panel
*/
render() {
const container = document.getElementById('stats-content');
if (!container) return;
container.innerHTML = `
Total Stardust Earned
0 ✨
Current Production
0 ✨/sec
Upgrades Purchased
0/${Object.keys(UPGRADES).length}
Achievements Unlocked
0/${Object.keys(ACHIEVEMENTS).length}
Total Golden Blooms Claimed
0
Production Boost
Inactive
Next Achievement
Loading...
`;
},
/**
* Update stats display
*/
update() {
// Total stardust
const totalStardustEl = document.getElementById('stat-total-stardust');
if (totalStardustEl) {
totalStardustEl.textContent = `${Game.formatNumber(Game.state.totalStardust)} ✨`;
}
// Current production
const productionEl = document.getElementById('stat-production');
if (productionEl) {
productionEl.textContent = `${Game.formatNumber(Game.getProductionPerSecond())} ✨/sec`;
}
// Total clicks
const clicksEl = document.getElementById('stat-clicks');
if (clicksEl) {
clicksEl.textContent = Game.formatNumber(Game.state.totalClicks);
}
// Click power
const clickPowerEl = document.getElementById('stat-click-power');
if (clickPowerEl) {
clickPowerEl.textContent = `${Game.formatNumber(Game.getClickPower())} ✨`;
}
// Time played
const timePlayedEl = document.getElementById('stat-time-played');
if (timePlayedEl) {
const elapsed = Math.floor((Date.now() - Game.state.startTime) / 1000);
timePlayedEl.textContent = this.formatTime(elapsed);
}
// Buildings owned
const buildingsEl = document.getElementById('stat-buildings');
if (buildingsEl) {
const total = Object.values(Game.state.buildings).reduce((a, b) => a + b, 0);
buildingsEl.textContent = total;
}
// Upgrades purchased
const upgradesEl = document.getElementById('stat-upgrades');
if (upgradesEl) {
upgradesEl.textContent = `${Game.state.upgrades.length}/${Object.keys(UPGRADES).length}`;
}
// Achievements unlocked
const achievementsEl = document.getElementById('stat-achievements');
if (achievementsEl) {
achievementsEl.textContent = `${Achievements.getCount()}/${Achievements.getTotal()}`;
}
// Total Golden Blooms claimed
const goldenBloomsEl = document.getElementById('stat-golden-blooms');
if (goldenBloomsEl) {
goldenBloomsEl.textContent = Game.state.goldenBlooms.totalClaimed || 0;
}
// Production boost status + progress bar
const boostInfo = Game.getProductionBoostInfo();
const boostEl = document.getElementById('stat-production-boost');
const boostProgressEl = document.getElementById('stat-boost-progress');
if (boostEl) {
if (boostInfo.active) {
boostEl.textContent = `Active (${boostInfo.remaining}s)`;
if (boostProgressEl) {
boostProgressEl.style.width = `${Math.min(100, (boostInfo.remaining / 30) * 100)}%`;
}
} else {
boostEl.textContent = 'Inactive';
if (boostProgressEl) {
boostProgressEl.style.width = '0%';
}
}
}
// Game progress (based on total stardust milestones)
const progressBarEl = document.getElementById('stat-progress-bar');
if (progressBarEl) {
const progress = this.calculateProgress();
progressBarEl.style.width = `${progress}%`;
}
// Next achievement tracking
this.updateNextAchievement();
},
/**
* Update the next achievement display with progress bar
*/
updateNextAchievement() {
const nextEl = document.getElementById('stat-next-achievement');
const progressEl = document.getElementById('stat-achievement-progress');
if (!nextEl) return;
// Find the closest unachieved milestone
let closest = null;
let closestProgress = -1;
for (const [id, achievement] of Object.entries(ACHIEVEMENTS)) {
if (Game.state.achievements.includes(id)) continue;
const result = this.calculateAchievementProgress(achievement);
if (result && result.progress > closestProgress) {
closestProgress = result.progress;
closest = { ...result, name: achievement.name, icon: achievement.icon };
}
}
if (closest) {
nextEl.textContent = `${closest.icon} ${closest.name}`;
if (progressEl) {
progressEl.style.width = `${Math.min(100, Math.max(0, closest.progress))}%`;
}
} else {
nextEl.textContent = 'All achievements unlocked! 🎉';
if (progressEl) {
progressEl.style.width = '100%';
}
}
},
/**
* Calculate progress toward a specific achievement
*/
calculateAchievementProgress(achievement) {
const state = Game.state;
// Click achievements
if (achievement.id === 'firstClick') return { current: state.totalClicks, target: 1, progress: Math.min(100, (state.totalClicks / 1) * 100) };
if (achievement.id === 'clicker') return { current: state.totalClicks, target: 100, progress: Math.min(100, (state.totalClicks / 100) * 100) };
if (achievement.id === 'spammer') return { current: state.totalClicks, target: 1000, progress: Math.min(100, (state.totalClicks / 1000) * 100) };
if (achievement.id === 'clickMaster') return { current: state.totalClicks, target: 10000, progress: Math.min(100, (state.totalClicks / 10000) * 100) };
// Stardust achievements
if (achievement.id === 'dustCollector') return { current: state.totalStardust, target: 1000, progress: Math.min(100, (state.totalStardust / 1000) * 100) };
if (achievement.id === 'stardustMagnate') return { current: state.totalStardust, target: 100000, progress: Math.min(100, (state.totalStardust / 100000) * 100) };
if (achievement.id === 'cosmicTycoon') return { current: state.totalStardust, target: 10000000, progress: Math.min(100, (state.totalStardust / 10000000) * 100) };
if (achievement.id === 'galaxyBaron') return { current: state.totalStardust, target: 1000000000, progress: Math.min(100, (state.totalStardust / 1000000000) * 100) };
// Building achievements
if (achievement.id === 'firstPlant') {
const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0);
return { current: totalBuildings, target: 1, progress: Math.min(100, (totalBuildings / 1) * 100) };
}
if (achievement.id === 'gardenStart') {
const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0);
return { current: totalBuildings, target: 10, progress: Math.min(100, (totalBuildings / 10) * 100) };
}
if (achievement.id === 'gardenCenter') {
const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0);
return { current: totalBuildings, target: 50, progress: Math.min(100, (totalBuildings / 50) * 100) };
}
if (achievement.id === 'cosmicGarden') {
const totalBuildings = Object.values(state.buildings).reduce((a, b) => a + b, 0);
return { current: totalBuildings, target: 100, progress: Math.min(100, (totalBuildings / 100) * 100) };
}
// Specific building achievements
if (achievement.id === 'sproutFarmer') return { current: state.buildings.starSprout || 0, target: 25, progress: Math.min(100, ((state.buildings.starSprout || 0) / 25) * 100) };
if (achievement.id === 'bloomGarden') return { current: state.buildings.moonBloom || 0, target: 25, progress: Math.min(100, ((state.buildings.moonBloom || 0) / 25) * 100) };
if (achievement.id === 'solarPowered') return { current: state.buildings.solarLeaf || 0, target: 25, progress: Math.min(100, ((state.buildings.solarLeaf || 0) / 25) * 100) };
if (achievement.id === 'voidWeaver') return { current: state.buildings.voidFern || 0, target: 25, progress: Math.min(100, ((state.buildings.voidFern || 0) / 25) * 100) };
if (achievement.id === 'supernovaGrowth') return { current: state.buildings.supernovaSeed || 0, target: 25, progress: Math.min(100, ((state.buildings.supernovaSeed || 0) / 25) * 100) };
// Production achievements
if (achievement.id === 'steadyStream') {
const prod = Game.getProductionPerSecond();
return { current: prod, target: 100, progress: Math.min(100, (prod / 100) * 100) };
}
if (achievement.id === 'rushingRiver') {
const prod = Game.getProductionPerSecond();
return { current: prod, target: 1000, progress: Math.min(100, (prod / 1000) * 100) };
}
if (achievement.id === 'cosmicFlood') {
const prod = Game.getProductionPerSecond();
return { current: prod, target: 100000, progress: Math.min(100, (prod / 100000) * 100) };
}
// Prestige achievements
if (achievement.id === 'firstPrestige') return { current: state.prestigeCount || 0, target: 1, progress: Math.min(100, ((state.prestigeCount || 0) / 1) * 100) };
if (achievement.id === 'stellarAdaptation') return { current: state.prestigeCount || 0, target: 5, progress: Math.min(100, ((state.prestigeCount || 0) / 5) * 100) };
if (achievement.id === 'cosmicAscension') return { current: state.prestigeCount || 0, target: 10, progress: Math.min(100, ((state.prestigeCount || 0) / 10) * 100) };
if (achievement.id === 'eternalGardener') return { current: state.totalPrestigeEssence || 0, target: 100, progress: Math.min(100, ((state.totalPrestigeEssence || 0) / 100) * 100) };
if (achievement.id === 'quantumGrowth') return { current: state.totalPrestigeEssence || 0, target: 1000, progress: Math.min(100, ((state.totalPrestigeEssence || 0) / 1000) * 100) };
// Click power achievements
if (achievement.id === 'powerfulHarvester') {
const cp = Game.getClickPower();
return { current: cp, target: 1000, progress: Math.min(100, (cp / 1000) * 100) };
}
if (achievement.id === 'divineTouch') {
const cp = Game.getClickPower();
return { current: cp, target: 10000, progress: Math.min(100, (cp / 10000) * 100) };
}
// Time-based achievement
if (achievement.id === 'dedicatedGardener') {
const elapsed = Date.now() - state.startTime;
return { current: elapsed, target: 3600000, progress: Math.min(100, (elapsed / 3600000) * 100) };
}
return null;
},
/**
* Format elapsed time as HH:MM:SS
*/
formatTime(seconds) {
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
if (hours > 0) {
return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;
}
return `${minutes}:${secs.toString().padStart(2, '0')}`;
},
/**
* Calculate game progress percentage
* Based on total stardust earned vs all building costs combined
*/
calculateProgress() {
let totalCost = 0;
for (const building of Object.values(BUILDINGS)) {
// Approximate cost to buy one of each building
totalCost += building.baseCost;
}
// Add upgrade costs
for (const upgrade of Object.values(UPGRADES)) {
totalCost += upgrade.cost;
}
const progress = Math.min(100, (Game.state.totalStardust / totalCost) * 100);
return Math.round(progress);
}
};
window.Stats = Stats;