P6: convert monster to BaseDomain + BaseNodeAdapter + concern split

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>
This commit is contained in:
znetsixe
2026-05-10 22:09:25 +02:00
parent 5a43f90569
commit 2a6a0bc34b
12 changed files with 710 additions and 1075 deletions

59
src/flow/flowTracker.js Normal file
View File

@@ -0,0 +1,59 @@
'use strict';
// Flow tracking — manual override + measured-child fan-in + effective
// blend (mean of the two when both present). Wraps the
// MeasurementContainer so the domain stays read-only on flow state.
const POSITIONS = ['upstream', 'downstream', 'atequipment'];
class FlowTracker {
constructor({ measurements, logger }) {
this.measurements = measurements;
this.logger = logger;
this.manualFlow = null;
}
updateManualFlow(payload = {}) {
const value = Number(payload.value);
if (!Number.isFinite(value)) return;
const unit = payload.unit || 'm3/h';
this.manualFlow = value;
this.measurements.type('flow').variant('manual').position('atequipment')
.value(value, Date.now(), unit);
}
handleMeasuredFlow(eventData) {
const value = Number(eventData?.value);
if (!Number.isFinite(value)) return;
const position = String(eventData.position || 'atequipment').toLowerCase();
const unit = eventData.unit || 'm3/h';
this.measurements.type('flow').variant('measured').position(position)
.value(value, eventData.timestamp || Date.now(), unit);
}
getMeasuredFlow() {
const values = [];
for (const pos of POSITIONS) {
const v = this.measurements.type('flow').variant('measured').position(pos).getCurrentValue();
if (Number.isFinite(v)) values.push(v);
}
if (!values.length) return null;
return values.reduce((s, c) => s + c, 0) / values.length;
}
getManualFlow() {
const v = this.measurements.type('flow').variant('manual').position('atequipment').getCurrentValue();
return Number.isFinite(v) ? v : null;
}
getEffectiveFlow() {
const measured = this.getMeasuredFlow();
const manual = this.getManualFlow();
if (measured != null && manual != null) return (measured + manual) / 2;
if (measured != null) return measured;
if (manual != null) return manual;
return 0;
}
}
module.exports = FlowTracker;