src/curves/ loader + normalizer (with cross-pressure anomaly
detection) + reverseCurve helper
src/prediction/ predictors (predictFlow/Power/Ctrl) +
groupPredictors (lazy group-scope views) +
OperatingPoint (pressure-driven prediction setpoints)
src/drift/ DriftAssessor (per-metric drift) + PredictionHealth
(composes flow/power/pressure into HealthStatus +
confidence sibling — see OPEN_QUESTIONS 2026-05-10)
src/pressure/ VirtualPressureChildren (dashboard-sim) +
PressureInitialization (real-vs-virtual tracking) +
PressureRouter (dispatches by position)
src/state/ stateBindings (state.emitter listener helper) +
isOperationalState
src/measurement/ measurementHandlers (dispatcher for flow/power/temp/pressure)
src/flow/ flowController (handleInput body — execSequence,
execMovement, flowMovement, emergencystop)
src/display/ workingCurves (showWorkingCurves + showCoG admin)
src/commands/ canonical names: set.mode, cmd.startup/shutdown/estop,
set.setpoint, set.flow-setpoint,
data.simulate-measurement, query.curves, query.cog,
child.register. execSequence demuxes by payload.action
to canonical cmd.* handlers.
CONTRACT.md inputs/outputs/events/children surface
110 basic tests pass (100 new + 10 pre-existing).
specificClass.js / nodeClass.js untouched — integration in P5 wave 2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
104 lines
3.4 KiB
JavaScript
104 lines
3.4 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const PressureInitialization = require('../../src/pressure/pressureInitialization');
|
|
|
|
const SILENT = { warn() {}, debug() {} };
|
|
|
|
/* A tiny in-memory stand-in for MeasurementContainer's chained API. */
|
|
function makeFakeMeasurements() {
|
|
const store = new Map();
|
|
const key = (pos, childId) => `${pos}::${childId == null ? '*' : childId}`;
|
|
return {
|
|
_write(pos, childId, value) { store.set(key(pos, childId), value); },
|
|
type() { return this; },
|
|
variant() { return this; },
|
|
position(p) { this._pos = p; return this; },
|
|
child(c) { this._child = c; return this; },
|
|
getCurrentValue() {
|
|
const k = key(this._pos, this._child);
|
|
this._child = null;
|
|
const v = store.get(k);
|
|
if (v != null) return v;
|
|
// fallback to bare position when no child specified
|
|
return store.get(key(this._pos, null));
|
|
},
|
|
};
|
|
}
|
|
|
|
test('getStatus reports initialized:false when neither real nor virtual data present', () => {
|
|
const init = new PressureInitialization({
|
|
measurements: makeFakeMeasurements(),
|
|
virtualPressureChildIds: { upstream: 'sim-u', downstream: 'sim-d' },
|
|
logger: SILENT,
|
|
});
|
|
const s = init.getStatus();
|
|
assert.equal(s.initialized, false);
|
|
assert.equal(s.hasDifferential, false);
|
|
assert.equal(s.source, null);
|
|
});
|
|
|
|
test('registerReal then getStatus reports initialized:true for that position', () => {
|
|
const meas = makeFakeMeasurements();
|
|
const init = new PressureInitialization({
|
|
measurements: meas,
|
|
virtualPressureChildIds: { upstream: 'sim-u', downstream: 'sim-d' },
|
|
logger: SILENT,
|
|
});
|
|
|
|
init.registerReal('upstream', 'pt-101');
|
|
meas._write('upstream', 'pt-101', 5000);
|
|
|
|
const s = init.getStatus();
|
|
assert.equal(s.initialized, true);
|
|
assert.equal(s.hasUpstream, true);
|
|
assert.equal(s.hasDownstream, false);
|
|
assert.equal(s.hasDifferential, false);
|
|
assert.equal(s.source, 'upstream');
|
|
});
|
|
|
|
test('hasDifferential true only when both upstream + downstream have data', () => {
|
|
const meas = makeFakeMeasurements();
|
|
const init = new PressureInitialization({
|
|
measurements: meas,
|
|
virtualPressureChildIds: { upstream: 'sim-u', downstream: 'sim-d' },
|
|
logger: SILENT,
|
|
});
|
|
init.registerReal('upstream', 'pt-1');
|
|
meas._write('upstream', 'pt-1', 5000);
|
|
assert.equal(init.getStatus().hasDifferential, false);
|
|
|
|
init.registerReal('downstream', 'pt-2');
|
|
meas._write('downstream', 'pt-2', 7000);
|
|
const s = init.getStatus();
|
|
assert.equal(s.hasDifferential, true);
|
|
assert.equal(s.source, 'differential');
|
|
});
|
|
|
|
test('virtual fallback when no real children registered', () => {
|
|
const meas = makeFakeMeasurements();
|
|
const init = new PressureInitialization({
|
|
measurements: meas,
|
|
virtualPressureChildIds: { upstream: 'sim-u', downstream: 'sim-d' },
|
|
logger: SILENT,
|
|
});
|
|
meas._write('upstream', 'sim-u', 5000);
|
|
const s = init.getStatus();
|
|
assert.equal(s.hasUpstream, true);
|
|
assert.equal(s.source, 'upstream');
|
|
});
|
|
|
|
test('unregisterReal removes a tracked child id', () => {
|
|
const init = new PressureInitialization({
|
|
measurements: makeFakeMeasurements(),
|
|
virtualPressureChildIds: { upstream: 'sim-u', downstream: 'sim-d' },
|
|
logger: SILENT,
|
|
});
|
|
init.registerReal('upstream', 'pt-1');
|
|
assert.ok(init.realPressureChildIds.upstream.has('pt-1'));
|
|
init.unregisterReal('upstream', 'pt-1');
|
|
assert.ok(!init.realPressureChildIds.upstream.has('pt-1'));
|
|
});
|