/** * Simulation Statistics & History Tracking * Keeps full account of births, deaths, consumption, and temporal population data for charting. */ export class SimStats { constructor() { this.reset(); } reset() { this.startTime = Date.now(); this.elapsedSimTime = 0; // simulated seconds // Historical population records (sampled at 1Hz sim time) this.history = []; this.sampleTimer = 0; // Entity counters this.totalSheepBorn = 0; this.totalWolvesBorn = 0; this.totalPlantsGrown = 0; this.totalPlantsFromDecay = 0; this.totalSeedsSprouted = 0; // Death counters this.sheepKilledByWolves = 0; this.sheepStarved = 0; this.wolvesStarved = 0; this.plantsEaten = 0; this.plantsWithered = 0; // Peaks this.peakSheep = 0; this.peakWolves = 0; this.peakPlants = 0; // Extinction flag this.extinct = false; this.extinctionTime = 0; } update(dt, sheepCount, wolfCount, plantCount) { this.elapsedSimTime += dt; if (sheepCount > this.peakSheep) this.peakSheep = sheepCount; if (wolfCount > this.peakWolves) this.peakWolves = wolfCount; if (plantCount > this.peakPlants) this.peakPlants = plantCount; // Sample population every 1 simulated second for graphs this.sampleTimer += dt; if (this.sampleTimer >= 1.0) { this.sampleTimer -= 1.0; this.history.push({ time: Math.round(this.elapsedSimTime), sheep: sheepCount, wolves: wolfCount, plants: plantCount, }); // Keep up to 600 data points (10 minutes of active history) if (this.history.length > 600) { this.history.shift(); } } // Check for extinction event (both animal populations reach 0 after starting) if (!this.extinct && this.elapsedSimTime > 2.0 && sheepCount === 0 && wolfCount === 0) { this.extinct = true; this.extinctionTime = this.elapsedSimTime; } } recordSheepBirth(isInitial = false) { if (!isInitial) this.totalSheepBorn++; } recordWolfBirth(isInitial = false) { if (!isInitial) this.totalWolvesBorn++; } recordPlantSpawn(isFromDecay = false, isFromSeed = false) { this.totalPlantsGrown++; if (isFromDecay) this.totalPlantsFromDecay++; if (isFromSeed) this.totalSeedsSprouted++; } recordSheepDeath(cause = 'wolf') { if (cause === 'wolf') { this.sheepKilledByWolves++; } else { this.sheepStarved++; } } recordWolfDeath(cause = 'starvation') { this.wolvesStarved++; } recordPlantConsumed() { this.plantsEaten++; } recordPlantWithered() { this.plantsWithered++; } }