refactor(units): route all conversions through UnitPolicy.convert
Delete the legacy _convertUnitValue helper on the domain and the duplicate convertUnitValue export on curveNormalizer; both were identical to UnitPolicy.convert. Callers in flowController, the curve normalizer, and buildQHCurve now go through this.unitPolicy. The contract in .claude/refactor/CONTRACTS.md §6 named these as the target migration; this finishes the rollout for rotatingMachine. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,6 @@ const { UnitPolicy } = require('generalFunctions');
|
||||
const {
|
||||
normalizeMachineCurve,
|
||||
normalizeCurveSection,
|
||||
convertUnitValue,
|
||||
} = require('../../src/curves/curveNormalizer');
|
||||
|
||||
function makePolicy() {
|
||||
@@ -50,39 +49,33 @@ test('normalizeMachineCurve: converts pressure mbar -> Pa and flow m3/h -> m3/s'
|
||||
});
|
||||
|
||||
test('normalizeCurveSection: warns on cross-pressure median > 3x jump', () => {
|
||||
const policy = makePolicy();
|
||||
const logger = captureLogger();
|
||||
const section = {
|
||||
1000: { x: [0, 50, 100], y: [0, 5, 10] }, // median 5
|
||||
1100: { x: [0, 50, 100], y: [0, 50, 100] }, // median 50 (10x jump)
|
||||
};
|
||||
normalizeCurveSection(section, 'm3/h', 'm3/h', 'mbar', 'mbar', 'nq', logger);
|
||||
normalizeCurveSection(section, policy, 'm3/h', 'm3/h', 'mbar', 'mbar', 'nq', logger);
|
||||
const hit = logger.warns.find((w) => /Curve anomaly/.test(w));
|
||||
assert.ok(hit, `expected a Curve anomaly warning, got: ${JSON.stringify(logger.warns)}`);
|
||||
assert.match(hit, /pressure 1100/);
|
||||
});
|
||||
|
||||
test('normalizeCurveSection: does not warn on smooth progressions', () => {
|
||||
const policy = makePolicy();
|
||||
const logger = captureLogger();
|
||||
const section = {
|
||||
1000: { x: [0, 50, 100], y: [0, 5, 10] },
|
||||
1100: { x: [0, 50, 100], y: [0, 6, 11] },
|
||||
};
|
||||
normalizeCurveSection(section, 'm3/h', 'm3/h', 'mbar', 'mbar', 'nq', logger);
|
||||
normalizeCurveSection(section, policy, 'm3/h', 'm3/h', 'mbar', 'mbar', 'nq', logger);
|
||||
assert.equal(logger.warns.filter((w) => /Curve anomaly/.test(w)).length, 0);
|
||||
});
|
||||
|
||||
test('normalizeCurveSection: throws when x/y length mismatch', () => {
|
||||
const policy = makePolicy();
|
||||
assert.throws(
|
||||
() => normalizeCurveSection({ 1000: { x: [0, 50], y: [0, 5, 10] } }, 'm3/h', 'm3/s', 'mbar', 'Pa', 'nq', null),
|
||||
() => normalizeCurveSection({ 1000: { x: [0, 50], y: [0, 5, 10] } }, policy, 'm3/h', 'm3/s', 'mbar', 'Pa', 'nq', null),
|
||||
/Invalid nq section/
|
||||
);
|
||||
});
|
||||
|
||||
test('convertUnitValue: identity when units match or missing', () => {
|
||||
assert.equal(convertUnitValue(42, 'm3/h', 'm3/h'), 42);
|
||||
assert.equal(convertUnitValue(42, null, null), 42);
|
||||
});
|
||||
|
||||
test('convertUnitValue: throws on non-finite input', () => {
|
||||
assert.throws(() => convertUnitValue('not-a-number', 'm3/h', 'm3/s', 'test'), /not finite/);
|
||||
});
|
||||
|
||||
@@ -27,6 +27,10 @@ function makeHost({
|
||||
unitPolicy: {
|
||||
canonical: { flow: 'm3/s' },
|
||||
output: { flow: 'm3/h' },
|
||||
convert: (val, from, to, label) => {
|
||||
host.calls.convertUnit.push({ val, from, to, label });
|
||||
return val * 1000; // pretend m3/h -> m3/s factor
|
||||
},
|
||||
},
|
||||
isValidActionForMode: (action) => allowedActions.has(action),
|
||||
isValidSourceForMode: () => allowedSources,
|
||||
@@ -38,10 +42,6 @@ function makeHost({
|
||||
return { moved: sp };
|
||||
},
|
||||
calcCtrl: (canonicalFlow) => { host.calls.calcCtrl.push(canonicalFlow); return canonicalFlow / 2; },
|
||||
_convertUnitValue: (val, from, to, label) => {
|
||||
host.calls.convertUnit.push({ val, from, to, label });
|
||||
return val * 1000; // pretend m3/h -> m3/s factor
|
||||
},
|
||||
};
|
||||
return host;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user