Files
generalFunctions/helper/measurements/Measurement.js
2025-05-26 17:09:18 +02:00

188 lines
5.2 KiB
JavaScript

// Add unit conversion support
const convertModule = require('../../../convert/dependencies/index');
class Measurement {
constructor(type, variant, position, windowSize) {
this.type = type; // e.g. 'pressure', 'flow', etc.
this.variant = variant; // e.g. 'predicted' or 'measured', etc..
this.position = position; // Downstream or upstream of parent object
this.windowSize = windowSize; // Rolling window size
// Place all data inside an array
this.values = []; // Array to store all values
this.timestamps = []; // Array to store all timestamps
// Unit tracking
this.unit = null; // Current unit of measurement
// For tracking differences if this is a calculated difference measurement
this.isDifference = false;
this.sourcePositions = [];
}
// -- Updater methods --
setType(type) {
this.type = type;
return this;
}
setVariant(variant) {
this.variant = variant;
return this;
}
setPosition(position) {
this.position = position;
return this;
}
setValue(value, timestamp = Date.now()) {
/*
if (value === undefined || value === null) {
value = null ;
//throw new Error('Value cannot be null or undefined');
}
*/
//shift the oldest value
if(this.values.length >= this.windowSize){
this.values.shift();
this.timestamps.shift();
}
//push the new value
this.values.push(value);
this.timestamps.push(timestamp);
return this;
}
setUnit(unit) {
this.unit = unit;
return this;
}
// -- Getter methods --
getCurrentValue() {
if (this.values.length === 0) return null;
return this.values[this.values.length - 1];
}
getAverage() {
if (this.values.length === 0) return null;
const sum = this.values.reduce((acc, val) => acc + val, 0);
return sum / this.values.length;
}
getMin() {
if (this.values.length === 0) return null;
return Math.min(...this.values);
}
getMax() {
if (this.values.length === 0) return null;
return Math.max(...this.values);
}
getAllValues() {
return {
values: [...this.values],
timestamps: [...this.timestamps],
unit: this.unit
};
}
// -- Position-based methods --
// Create a new measurement that is the difference between two positions
static createDifference(upstreamMeasurement, downstreamMeasurement) {
console.log('hello:');
if (upstreamMeasurement.type !== downstreamMeasurement.type ||
upstreamMeasurement.variant !== downstreamMeasurement.variant) {
throw new Error('Cannot calculate difference between different measurement types or variants');
}
// Ensure units match
let downstream = downstreamMeasurement;
if (upstreamMeasurement.unit && downstream.unit &&
upstreamMeasurement.unit !== downstream.unit) {
downstream = downstream.convertTo(upstreamMeasurement.unit);
}
// Create a new difference measurement
const diffMeasurement = new Measurement(
upstreamMeasurement.type,
upstreamMeasurement.variant,
'difference',
Math.min(upstreamMeasurement.windowSize, downstream.windowSize)
);
// Mark as a difference measurement and keep track of sources
diffMeasurement.isDifference = true;
diffMeasurement.sourcePositions = ['upstream', 'downstream'];
// Calculate all differences where timestamps match
const upValues = upstreamMeasurement.getAllValues();
const downValues = downstream.getAllValues();
// Match timestamps and calculate differences
for (let i = 0; i < upValues.timestamps.length; i++) {
const upTimestamp = upValues.timestamps[i];
const downIndex = downValues.timestamps.indexOf(upTimestamp);
if (downIndex !== -1) {
const diff = upValues.values[i] - downValues.values[downIndex];
diffMeasurement.setValue(diff, upTimestamp);
}
}
diffMeasurement.setUnit(upstreamMeasurement.unit);
return diffMeasurement;
}
// -- Additional getter methods --
getLatestTimestamp() {
if (this.timestamps.length === 0) return null;
return this.timestamps[this.timestamps.length - 1];
}
getValueAtTimestamp(timestamp) {
const index = this.timestamps.indexOf(timestamp);
if (index === -1) return null;
return this.values[index];
}
// -- Unit conversion methods --
convertTo(targetUnit) {
if (!this.unit) {
throw new Error('Current unit not set, cannot convert');
}
try {
const convertedValues = this.values.map(value =>
convertModule.convert(value).from(this.unit).to(targetUnit)
);
const newMeasurement = new Measurement(
this.type,
this.variant,
this.position,
this.windowSize
);
// Copy values and timestamps
newMeasurement.values = convertedValues;
newMeasurement.timestamps = [...this.timestamps];
newMeasurement.unit = targetUnit;
return newMeasurement;
} catch (error) {
throw new Error(`Unit conversion failed: ${error.message}`);
}
}
}
module.exports = Measurement;