/** * Read-only snapshots of the active machine curves and the centre-of-gravity * statistics. These back the rotatingMachine admin endpoints used by the * editor (`/rotatingMachine/working-curves`, `/rotatingMachine/cog`). * * Both functions accept a single `predictors` argument — an object describing * the current curve state. By taking everything via that one parameter the * helpers stay pure and trivially testable with a plain fixture; the host * just passes itself (or a slim adapter) in. * * Expected shape of `predictors`: * { * hasCurve: boolean, * predictFlow, predictPower, // generalFunctions/predict instances * getCurrentCurves(): { powerCurve, flowCurve }, * calcCog(): { cog, cogIndex, NCog, minEfficiency }, * cog, cogIndex, NCog, * minEfficiency, * currentEfficiencyCurve, * absDistFromPeak, relDistFromPeak, * } */ const NO_CURVE_ERROR = 'No curve data available'; function showCoG(predictors) { if (!predictors || !predictors.hasCurve) { return { error: NO_CURVE_ERROR, cog: 0, NCog: 0, cogIndex: 0 }; } const { cog, cogIndex, NCog, minEfficiency } = predictors.calcCog(); return { cog, cogIndex, NCog, NCogPercent: Math.round(NCog * 100 * 100) / 100, minEfficiency, currentEfficiencyCurve: predictors.currentEfficiencyCurve, absDistFromPeak: predictors.absDistFromPeak, relDistFromPeak: predictors.relDistFromPeak, }; } function showWorkingCurves(predictors) { if (!predictors || !predictors.hasCurve) { return { error: NO_CURVE_ERROR }; } const { powerCurve, flowCurve } = predictors.getCurrentCurves(); return { powerCurve, flowCurve, cog: predictors.cog, cogIndex: predictors.cogIndex, NCog: predictors.NCog, minEfficiency: predictors.minEfficiency, currentEfficiencyCurve: predictors.currentEfficiencyCurve, absDistFromPeak: predictors.absDistFromPeak, relDistFromPeak: predictors.relDistFromPeak, }; } module.exports = { showWorkingCurves, showCoG };