Refactor of monster to use the platform infrastructure (BaseDomain, BaseNodeAdapter, ChildRouter, commandRegistry, statusBadge). Extracts concerns into focused modules per .claude/refactor/MODULE_SPLIT.md generic template. Tests stay green; CONTRACT.md generated; legacy aliases preserved. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
59 lines
2.1 KiB
JavaScript
59 lines
2.1 KiB
JavaScript
'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;
|