'use strict'; // Rain-data aggregator — sums per-location hourly precipitation, weighted // by per-hour probability, and stores both the raw and probability-weighted // values keyed by timestamp. sumRain/avgRain feed parameters.getRainIndex // which scales the predicted flow rate between nominalFlowMin and flowMax. class RainAggregator { constructor({ logger } = {}) { this.logger = logger; this.aggregatedOutput = {}; this.sumRain = 0; this.avgRain = 0; } // Returns the aggregated per-location object so callers can chain. // Mutates this.aggregatedOutput / sumRain / avgRain in place. update(value) { if (!value) return this.aggregatedOutput; const totalRaw = {}; const totalProb = {}; let numberOfLocations = 0; Object.entries(value).forEach(([locationKey, location]) => { numberOfLocations++; const slot = (this.aggregatedOutput[locationKey] = { tag: { latitude: location.latitude, longitude: location.longitude }, precipationRaw: {}, precipationProb: {}, }); Object.entries(location.hourly.time).forEach(([key, time]) => { const currTimestamp = new Date(time).getTime(); let probability = 100; if (typeof location.hourly.precipitation_probability !== 'undefined') { probability = location.hourly.precipitation_probability[key]; } if (probability > 0) probability /= 100; if (totalRaw[currTimestamp] === undefined) totalRaw[currTimestamp] = 0; if (totalProb[currTimestamp] === undefined) totalProb[currTimestamp] = 0; totalRaw[currTimestamp] += location.hourly.precipitation[key]; totalProb[currTimestamp] += location.hourly.precipitation[key] * probability; slot.precipationRaw[key] = { val: location.hourly.precipitation[key], time: currTimestamp }; slot.precipationProb[key] = { val: probability, time: currTimestamp }; }); }); this.sumRain = Object.values(totalProb).reduce((s, v) => s + v, 0); this.avgRain = numberOfLocations > 0 ? this.sumRain / numberOfLocations : 0; return this.aggregatedOutput; } } module.exports = RainAggregator;