Compare commits
2 Commits
428c611ec6
...
c99d24e4c6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c99d24e4c6 | ||
|
|
f9d1348fd0 |
@@ -206,21 +206,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"basin": {
|
"basin": {
|
||||||
"shape": {
|
"volume": {
|
||||||
"default": "cylindrical",
|
"default": "1",
|
||||||
"rules": {
|
"rules": {
|
||||||
"type": "enum",
|
"type": "number",
|
||||||
"values": [
|
"description": "Total volume of empty basin in m3"
|
||||||
{
|
}
|
||||||
"value": "cylindrical",
|
},
|
||||||
"description": "The wet well is primarily cylindrical."
|
"height": {
|
||||||
},
|
"default": "1",
|
||||||
{
|
"rules": {
|
||||||
"value": "rectangular",
|
"type": "number",
|
||||||
"description": "The wet well is rectangular or box shaped."
|
"description": "Total height of basin in m"
|
||||||
}
|
|
||||||
],
|
|
||||||
"description": "General geometry of the basin or wet well."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"levelUnit": {
|
"levelUnit": {
|
||||||
@@ -272,7 +269,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hydraulics": {
|
"hydraulics": {
|
||||||
|
|
||||||
"maxInflowRate": {
|
"maxInflowRate": {
|
||||||
"default": 200,
|
"default": 200,
|
||||||
"rules": {
|
"rules": {
|
||||||
@@ -281,6 +277,28 @@
|
|||||||
"description": "Maximum expected inflow during peak events (m3/h)."
|
"description": "Maximum expected inflow during peak events (m3/h)."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"refHeight": {
|
||||||
|
"default": "NAP",
|
||||||
|
"rules": {
|
||||||
|
"type": "enum",
|
||||||
|
"values": [
|
||||||
|
{
|
||||||
|
"value": "NAP",
|
||||||
|
"description": "NAP (Normaal Amsterdams Peil)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "EVRF",
|
||||||
|
"description": "EVRF (European Vertical Reference Frame)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "EGM2008",
|
||||||
|
"description": "EGM2008 / EGM96 (satellietmetingen) Geopotentieel model earth "
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
"description": "Reference height to use to identify the height vs other basins with. This will say something more about the expected pressure loss in m head"
|
||||||
|
}
|
||||||
|
},
|
||||||
"staticHead": {
|
"staticHead": {
|
||||||
"default": 12,
|
"default": 12,
|
||||||
"rules": {
|
"rules": {
|
||||||
|
|||||||
@@ -68,6 +68,23 @@ class Measurement {
|
|||||||
return this.values[this.values.length - 1];
|
return this.values[this.values.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLaggedValue(lag){
|
||||||
|
if(this.values.length <= lag) return null;
|
||||||
|
return this.values[this.values.length - lag];
|
||||||
|
}
|
||||||
|
|
||||||
|
getLaggedSample(lag){
|
||||||
|
if (lag < 0) throw new Error('lag must be >= 0');
|
||||||
|
const index = this.values.length - 1 - lag;
|
||||||
|
if (index < 0) return null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: this.values[index],
|
||||||
|
timestamp: this.timestamps[index],
|
||||||
|
unit: this.unit,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
getAverage() {
|
getAverage() {
|
||||||
if (this.values.length === 0) return null;
|
if (this.values.length === 0) return null;
|
||||||
const sum = this.values.reduce((acc, val) => acc + val, 0);
|
const sum = this.values.reduce((acc, val) => acc + val, 0);
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ class MeasurementContainer {
|
|||||||
throw new Error('Variant must be specified before position');
|
throw new Error('Variant must be specified before position');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._currentPosition = positionValue;
|
|
||||||
|
this._currentPosition = positionValue.toString().toLowerCase();;
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@@ -247,38 +248,65 @@ class MeasurementContainer {
|
|||||||
return measurement ? measurement.getAllValues() : null;
|
return measurement ? measurement.getAllValues() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getLaggedValue(lag = 1,requestedUnit = null ){
|
||||||
|
const measurement = this.get();
|
||||||
|
if (!measurement) return null;
|
||||||
|
|
||||||
|
const value = measurement.getLaggedSample(lag);
|
||||||
|
if (value === null) return null;
|
||||||
|
|
||||||
|
// Return as-is if no unit conversion requested
|
||||||
|
if (!requestedUnit) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert if needed
|
||||||
|
if (measurement.unit && requestedUnit !== measurement.unit) {
|
||||||
|
try {
|
||||||
|
return convertModule(value).from(measurement.unit).to(requestedUnit);
|
||||||
|
} catch (error) {
|
||||||
|
if (this.logger) {
|
||||||
|
this.logger.error(`Unit conversion failed: ${error.message}`);
|
||||||
|
}
|
||||||
|
return value; // Return original value if conversion fails
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Difference calculations between positions
|
// Difference calculations between positions
|
||||||
difference(requestedUnit = null) {
|
difference({ from = "downstream", to = "upstream", unit: requestedUnit } = {}) {
|
||||||
|
if (!this._currentType || !this._currentVariant) {
|
||||||
if (!this._currentType || !this._currentVariant) {
|
throw new Error("Type and variant must be specified for difference calculation");
|
||||||
throw new Error('Type and variant must be specified for difference calculation');
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
|
|
||||||
return {
|
|
||||||
value: downstreamValue - upstreamValue,
|
|
||||||
avgDiff: downstreamAvg - upstreamAvg,
|
|
||||||
unit: targetUnit
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const get = pos =>
|
||||||
|
this.measurements?.[this._currentType]?.[this._currentVariant]?.[pos] || null;
|
||||||
|
|
||||||
|
const a = get(from);
|
||||||
|
const b = get(to);
|
||||||
|
if (!a || !b || a.values.length === 0 || b.values.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetUnit = requestedUnit || a.unit || b.unit;
|
||||||
|
const aVal = this._convertValueToUnit(a.getCurrentValue(), a.unit, targetUnit);
|
||||||
|
const bVal = this._convertValueToUnit(b.getCurrentValue(), b.unit, targetUnit);
|
||||||
|
|
||||||
|
const aAvg = this._convertValueToUnit(a.getAverage(), a.unit, targetUnit);
|
||||||
|
const bAvg = this._convertValueToUnit(b.getAverage(), b.unit, targetUnit);
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: aVal - bVal,
|
||||||
|
avgDiff: aAvg - bAvg,
|
||||||
|
unit: targetUnit,
|
||||||
|
from,
|
||||||
|
to,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
_ensureChainIsValid() {
|
_ensureChainIsValid() {
|
||||||
if (!this._currentType || !this._currentVariant || !this._currentPosition) {
|
if (!this._currentType || !this._currentVariant || !this._currentPosition) {
|
||||||
|
|||||||
@@ -213,6 +213,10 @@ const pressureDiff = basicContainer
|
|||||||
|
|
||||||
console.log(`Pressure difference: ${pressureDiff.value} ${pressureDiff.unit}\n`);
|
console.log(`Pressure difference: ${pressureDiff.value} ${pressureDiff.unit}\n`);
|
||||||
|
|
||||||
|
//reversable difference
|
||||||
|
const deltaP = basicContainer.type("pressure").variant("measured").difference(); // defaults to downstream - upstream
|
||||||
|
const netFlow = basicContainer.type("flow").variant("measured").difference({ from: "upstream", to: "downstream" });
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// ADVANCED STATISTICS & HISTORY
|
// ADVANCED STATISTICS & HISTORY
|
||||||
// ====================================
|
// ====================================
|
||||||
@@ -248,6 +252,28 @@ const allValues = stats.getAllValues();
|
|||||||
console.log(` Samples: ${allValues.values.length}`);
|
console.log(` Samples: ${allValues.values.length}`);
|
||||||
console.log(` History: [${allValues.values.join(', ')}]\n`);
|
console.log(` History: [${allValues.values.join(', ')}]\n`);
|
||||||
|
|
||||||
|
console.log('--- Lagged sample comparison ---');
|
||||||
|
|
||||||
|
const latest = stats.getCurrentValue(); // existing helper
|
||||||
|
const prevSample = stats.getLaggedValue(1); // new helper
|
||||||
|
const prevPrevSample = stats.getLaggedValue(2); // optional
|
||||||
|
|
||||||
|
if (prevSample) {
|
||||||
|
const delta = latest - prevSample.value;
|
||||||
|
console.log(
|
||||||
|
`Current vs previous: ${latest} ${statsData.unit} (t=${stats.get().getLatestTimestamp()}) vs ` +
|
||||||
|
`${prevSample.value} ${prevSample.unit} (t=${prevSample.timestamp})`
|
||||||
|
);
|
||||||
|
console.log(`Δ = ${delta.toFixed(2)} ${statsData.unit}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevPrevSample) {
|
||||||
|
console.log(
|
||||||
|
`Previous vs 2-steps-back timestamps: ${new Date(prevSample.timestamp).toISOString()} vs ` +
|
||||||
|
`${new Date(prevPrevSample.timestamp).toISOString()}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// DYNAMIC UNIT MANAGEMENT
|
// DYNAMIC UNIT MANAGEMENT
|
||||||
// ====================================
|
// ====================================
|
||||||
@@ -299,8 +325,11 @@ basicContainer.getTypes().forEach(type => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
console.log('\n✅ All examples complete!\n');
|
console.log('\n✅ All examples complete!\n');
|
||||||
|
|
||||||
|
|
||||||
// ====================================
|
// ====================================
|
||||||
// BEST PRACTICES
|
// BEST PRACTICES
|
||||||
// ====================================
|
// ====================================
|
||||||
|
|||||||
Reference in New Issue
Block a user