Updated distance in measurement helper so its a settable compoment. See example.js file in measurement helper folder
This commit is contained in:
@@ -3,15 +3,16 @@ const EventEmitter = require('events');
|
||||
const convertModule = require('../convert/index');
|
||||
|
||||
class MeasurementContainer {
|
||||
constructor(options = {}) {
|
||||
constructor(options = {},logger) {
|
||||
this.emitter = new EventEmitter();
|
||||
this.measurements = {};
|
||||
this.windowSize = options.windowSize || 10; // Default window size
|
||||
|
||||
|
||||
// For chaining context
|
||||
this._currentType = null;
|
||||
this._currentVariant = null;
|
||||
this._currentPosition = null;
|
||||
this._currentDistance = null;
|
||||
this._unit = null;
|
||||
|
||||
// Default units for each measurement type
|
||||
@@ -24,11 +25,11 @@ class MeasurementContainer {
|
||||
length: 'm',
|
||||
...options.defaultUnits // Allow override
|
||||
};
|
||||
|
||||
|
||||
// Auto-conversion settings
|
||||
this.autoConvert = options.autoConvert !== false; // Default to true
|
||||
this.preferredUnits = options.preferredUnits || {}; // Per-measurement overrides
|
||||
|
||||
|
||||
// For chaining context
|
||||
this._currentType = null;
|
||||
this._currentVariant = null;
|
||||
@@ -39,23 +40,23 @@ class MeasurementContainer {
|
||||
this.childId = null;
|
||||
this.childName = null;
|
||||
this.parentRef = null;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// NEW: Methods to set child context
|
||||
setChildId(childId) {
|
||||
this.childId = childId;
|
||||
return this;
|
||||
this.childId = childId;
|
||||
return this;
|
||||
}
|
||||
|
||||
setChildName(childName) {
|
||||
this.childName = childName;
|
||||
return this;
|
||||
this.childName = childName;
|
||||
return this;
|
||||
}
|
||||
|
||||
setParentRef(parent) {
|
||||
this.parentRef = parent;
|
||||
return this;
|
||||
this.parentRef = parent;
|
||||
return this;
|
||||
}
|
||||
|
||||
// New method to set preferred units
|
||||
@@ -66,9 +67,9 @@ class MeasurementContainer {
|
||||
|
||||
// Get the target unit for a measurement type
|
||||
_getTargetUnit(measurementType) {
|
||||
return this.preferredUnits[measurementType] ||
|
||||
this.defaultUnits[measurementType] ||
|
||||
null;
|
||||
return this.preferredUnits[measurementType] ||
|
||||
this.defaultUnits[measurementType] ||
|
||||
null;
|
||||
}
|
||||
|
||||
// Chainable methods
|
||||
@@ -93,78 +94,84 @@ class MeasurementContainer {
|
||||
throw new Error('Variant must be specified before position');
|
||||
}
|
||||
|
||||
// Turn string positions into numeric values
|
||||
if (typeof positionValue == "string") {
|
||||
positionValue = this._convertPositionStr2Num(positionValue);
|
||||
this._currentPosition = positionValue;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
distance(distance) {
|
||||
// If distance is not provided, derive from positionVsParent
|
||||
if(distance === null) {
|
||||
distance = this._convertPositionStr2Num(this._currentPosition);
|
||||
}
|
||||
|
||||
this._currentPosition = positionValue;
|
||||
this._currentDistance = distance;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
// ENHANCED: Update your existing value method
|
||||
value(val, timestamp = Date.now(), sourceUnit = null) {
|
||||
if (!this._ensureChainIsValid()) return this;
|
||||
if (!this._ensureChainIsValid()) return this;
|
||||
|
||||
const measurement = this._getOrCreateMeasurement();
|
||||
const targetUnit = this._getTargetUnit(this._currentType);
|
||||
|
||||
let convertedValue = val;
|
||||
let finalUnit = sourceUnit || targetUnit;
|
||||
|
||||
const measurement = this._getOrCreateMeasurement();
|
||||
const targetUnit = this._getTargetUnit(this._currentType);
|
||||
|
||||
let convertedValue = val;
|
||||
let finalUnit = sourceUnit || targetUnit;
|
||||
|
||||
// Auto-convert if enabled and units are specified
|
||||
if (this.autoConvert && sourceUnit && targetUnit && sourceUnit !== targetUnit) {
|
||||
try {
|
||||
convertedValue = convertModule(val).from(sourceUnit).to(targetUnit);
|
||||
finalUnit = targetUnit;
|
||||
|
||||
if (this.logger) {
|
||||
this.logger.debug(`Auto-converted ${val} ${sourceUnit} to ${convertedValue} ${targetUnit}`);
|
||||
// Auto-convert if enabled and units are specified
|
||||
if (this.autoConvert && sourceUnit && targetUnit && sourceUnit !== targetUnit) {
|
||||
try {
|
||||
convertedValue = convertModule(val).from(sourceUnit).to(targetUnit);
|
||||
finalUnit = targetUnit;
|
||||
|
||||
if (this.logger) {
|
||||
this.logger.debug(`Auto-converted ${val} ${sourceUnit} to ${convertedValue} ${targetUnit}`);
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.logger) {
|
||||
this.logger.warn(`Auto-conversion failed from ${sourceUnit} to ${targetUnit}: ${error.message}`);
|
||||
}
|
||||
convertedValue = val;
|
||||
finalUnit = sourceUnit;
|
||||
}
|
||||
} catch (error) {
|
||||
if (this.logger) {
|
||||
this.logger.warn(`Auto-conversion failed from ${sourceUnit} to ${targetUnit}: ${error.message}`);
|
||||
}
|
||||
convertedValue = val;
|
||||
finalUnit = sourceUnit;
|
||||
}
|
||||
}
|
||||
|
||||
measurement.setValue(convertedValue, timestamp);
|
||||
measurement.setValue(convertedValue, timestamp);
|
||||
|
||||
if (finalUnit && !measurement.unit) {
|
||||
measurement.setUnit(finalUnit);
|
||||
}
|
||||
|
||||
if (finalUnit && !measurement.unit) {
|
||||
measurement.setUnit(finalUnit);
|
||||
}
|
||||
// ENHANCED: Emit event with rich context
|
||||
const eventData = {
|
||||
value: convertedValue,
|
||||
originalValue: val,
|
||||
unit: finalUnit,
|
||||
sourceUnit: sourceUnit,
|
||||
timestamp,
|
||||
position: this._currentPosition,
|
||||
distance: this._currentDistance,
|
||||
variant: this._currentVariant,
|
||||
type: this._currentType,
|
||||
// NEW: Enhanced context
|
||||
childId: this.childId,
|
||||
childName: this.childName,
|
||||
parentRef: this.parentRef,
|
||||
};
|
||||
|
||||
// ENHANCED: Emit event with rich context
|
||||
const eventData = {
|
||||
value: convertedValue,
|
||||
originalValue: val,
|
||||
unit: finalUnit,
|
||||
sourceUnit: sourceUnit,
|
||||
timestamp,
|
||||
position: this._currentPosition,
|
||||
variant: this._currentVariant,
|
||||
type: this._currentType,
|
||||
// NEW: Enhanced context
|
||||
childId: this.childId,
|
||||
childName: this.childName,
|
||||
parentRef: this.parentRef
|
||||
};
|
||||
// Emit the exact event your parent expects
|
||||
this.emitter.emit(`${this._currentType}.${this._currentVariant}.${this._currentPosition}`, eventData);
|
||||
console.log(`Emitted event: ${this._currentType}.${this._currentVariant}.${this._currentPosition}`, eventData);
|
||||
|
||||
// Emit the exact event your parent expects
|
||||
this.emitter.emit(`${this._currentType}.${this._currentVariant}.${this._convertPositionNum2Str(this._currentPosition)}`, eventData);
|
||||
this.emitter.emit(`${this._currentType}.${this._currentVariant}.${this._currentPosition}`, eventData);
|
||||
console.log(`Emitted event: ${this._currentType}.${this._currentVariant}.${this._currentPosition}`, eventData);
|
||||
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
unit(unitName) {
|
||||
if (!this._ensureChainIsValid()) return this;
|
||||
|
||||
|
||||
const measurement = this._getOrCreateMeasurement();
|
||||
measurement.setUnit(unitName);
|
||||
this._unit = unitName;
|
||||
@@ -180,7 +187,7 @@ class MeasurementContainer {
|
||||
getCurrentValue(requestedUnit = null) {
|
||||
const measurement = this.get();
|
||||
if (!measurement) return null;
|
||||
|
||||
|
||||
const value = measurement.getCurrentValue();
|
||||
if (value === null) return null;
|
||||
|
||||
@@ -207,7 +214,7 @@ class MeasurementContainer {
|
||||
getAverage(requestedUnit = null) {
|
||||
const measurement = this.get();
|
||||
if (!measurement) return null;
|
||||
|
||||
|
||||
const avgValue = measurement.getAverage();
|
||||
if (avgValue === null) return null;
|
||||
|
||||
@@ -244,34 +251,24 @@ class MeasurementContainer {
|
||||
|
||||
// Difference calculations between positions
|
||||
difference(requestedUnit = null) {
|
||||
|
||||
if (!this._currentType || !this._currentVariant) {
|
||||
throw new Error('Type and variant must be specified for difference calculation');
|
||||
}
|
||||
|
||||
const savedPosition = this._currentPosition;
|
||||
|
||||
// Get upstream and downstream measurements
|
||||
const positions = this.getPositions();
|
||||
|
||||
this._currentPosition = Math.min(...positions);
|
||||
const upstream = this.get();
|
||||
|
||||
this._currentPosition = Math.max(...positions);
|
||||
const downstream = this.get();
|
||||
|
||||
this._currentPosition = savedPosition;
|
||||
}
|
||||
const upstream = this.measurements?.[this._currentType]?.[this._currentVariant]?.['upstream'] || null;
|
||||
const downstream = this.measurements?.[this._currentType]?.[this._currentVariant]?.['downstream'] || null;
|
||||
|
||||
if (!upstream || !downstream || upstream.values.length === 0 || downstream.values.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// Get target unit for conversion
|
||||
const targetUnit = requestedUnit || upstream.unit || downstream.unit;
|
||||
|
||||
|
||||
// Get values in the same unit
|
||||
const upstreamValue = this._convertValueToUnit(upstream.getCurrentValue(), upstream.unit, targetUnit);
|
||||
const downstreamValue = this._convertValueToUnit(downstream.getCurrentValue(), downstream.unit, targetUnit);
|
||||
|
||||
|
||||
const upstreamAvg = this._convertValueToUnit(upstream.getAverage(), upstream.unit, targetUnit);
|
||||
const downstreamAvg = this._convertValueToUnit(downstream.getAverage(), downstream.unit, targetUnit);
|
||||
|
||||
@@ -298,21 +295,22 @@ class MeasurementContainer {
|
||||
if (!this.measurements[this._currentType]) {
|
||||
this.measurements[this._currentType] = {};
|
||||
}
|
||||
|
||||
|
||||
if (!this.measurements[this._currentType][this._currentVariant]) {
|
||||
this.measurements[this._currentType][this._currentVariant] = {};
|
||||
}
|
||||
|
||||
|
||||
if (!this.measurements[this._currentType][this._currentVariant][this._currentPosition]) {
|
||||
this.measurements[this._currentType][this._currentVariant][this._currentPosition] =
|
||||
this.measurements[this._currentType][this._currentVariant][this._currentPosition] =
|
||||
new MeasurementBuilder()
|
||||
.setType(this._currentType)
|
||||
.setVariant(this._currentVariant)
|
||||
.setPosition(this._currentPosition)
|
||||
.setWindowSize(this.windowSize)
|
||||
.setDistance(this._currentDistance)
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
return this.measurements[this._currentType][this._currentVariant][this._currentPosition];
|
||||
}
|
||||
|
||||
@@ -325,25 +323,21 @@ class MeasurementContainer {
|
||||
if (!this._currentType) {
|
||||
throw new Error('Type must be specified before listing variants');
|
||||
}
|
||||
return this.measurements[this._currentType] ?
|
||||
return this.measurements[this._currentType] ?
|
||||
Object.keys(this.measurements[this._currentType]) : [];
|
||||
}
|
||||
|
||||
getPositions(asNumber = false) {
|
||||
getPositions() {
|
||||
if (!this._currentType || !this._currentVariant) {
|
||||
throw new Error('Type and variant must be specified before listing positions');
|
||||
}
|
||||
|
||||
if (!this.measurements[this._currentType] ||
|
||||
!this.measurements[this._currentType][this._currentVariant]) {
|
||||
|
||||
if (!this.measurements[this._currentType] ||
|
||||
!this.measurements[this._currentType][this._currentVariant]) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (asNumber) {
|
||||
return Object.keys(this.measurements[this._currentType][this._currentVariant]);
|
||||
}
|
||||
|
||||
return Object.keys(this.measurements[this._currentType][this._currentVariant]).map(this._convertPositionNum2Str);
|
||||
return Object.keys(this.measurements[this._currentType][this._currentVariant]);
|
||||
}
|
||||
|
||||
clear() {
|
||||
@@ -408,7 +402,7 @@ class MeasurementContainer {
|
||||
const best = convertModule(currentValue)
|
||||
.from(measurement.unit)
|
||||
.toBest({ exclude: excludeUnits });
|
||||
|
||||
|
||||
return best;
|
||||
} catch (error) {
|
||||
if (this.logger) {
|
||||
@@ -419,16 +413,14 @@ class MeasurementContainer {
|
||||
}
|
||||
|
||||
_convertPositionStr2Num(positionString) {
|
||||
|
||||
switch (positionString) {
|
||||
|
||||
switch(positionString) {
|
||||
case "atEquipment":
|
||||
return 0;
|
||||
case "upstream":
|
||||
return Number.POSITIVE_INFINITY;
|
||||
case "downstream":
|
||||
return Number.NEGATIVE_INFINITY;
|
||||
|
||||
|
||||
default:
|
||||
if (this.logger) {
|
||||
this.logger.error(`Invalid positionVsParent provided: ${positionString}`);
|
||||
@@ -438,18 +430,15 @@ class MeasurementContainer {
|
||||
}
|
||||
|
||||
_convertPositionNum2Str(positionValue) {
|
||||
if (positionValue === 0) {
|
||||
switch (positionValue) {
|
||||
case 0:
|
||||
return "atEquipment";
|
||||
}
|
||||
if (positionValue < 0) {
|
||||
case (positionValue < 0):
|
||||
return "upstream";
|
||||
}
|
||||
if (positionValue > 0) {
|
||||
case (positionValue > 0):
|
||||
return "downstream";
|
||||
}
|
||||
|
||||
if (this.logger) {
|
||||
this.logger.error(`Invalid position provided: ${positionValue}`);
|
||||
default:
|
||||
console.log(`Invalid position provided: ${positionValue}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user