forked from RnD/rotatingMachine
first commit
This commit is contained in:
814
dependencies/machine/machine.js
vendored
Normal file
814
dependencies/machine/machine.js
vendored
Normal file
@@ -0,0 +1,814 @@
|
||||
/**
|
||||
* @file machine.js
|
||||
*
|
||||
* Permission is hereby granted to any person obtaining a copy of this software
|
||||
* and associated documentation files (the "Software"), to use it for personal
|
||||
* or non-commercial purposes, with the following restrictions:
|
||||
*
|
||||
* 1. **No Copying or Redistribution**: The Software or any of its parts may not
|
||||
* be copied, merged, distributed, sublicensed, or sold without explicit
|
||||
* prior written permission from the author.
|
||||
*
|
||||
* 2. **Commercial Use**: Any use of the Software for commercial purposes requires
|
||||
* a valid license, obtainable only with the explicit consent of the author.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Ownership of this code remains solely with the original author. Unauthorized
|
||||
* use of this Software is strictly prohibited.
|
||||
*
|
||||
* @summary A class to interact and manipulate machines with a non-euclidian curve
|
||||
* @description A class to interact and manipulate machines with a non-euclidian curve
|
||||
* @module machine
|
||||
* @exports machine
|
||||
* @version 0.1.0
|
||||
* @since 0.1.0
|
||||
*
|
||||
* Author:
|
||||
* - Rene De Ren
|
||||
* Email:
|
||||
* - rene@thegoldenbasket.nl
|
||||
*
|
||||
* Add functionality later
|
||||
// -------- Operational Metrics -------- //
|
||||
maintenanceAlert: this.state.checkMaintenanceStatus()
|
||||
|
||||
|
||||
*/
|
||||
|
||||
//load local dependencies
|
||||
const EventEmitter = require('events');
|
||||
const Logger = require('../../../generalFunctions/helper/logger');
|
||||
const State = require('../../../generalFunctions/helper/state/state');
|
||||
const Predict = require('../../../predict/dependencies/predict/predict_class');
|
||||
const { MeasurementContainer } = require('../../../generalFunctions/helper/measurements/index');
|
||||
const Interpolation = require('../../../predict/dependencies/predict/interpolation');
|
||||
|
||||
//load all config modules
|
||||
const defaultConfig = require('../rotatingMachine/rotatingMachineConfig.json');
|
||||
const ConfigUtils = require('../../../generalFunctions/helper/configUtils');
|
||||
|
||||
//load registration utility
|
||||
const ChildRegistrationUtils = require('../../../generalFunctions/helper/childRegistrationUtils');
|
||||
const ErrorMetrics = require('../../../generalFunctions/helper/nrmse/errorMetrics');
|
||||
|
||||
class Machine {
|
||||
|
||||
/*------------------- Construct and set vars -------------------*/
|
||||
constructor(machineConfig = {}, stateConfig = {}, errorMetricsConfig = {}) {
|
||||
|
||||
//basic setup
|
||||
this.emitter = new EventEmitter(); // Own EventEmitter
|
||||
this.configUtils = new ConfigUtils(defaultConfig);
|
||||
this.config = this.configUtils.initConfig(machineConfig);
|
||||
|
||||
// Initialize measurements
|
||||
this.measurements = new MeasurementContainer();
|
||||
this.interpolation = new Interpolation();
|
||||
this.child = {}; // object to hold child information so we know on what to subscribe
|
||||
|
||||
this.flowDrift = null;
|
||||
|
||||
// Init after config is set
|
||||
this.logger = new Logger(this.config.general.logging.enabled, this.config.general.logging.logLevel, this.config.general.name);
|
||||
this.state = new State(stateConfig, this.logger); // Init State manager and pass logger
|
||||
this.errorMetrics = new ErrorMetrics(errorMetricsConfig, this.logger);
|
||||
|
||||
this.predictFlow = new Predict({ curve: this.config.asset.machineCurve.nq }); // load nq (x : ctrl , y : flow relationship)
|
||||
this.predictPower = new Predict({ curve: this.config.asset.machineCurve.np }); // load np (x : ctrl , y : power relationship)
|
||||
this.predictCtrl = new Predict({ curve: this.reverseCurve(this.config.asset.machineCurve.nq) }); // load reversed nq (x: flow, y: ctrl relationship)
|
||||
|
||||
this.currentMode = this.config.mode.current;
|
||||
this.currentEfficiencyCurve = {};
|
||||
this.cog = 0;
|
||||
this.NCog = 0;
|
||||
this.cogIndex = 0;
|
||||
this.minEfficiency = 0;
|
||||
this.absDistFromPeak = 0;
|
||||
this.relDistFromPeak = 0;
|
||||
|
||||
this.state.emitter.on("positionChange", (data) => {
|
||||
this.logger.debug(`Position change detected: ${data}`);
|
||||
this.updatePosition();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
//this.calcCog();
|
||||
|
||||
|
||||
this.childRegistrationUtils = new ChildRegistrationUtils(this); // Child registration utility
|
||||
|
||||
}
|
||||
|
||||
// Method to assess drift using errorMetrics
|
||||
assessDrift(measurement, processMin, processMax) {
|
||||
this.logger.debug(`Assessing drift for measurement: ${measurement} processMin: ${processMin} processMax: ${processMax}`);
|
||||
const predictedMeasurement = this.measurements.type(measurement).variant("predicted").position("downstream").getAllValues().values;
|
||||
const measuredMeasurement = this.measurements.type(measurement).variant("measured").position("downstream").getAllValues().values;
|
||||
|
||||
if (!predictedMeasurement || !measuredMeasurement) return null;
|
||||
|
||||
return this.errorMetrics.assessDrift(
|
||||
predictedMeasurement,
|
||||
measuredMeasurement,
|
||||
processMin,
|
||||
processMax
|
||||
);
|
||||
}
|
||||
|
||||
reverseCurve(curve) {
|
||||
const reversedCurve = {};
|
||||
for (const [pressure, values] of Object.entries(curve)) {
|
||||
reversedCurve[pressure] = {
|
||||
x: [...values.y], // Previous y becomes new x
|
||||
y: [...values.x] // Previous x becomes new y
|
||||
};
|
||||
}
|
||||
return reversedCurve;
|
||||
}
|
||||
|
||||
// -------- Config -------- //
|
||||
updateConfig(newConfig) {
|
||||
this.config = this.configUtils.updateConfig(this.config, newConfig);
|
||||
}
|
||||
|
||||
// -------- Mode and Input Management -------- //
|
||||
isValidSourceForMode(source, mode) {
|
||||
const allowedSourcesSet = this.config.mode.allowedSources[mode] || [];
|
||||
return allowedSourcesSet.has(source);
|
||||
}
|
||||
|
||||
isValidActionForMode(action, mode) {
|
||||
const allowedActionsSet = this.config.mode.allowedActions[mode] || [];
|
||||
return allowedActionsSet.has(action);
|
||||
}
|
||||
|
||||
async handleInput(source, action, parameter) {
|
||||
if (!this.isValidSourceForMode(source, this.currentMode)) {
|
||||
let warningTxt = `Source '${source}' is not valid for mode '${this.currentMode}'.`;
|
||||
this.logger.warn(warningTxt);
|
||||
return {status : false , feedback: warningTxt};
|
||||
}
|
||||
|
||||
|
||||
this.logger.info(`Handling input from source '${source}' with action '${action}' in mode '${this.currentMode}'.`);
|
||||
try {
|
||||
switch (action) {
|
||||
case "execSequence":
|
||||
await this.executeSequence(parameter);
|
||||
//recalc flow and power
|
||||
this.updatePosition();
|
||||
break;
|
||||
case "execMovement":
|
||||
await this.setpoint(parameter);
|
||||
break;
|
||||
case "flowMovement":
|
||||
// Calculate the control value for a desired flow
|
||||
const pos = this.calcCtrl(parameter);
|
||||
// Move to the desired setpoint
|
||||
await this.setpoint(pos);
|
||||
break;
|
||||
case "emergencyStop":
|
||||
this.logger.warn(`Emergency stop activated by '${source}'.`);
|
||||
await this.executeSequence("emergencyStop");
|
||||
break;
|
||||
case "statusCheck":
|
||||
this.logger.info(`Status Check: Mode = '${this.currentMode}', Source = '${source}'.`);
|
||||
break;
|
||||
default:
|
||||
this.logger.warn(`Action '${action}' is not implemented.`);
|
||||
break;
|
||||
}
|
||||
this.logger.debug(`Action '${action}' successfully executed`);
|
||||
return {status : true , feedback: `Action '${action}' successfully executed.`};
|
||||
} catch (error) {
|
||||
this.logger.error(`Error handling input: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
setMode(newMode) {
|
||||
const availableModes = defaultConfig.mode.current.rules.values.map(v => v.value);
|
||||
if (!availableModes.includes(newMode)) {
|
||||
this.logger.warn(`Invalid mode '${newMode}'. Allowed modes are: ${availableModes.join(', ')}`);
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentMode = newMode;
|
||||
this.logger.info(`Mode successfully changed to '${newMode}'.`);
|
||||
}
|
||||
|
||||
// -------- Sequence Handlers -------- //
|
||||
async executeSequence(sequenceName) {
|
||||
|
||||
const sequence = this.config.sequences[sequenceName];
|
||||
|
||||
if (!sequence || sequence.size === 0) {
|
||||
this.logger.warn(`Sequence '${sequenceName}' not defined.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.state.getCurrentState() == "operational" && sequenceName == "shutdown") {
|
||||
this.logger.info(`Machine will ramp down to position 0 before performing ${sequenceName} sequence`);
|
||||
await this.setpoint(0);
|
||||
}
|
||||
|
||||
this.logger.info(` --------- Executing sequence: ${sequenceName} -------------`);
|
||||
|
||||
for (const state of sequence) {
|
||||
try {
|
||||
await this.state.transitionToState(state);
|
||||
// Update measurements after state change
|
||||
|
||||
} catch (error) {
|
||||
this.logger.error(`Error during sequence '${sequenceName}': ${error}`);
|
||||
break; // Exit sequence execution on error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async setpoint(setpoint) {
|
||||
|
||||
try {
|
||||
// Validate setpoint
|
||||
if (typeof setpoint !== 'number' || setpoint < 0) {
|
||||
throw new Error("Invalid setpoint: Setpoint must be a non-negative number.");
|
||||
}
|
||||
|
||||
// Move to the desired setpoint
|
||||
await this.state.moveTo(setpoint);
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Error setting setpoint: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate flow based on current pressure and position
|
||||
calcFlow(x) {
|
||||
const state = this.state.getCurrentState();
|
||||
|
||||
if (!["operational", "accelerating", "decelerating"].includes(state)) {
|
||||
this.measurements.type("flow").variant("predicted").position("downstream").value(0);
|
||||
this.logger.debug(`Machine is not operational. Setting predicted flow to 0.`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//this.predictFlow.currentX = x; Decrepated
|
||||
const cFlow = this.predictFlow.y(x);
|
||||
this.measurements.type("flow").variant("predicted").position("downstream").value(cFlow);
|
||||
//this.logger.debug(`Calculated flow: ${cFlow} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
|
||||
return cFlow;
|
||||
|
||||
}
|
||||
|
||||
// Calculate power based on current pressure and position
|
||||
calcPower(x) {
|
||||
const state = this.state.getCurrentState();
|
||||
if (!["operational", "accelerating", "decelerating"].includes(state)) {
|
||||
this.measurements.type("power").variant("predicted").position('upstream').value(0);
|
||||
this.logger.debug(`Machine is not operational. Setting predicted power to 0.`);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//this.predictPower.currentX = x; Decrepated
|
||||
const cPower = this.predictPower.y(x);
|
||||
this.measurements.type("power").variant("predicted").position('upstream').value(cPower);
|
||||
//this.logger.debug(`Calculated power: ${cPower} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
|
||||
return cPower;
|
||||
}
|
||||
|
||||
// calculate the power consumption using only flow and pressure
|
||||
inputFlowCalcPower(flow) {
|
||||
this.predictCtrl.currentX = flow;
|
||||
const cCtrl = this.predictCtrl.y(flow);
|
||||
this.predictPower.currentX = cCtrl;
|
||||
const cPower = this.predictPower.y(cCtrl);
|
||||
return cPower;
|
||||
}
|
||||
|
||||
// Function to predict control value for a desired flow
|
||||
calcCtrl(x) {
|
||||
|
||||
this.predictCtrl.currentX = x;
|
||||
const cCtrl = this.predictCtrl.y(x);
|
||||
this.measurements.type("ctrl").variant("predicted").position('upstream').value(cCtrl);
|
||||
//this.logger.debug(`Calculated ctrl: ${cCtrl} for pressure: ${this.getMeasuredPressure()} and position: ${x}`);
|
||||
return cCtrl;
|
||||
|
||||
}
|
||||
|
||||
// this function returns the pressure for calculations
|
||||
getMeasuredPressure() {
|
||||
const pressureDiff = this.measurements.type('pressure').variant('measured').difference();
|
||||
|
||||
// Both upstream & downstream => differential
|
||||
if (pressureDiff != null) {
|
||||
this.logger.debug(`Pressure differential: ${pressureDiff.value}`);
|
||||
this.predictFlow.fDimension = pressureDiff.value;
|
||||
this.predictPower.fDimension = pressureDiff.value;
|
||||
this.predictCtrl.fDimension = pressureDiff.value;
|
||||
//update the cog
|
||||
const { cog, minEfficiency } = this.calcCog();
|
||||
// calc efficiency
|
||||
const efficiency = this.calcEfficiency(this.predictPower.outputY, this.predictFlow.outputY, "predicted");
|
||||
//update the distance from peak
|
||||
this.calcDistanceBEP(efficiency,cog,minEfficiency);
|
||||
|
||||
return pressureDiff.value;
|
||||
}
|
||||
|
||||
// get downstream
|
||||
const downstreamPressure = this.measurements.type('pressure').variant('measured').position('downstream').getCurrentValue();
|
||||
|
||||
// Only downstream => use it, warn that it's partial
|
||||
if (downstreamPressure != null) {
|
||||
this.logger.warn(`Using downstream pressure only for prediction: ${downstreamPressure} `);
|
||||
this.predictFlow.fDimension = downstreamPressure;
|
||||
this.predictPower.fDimension = downstreamPressure;
|
||||
this.predictCtrl.fDimension = downstreamPressure;
|
||||
//update the cog
|
||||
const { cog, minEfficiency } = this.calcCog();
|
||||
// calc efficiency
|
||||
const efficiency = this.calcEfficiency(this.predictPower.outputY, this.predictFlow.outputY, "predicted");
|
||||
//update the distance from peak
|
||||
this.calcDistanceBEP(efficiency,cog,minEfficiency);
|
||||
return downstreamPressure;
|
||||
}
|
||||
|
||||
this.logger.error(`No valid pressure measurements available to calculate prediction using last known pressure`);
|
||||
|
||||
//set default at 0 => lowest pressure possible
|
||||
this.predictFlow.fDimension = 0;
|
||||
this.predictPower.fDimension = 0;
|
||||
this.predictCtrl.fDimension = 0;
|
||||
//update the cog
|
||||
const { cog, minEfficiency } = this.calcCog();
|
||||
// calc efficiency
|
||||
const efficiency = this.calcEfficiency(this.predictPower.outputY, this.predictFlow.outputY, "predicted");
|
||||
//update the distance from peak
|
||||
this.calcDistanceBEP(efficiency,cog,minEfficiency);
|
||||
return 0;
|
||||
}
|
||||
|
||||
handleMeasuredFlow() {
|
||||
const flowDiff = this.measurements.type('flow').variant('measured').difference();
|
||||
|
||||
// If both are present
|
||||
if (flowDiff != null) {
|
||||
// In theory, mass flow in = mass flow out, so they should match or be close.
|
||||
if (flowDiff.value < 0.001) {
|
||||
// flows match within tolerance
|
||||
this.logger.debug(`Flow match: ${flowDiff.value}`);
|
||||
return flowDiff.value;
|
||||
} else {
|
||||
// Mismatch => decide how to handle. Maybe take the average?
|
||||
// Or bail out with an error. Example: we bail out here.
|
||||
this.logger.error(`Something wrong with down or upstream flow measurement. Bailing out!`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// get
|
||||
const upstreamFlow = this.measurements.type('pressure').variant('measured').position('upstream').getCurrentValue();
|
||||
|
||||
// Only upstream => might still accept it, but warn
|
||||
if (upstreamFlow != null) {
|
||||
this.logger.warn(`Only upstream flow is present. Using it but results may be incomplete!`);
|
||||
return upstreamFlow;
|
||||
}
|
||||
|
||||
// get
|
||||
const downstreamFlow = this.measurements.type('pressure').variant('measured').position('downstream').getCurrentValue();
|
||||
|
||||
// Only downstream => might still accept it, but warn
|
||||
if (downstreamFlow != null) {
|
||||
this.logger.warn(`Only downstream flow is present. Using it but results may be incomplete!`);
|
||||
return downstreamFlow;
|
||||
}
|
||||
|
||||
// Neither => error
|
||||
this.logger.error(`No upstream or downstream flow measurement. Bailing out!`);
|
||||
return null;
|
||||
}
|
||||
|
||||
handleMeasuredPower() {
|
||||
const power = this.measurements.type("power").variant("measured").position("upstream").getCurrentValue();
|
||||
// If your system calls it "upstream" or just a single "value", adjust accordingly
|
||||
|
||||
if (power != null) {
|
||||
this.logger.debug(`Measured power: ${power}`);
|
||||
return power;
|
||||
} else {
|
||||
this.logger.error(`No measured power found. Bailing out!`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
updatePressure(variant,value,position) {
|
||||
|
||||
switch (variant) {
|
||||
case ("measured"):
|
||||
//only update when machine is in a state where it can be used
|
||||
if (this.state.getCurrentState() == "operational" || this.state.getCurrentState() == "accelerating" || this.state.getCurrentState() == "decelerating") {
|
||||
// put value in measurements
|
||||
this.measurements.type("pressure").variant("measured").position(position).value(value);
|
||||
//when measured pressure gets updated we need some logic to fetch the relevant value which could be downstream or differential pressure
|
||||
const pressure = this.getMeasuredPressure();
|
||||
//update the flow power and cog
|
||||
this.updatePosition();
|
||||
this.logger.debug(`Measured pressure: ${pressure}`);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
this.logger.warn(`Unrecognized variant '${variant}' for pressure update.`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateFlow(variant,value,position) {
|
||||
|
||||
switch (variant) {
|
||||
case ("measured"):
|
||||
// put value in measurements
|
||||
this.measurements.type("flow").variant("measured").position(position).value(value);
|
||||
//when measured flow gets updated we need to push the last known value in the prediction measurements to keep them synced
|
||||
this.measurements.type("flow").variant("predicted").position("downstream").value(this.predictFlow.outputY);
|
||||
break;
|
||||
|
||||
case ("predicted"):
|
||||
this.logger.debug('not doing anythin yet');
|
||||
break;
|
||||
|
||||
default:
|
||||
this.logger.warn(`Unrecognized variant '${variant}' for flow update.`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
updateMeasurement(variant, subType, value, position) {
|
||||
this.logger.debug(`---------------------- updating ${subType} ------------------ `);
|
||||
switch (subType) {
|
||||
case "pressure":
|
||||
// Update pressure measurement
|
||||
this.updatePressure(variant,value,position);
|
||||
break;
|
||||
case "flow":
|
||||
this.updateFlow(variant,value,position);
|
||||
// Update flow measurement
|
||||
this.flowDrift = this.assessDrift("flow", this.predictFlow.currentFxyYMin , this.predictFlow.currentFxyYMax);
|
||||
this.logger.debug(`---------------------------------------- `);
|
||||
break;
|
||||
case "power":
|
||||
// Update power measurement
|
||||
break;
|
||||
default:
|
||||
this.logger.error(`Type '${type}' not recognized for measured update.`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//what is the internal functions that need updating when something changes that has influence on this.
|
||||
updatePosition() {
|
||||
if (this.state.getCurrentState() == "operational" || this.state.getCurrentState() == "accelerating" || this.state.getCurrentState() == "decelerating") {
|
||||
|
||||
const currentPosition = this.state.getCurrentPosition();
|
||||
|
||||
// Update the predicted values based on the new position
|
||||
const { cPower, cFlow } = this.calcFlowPower(currentPosition);
|
||||
|
||||
// Calc predicted efficiency
|
||||
const efficiency = this.calcEfficiency(cPower, cFlow, "predicted");
|
||||
|
||||
//update the cog
|
||||
const { cog, minEfficiency } = this.calcCog();
|
||||
|
||||
//update the distance from peak
|
||||
this.calcDistanceBEP(efficiency,cog,minEfficiency);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
calcDistanceFromPeak(currentEfficiency,peakEfficiency){
|
||||
return Math.abs(currentEfficiency - peakEfficiency);
|
||||
}
|
||||
|
||||
calcRelativeDistanceFromPeak(currentEfficiency,maxEfficiency,minEfficiency){
|
||||
let distance = 1;
|
||||
if(currentEfficiency != null){
|
||||
distance = this.interpolation.interpolate_lin_single_point(currentEfficiency,maxEfficiency, minEfficiency, 0, 1);
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
// Calculate the center of gravity for current pressure
|
||||
calcCog() {
|
||||
|
||||
//fetch current curve data for power and flow
|
||||
const { powerCurve, flowCurve } = this.getCurrentCurves();
|
||||
|
||||
const {efficiencyCurve, peak, peakIndex, minEfficiency } = this.calcEfficiencyCurve(powerCurve, flowCurve);
|
||||
|
||||
// Calculate the normalized center of gravity
|
||||
const NCog = (flowCurve.y[peakIndex] - this.predictFlow.currentFxyYMin) / (this.predictFlow.currentFxyYMax - this.predictFlow.currentFxyYMin);
|
||||
|
||||
//store in object for later retrieval
|
||||
this.currentEfficiencyCurve = efficiencyCurve;
|
||||
this.cog = peak;
|
||||
this.cogIndex = peakIndex;
|
||||
this.NCog = NCog;
|
||||
this.minEfficiency = minEfficiency;
|
||||
|
||||
return { cog: peak, cogIndex: peakIndex, NCog: NCog, minEfficiency: minEfficiency };
|
||||
|
||||
}
|
||||
|
||||
calcEfficiencyCurve(powerCurve, flowCurve) {
|
||||
|
||||
const efficiencyCurve = [];
|
||||
let peak = 0;
|
||||
let peakIndex = 0;
|
||||
let minEfficiency = 0;
|
||||
|
||||
// Calculate efficiency curve based on power and flow curves
|
||||
powerCurve.y.forEach((power, index) => {
|
||||
|
||||
// Get flow for the current power
|
||||
const flow = flowCurve.y[index];
|
||||
|
||||
// higher efficiency is better
|
||||
efficiencyCurve.push( Math.round( ( flow / power ) * 100 ) / 100);
|
||||
|
||||
// Keep track of peak efficiency
|
||||
peak = Math.max(peak, efficiencyCurve[index]);
|
||||
peakIndex = peak == efficiencyCurve[index] ? index : peakIndex;
|
||||
minEfficiency = Math.min(...efficiencyCurve);
|
||||
|
||||
});
|
||||
|
||||
return { efficiencyCurve, peak, peakIndex, minEfficiency };
|
||||
|
||||
}
|
||||
|
||||
//calc flow power based on pressure and current position
|
||||
calcFlowPower(x) {
|
||||
|
||||
// Calculate flow and power
|
||||
const cFlow = this.calcFlow(x);
|
||||
const cPower = this.calcPower(x);
|
||||
|
||||
return { cPower, cFlow };
|
||||
}
|
||||
|
||||
calcEfficiency(power, flow, variant) {
|
||||
|
||||
if (power != 0 && flow != 0) {
|
||||
// Calculate efficiency after measurements update
|
||||
this.measurements.type("efficiency").variant(variant).position('downstream').value((flow / power));
|
||||
} else {
|
||||
this.measurements.type("efficiency").variant(variant).position('downstream').value(null);
|
||||
}
|
||||
|
||||
return this.measurements.type("efficiency").variant(variant).position('downstream').getCurrentValue();
|
||||
|
||||
}
|
||||
|
||||
updateCurve(newCurve) {
|
||||
this.logger.info(`Updating machine curve`);
|
||||
const newConfig = { asset: { machineCurve: newCurve } };
|
||||
|
||||
//validate input of new curve fed to the machine
|
||||
this.config = this.configUtils.updateConfig(this.config, newConfig);
|
||||
|
||||
//After we passed validation load the curves into their predictors
|
||||
this.predictFlow.updateCurve(this.config.asset.machineCurve.nq);
|
||||
this.predictPower.updateCurve(this.config.asset.machineCurve.np);
|
||||
this.predictCtrl.updateCurve(this.reverseCurve(this.config.asset.machineCurve.nq));
|
||||
}
|
||||
|
||||
getCompleteCurve() {
|
||||
const powerCurve = this.predictPower.inputCurveData;
|
||||
const flowCurve = this.predictFlow.inputCurveData;
|
||||
return { powerCurve, flowCurve };
|
||||
}
|
||||
|
||||
getCurrentCurves() {
|
||||
const powerCurve = this.predictPower.currentFxyCurve[this.predictPower.currentF];
|
||||
const flowCurve = this.predictFlow.currentFxyCurve[this.predictFlow.currentF];
|
||||
|
||||
return { powerCurve, flowCurve };
|
||||
|
||||
}
|
||||
|
||||
calcDistanceBEP(efficiency,maxEfficiency,minEfficiency) {
|
||||
|
||||
const absDistFromPeak = this.calcDistanceFromPeak(efficiency,maxEfficiency);
|
||||
const relDistFromPeak = this.calcRelativeDistanceFromPeak(efficiency,maxEfficiency,minEfficiency);
|
||||
|
||||
//store internally
|
||||
this.absDistFromPeak = absDistFromPeak ;
|
||||
this.relDistFromPeak = relDistFromPeak;
|
||||
|
||||
return { absDistFromPeak: absDistFromPeak, relDistFromPeak: relDistFromPeak };
|
||||
}
|
||||
|
||||
getOutput() {
|
||||
|
||||
// Improved output object generation
|
||||
const output = {};
|
||||
//build the output object
|
||||
this.measurements.getTypes().forEach(type => {
|
||||
this.measurements.getVariants(type).forEach(variant => {
|
||||
|
||||
const downstreamVal = this.measurements.type(type).variant(variant).position("downstream").getCurrentValue();
|
||||
const upstreamVal = this.measurements.type(type).variant(variant).position("upstream").getCurrentValue();
|
||||
|
||||
if (downstreamVal != null) {
|
||||
output[`downstream_${variant}_${type}`] = downstreamVal;
|
||||
}
|
||||
if (upstreamVal != null) {
|
||||
output[`upstream_${variant}_${type}`] = upstreamVal;
|
||||
}
|
||||
if (downstreamVal != null && upstreamVal != null) {
|
||||
const diffVal = this.measurements.type(type).variant(variant).difference().value;
|
||||
output[`differential_${variant}_${type}`] = diffVal;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//fill in the rest of the output object
|
||||
output["state"] = this.state.getCurrentState();
|
||||
output["runtime"] = this.state.getRunTimeHours();
|
||||
output["ctrl"] = this.state.getCurrentPosition();
|
||||
output["moveTimeleft"] = this.state.getMoveTimeLeft();
|
||||
output["mode"] = this.currentMode;
|
||||
output["cog"] = this.cog; // flow / power efficiency
|
||||
output["NCog"] = this.NCog; // normalized cog
|
||||
output["NCogPercent"] = Math.round(this.NCog * 100 * 100) / 100 ;
|
||||
|
||||
if(this.flowDrift != null){
|
||||
const flowDrift = this.flowDrift;
|
||||
output["flowNrmse"] = flowDrift.nrmse;
|
||||
output["flowLongterNRMSD"] = flowDrift.longTermNRMSD;
|
||||
output["flowImmediateLevel"] = flowDrift.immediateLevel;
|
||||
output["flowLongTermLevel"] = flowDrift.longTermLevel;
|
||||
}
|
||||
|
||||
//should this all go in the container of measurements?
|
||||
output["effDistFromPeak"] = this.absDistFromPeak;
|
||||
output["effRelDistFromPeak"] = this.relDistFromPeak;
|
||||
//this.logger.debug(`Output: ${JSON.stringify(output)}`);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
} // end of class
|
||||
|
||||
module.exports = Machine;
|
||||
|
||||
/*------------------- Testing -------------------*/
|
||||
|
||||
/*
|
||||
curve = require('C:/Users/zn375/.node-red/public/fallbackData.json');
|
||||
|
||||
//import a child
|
||||
const Child = require('../../../measurement/dependencies/measurement/measurement');
|
||||
|
||||
console.log(`Creating child...`);
|
||||
const PT1 = new Child(config={
|
||||
general:{
|
||||
name:"PT1",
|
||||
logging:{
|
||||
enabled:true,
|
||||
logLevel:"debug",
|
||||
},
|
||||
},
|
||||
functionality:{
|
||||
softwareType:"measurement",
|
||||
},
|
||||
asset:{
|
||||
type:"sensor",
|
||||
subType:"pressure",
|
||||
},
|
||||
});
|
||||
|
||||
const PT2 = new Child(config={
|
||||
general:{
|
||||
name:"PT2",
|
||||
logging:{
|
||||
enabled:true,
|
||||
logLevel:"debug",
|
||||
},
|
||||
},
|
||||
functionality:{
|
||||
softwareType:"measurement",
|
||||
},
|
||||
asset:{
|
||||
type:"sensor",
|
||||
subType:"pressure",
|
||||
},
|
||||
});
|
||||
|
||||
//create a machine
|
||||
console.log(`Creating machine...`);
|
||||
|
||||
const machineConfig = {
|
||||
general: {
|
||||
name: "Hydrostal",
|
||||
logging: {
|
||||
enabled: true,
|
||||
logLevel: "debug",
|
||||
}
|
||||
},
|
||||
asset: {
|
||||
supplier: "Hydrostal",
|
||||
type: "pump",
|
||||
subType: "centrifugal",
|
||||
model: "H05K-S03R+HGM1X-X280KO", // Ensure this field is present.
|
||||
machineCurve: curve["machineCurves"]["Hydrostal"]["H05K-S03R+HGM1X-X280KO"],
|
||||
}
|
||||
}
|
||||
|
||||
const stateConfig = {
|
||||
general: {
|
||||
logging: {
|
||||
enabled: true,
|
||||
logLevel: "debug",
|
||||
},
|
||||
},
|
||||
// Your custom config here (or leave empty for defaults)
|
||||
movement: {
|
||||
speed: 1,
|
||||
},
|
||||
time: {
|
||||
starting: 2,
|
||||
warmingup: 3,
|
||||
stopping: 2,
|
||||
coolingdown: 3,
|
||||
},
|
||||
};
|
||||
|
||||
const machine = new Machine(machineConfig, stateConfig);
|
||||
|
||||
//machine.logger.info(JSON.stringify(curve["machineCurves"]["Hydrostal"]["H05K-S03R+HGM1X-X280KO"]));
|
||||
machine.logger.info(`Registering child...`);
|
||||
machine.childRegistrationUtils.registerChild(PT1, "upstream");
|
||||
machine.childRegistrationUtils.registerChild(PT2, "downstream");
|
||||
|
||||
//feed curve to the machine class
|
||||
//machine.updateCurve(curve["machineCurves"]["Hydrostal"]["H05K-S03R+HGM1X-X280KO"]);
|
||||
|
||||
PT1.logger.info(`Enable sim...`);
|
||||
PT1.toggleSimulation();
|
||||
PT2.logger.info(`Enable sim...`);
|
||||
PT2.toggleSimulation();
|
||||
machine.getOutput();
|
||||
//manual test
|
||||
//machine.handleInput("parent", "execSequence", "startup");
|
||||
|
||||
machine.measurements.type("pressure").variant("measured").position('upstream').value(-200);
|
||||
machine.measurements.type("pressure").variant("measured").position('downstream').value(1000);
|
||||
|
||||
testingSequences();
|
||||
|
||||
const tickLoop = setInterval(changeInput,1000);
|
||||
|
||||
function changeInput(){
|
||||
PT1.logger.info(`tick...`);
|
||||
PT1.tick();
|
||||
PT2.tick();
|
||||
}
|
||||
|
||||
async function testingSequences(){
|
||||
try{
|
||||
console.log(` ********** Testing sequence startup... **********`);
|
||||
await machine.handleInput("parent", "execSequence", "startup");
|
||||
console.log(` ********** Testing movement to 15... **********`);
|
||||
await machine.handleInput("parent", "execMovement", 15);
|
||||
machine.getOutput();
|
||||
console.log(` ********** Testing sequence shutdown... **********`);
|
||||
await machine.handleInput("parent", "execSequence", "shutdown");
|
||||
console.log(`********** Testing moving to setpoint 10... while in idle **********`);
|
||||
await machine.handleInput("parent", "execMovement", 10);
|
||||
console.log(` ********** Testing sequence emergencyStop... **********`);
|
||||
await machine.handleInput("parent", "execSequence", "emergencystop");
|
||||
console.log(`********** Testing sequence boot... **********`);
|
||||
await machine.handleInput("parent", "execSequence", "boot");
|
||||
}catch(error){
|
||||
console.error(`Error: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*/
|
||||
|
||||
|
||||
|
||||
297
dependencies/machine/machine.test.js
vendored
Normal file
297
dependencies/machine/machine.test.js
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
const Machine = require('./machine');
|
||||
const specs = require('../../../generalFunctions/datasets/assetData/pumps/hydrostal/centrifugal pumps/models.json');
|
||||
|
||||
class MachineTester {
|
||||
constructor() {
|
||||
this.totalTests = 0;
|
||||
this.passedTests = 0;
|
||||
this.failedTests = 0;
|
||||
this.machineCurve = specs[0].machineCurve;
|
||||
}
|
||||
|
||||
assert(condition, message) {
|
||||
this.totalTests++;
|
||||
if (condition) {
|
||||
console.log(`✓ PASS: ${message}`);
|
||||
this.passedTests++;
|
||||
} else {
|
||||
console.log(`✗ FAIL: ${message}`);
|
||||
this.failedTests++;
|
||||
}
|
||||
}
|
||||
|
||||
createBaseMachineConfig(name) {
|
||||
return {
|
||||
general: {
|
||||
logging: { enabled: true, logLevel: "debug" },
|
||||
name: name,
|
||||
unit: "m3/h"
|
||||
},
|
||||
functionality: {
|
||||
softwareType: "machine",
|
||||
role: "RotationalDeviceController"
|
||||
},
|
||||
asset: {
|
||||
type: "pump",
|
||||
subType: "Centrifugal",
|
||||
model: "TestModel",
|
||||
supplier: "Hydrostal",
|
||||
machineCurve: this.machineCurve
|
||||
},
|
||||
mode: {
|
||||
current: "auto",
|
||||
allowedActions: {
|
||||
auto: ["execSequence", "execMovement", "statusCheck"],
|
||||
virtualControl: ["execMovement", "statusCheck"],
|
||||
fysicalControl: ["statusCheck"]
|
||||
},
|
||||
allowedSources: {
|
||||
auto: ["parent", "GUI"],
|
||||
virtualControl: ["GUI"],
|
||||
fysicalControl: ["fysical"]
|
||||
}
|
||||
},
|
||||
sequences: {
|
||||
startup: ["starting", "warmingup", "operational"],
|
||||
shutdown: ["stopping", "coolingdown", "idle"],
|
||||
emergencystop: ["emergencystop", "off"],
|
||||
boot: ["idle", "starting", "warmingup", "operational"]
|
||||
},
|
||||
calculationMode: "medium"
|
||||
};
|
||||
}
|
||||
|
||||
async testBasicOperations() {
|
||||
console.log('\nTesting Basic Machine Operations...');
|
||||
|
||||
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
||||
|
||||
try {
|
||||
// Test 1: Initialization
|
||||
this.assert(
|
||||
machine.currentMode === "auto",
|
||||
'Machine should initialize in auto mode'
|
||||
);
|
||||
|
||||
// Test 2: Set pressure measurement
|
||||
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
||||
const pressure = machine.handleMeasuredPressure();
|
||||
this.assert(
|
||||
pressure === 800,
|
||||
'Should correctly handle pressure measurement'
|
||||
);
|
||||
|
||||
// Test 3: State transition
|
||||
await machine.state.transitionToState("idle");
|
||||
this.assert(
|
||||
machine.state.getCurrentState() === "idle",
|
||||
'Should transition to idle state'
|
||||
);
|
||||
|
||||
// Test 4: Mode change
|
||||
machine.setMode("virtualControl");
|
||||
this.assert(
|
||||
machine.currentMode === "virtualControl",
|
||||
'Should change mode to virtual control'
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Test failed with error:', error);
|
||||
this.failedTests++;
|
||||
}
|
||||
}
|
||||
|
||||
async testPredictions() {
|
||||
console.log('\nTesting Machine Predictions...');
|
||||
|
||||
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
||||
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
||||
|
||||
try {
|
||||
// Test 1: Flow prediction
|
||||
const flow = machine.calcFlow(50);
|
||||
this.assert(
|
||||
flow > 0 && !isNaN(flow),
|
||||
'Should calculate valid flow for control value'
|
||||
);
|
||||
|
||||
// Test 2: Power prediction
|
||||
const power = machine.calcPower(50);
|
||||
this.assert(
|
||||
power > 0 && !isNaN(power),
|
||||
'Should calculate valid power for control value'
|
||||
);
|
||||
|
||||
// Test 3: Control prediction
|
||||
const ctrl = machine.calcCtrl(100);
|
||||
this.assert(
|
||||
ctrl >= 0 && ctrl <= 100,
|
||||
'Should calculate valid control value for desired flow'
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Test failed with error:', error);
|
||||
this.failedTests++;
|
||||
}
|
||||
}
|
||||
|
||||
async testSequenceExecution() {
|
||||
console.log('\nTesting Machine Sequences...');
|
||||
|
||||
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
||||
|
||||
try {
|
||||
// Test 1: Startup sequence
|
||||
await machine.handleInput("parent", "execSequence", "startup");
|
||||
this.assert(
|
||||
machine.state.getCurrentState() === "operational",
|
||||
'Should complete startup sequence'
|
||||
);
|
||||
|
||||
// Test 2: Movement after startup
|
||||
await machine.handleInput("parent", "execMovement", 50);
|
||||
this.assert(
|
||||
machine.state.getCurrentPosition() === 50,
|
||||
'Should move to specified position'
|
||||
);
|
||||
|
||||
// Test 3: Shutdown sequence
|
||||
await machine.handleInput("parent", "execSequence", "shutdown");
|
||||
this.assert(
|
||||
machine.state.getCurrentState() === "idle",
|
||||
'Should complete shutdown sequence'
|
||||
);
|
||||
|
||||
// Test 4: Emergency stop
|
||||
await machine.handleInput("parent", "execSequence", "emergencystop");
|
||||
this.assert(
|
||||
machine.state.getCurrentState() === "off",
|
||||
'Should execute emergency stop'
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Test failed with error:', error);
|
||||
this.failedTests++;
|
||||
}
|
||||
}
|
||||
|
||||
async testMeasurementHandling() {
|
||||
console.log('\nTesting Measurement Handling...');
|
||||
|
||||
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
||||
|
||||
try {
|
||||
// Test 1: Pressure measurement
|
||||
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
||||
machine.measurements.type("pressure").variant("measured").setUpstream(1000);
|
||||
const pressure = machine.handleMeasuredPressure();
|
||||
this.assert(
|
||||
pressure === 200,
|
||||
'Should calculate correct differential pressure'
|
||||
);
|
||||
|
||||
// Test 2: Flow measurement
|
||||
machine.measurements.type("flow").variant("measured").position("downstream").value(100);
|
||||
const flow = machine.handleMeasuredFlow();
|
||||
this.assert(
|
||||
flow === 100,
|
||||
'Should handle flow measurement correctly'
|
||||
);
|
||||
|
||||
// Test 3: Power measurement
|
||||
machine.measurements.type("power").variant("measured").setUpstream(75);
|
||||
const power = machine.handleMeasuredPower();
|
||||
this.assert(
|
||||
power === 75,
|
||||
'Should handle power measurement correctly'
|
||||
);
|
||||
|
||||
// Test 4: Efficiency calculation
|
||||
machine.calcEfficiency();
|
||||
const efficiency = machine.measurements.type("efficiency").variant("measured").getDownstream();
|
||||
this.assert(
|
||||
efficiency > 0 && !isNaN(efficiency),
|
||||
'Should calculate valid efficiency'
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Test failed with error:', error);
|
||||
this.failedTests++;
|
||||
}
|
||||
}
|
||||
|
||||
async testCurveHandling() {
|
||||
console.log('\nTesting Machine Curve Handling...');
|
||||
|
||||
const machine = new Machine(this.createBaseMachineConfig("TestMachine"));
|
||||
|
||||
try {
|
||||
// Test 1: Curve initialization
|
||||
const curves = machine.showCurve();
|
||||
this.assert(
|
||||
curves.powerCurve && curves.flowCurve,
|
||||
'Should properly initialize power and flow curves'
|
||||
);
|
||||
|
||||
// Test 2: Test reverse curve creation
|
||||
const reversedCurve = machine.reverseCurve(this.machineCurve.nq);
|
||||
this.assert(
|
||||
reversedCurve["1"].x[0] === this.machineCurve.nq["1"].y[0] &&
|
||||
reversedCurve["1"].y[0] === this.machineCurve.nq["1"].x[0],
|
||||
'Should correctly reverse x and y values in curve'
|
||||
);
|
||||
|
||||
// Test 3: Update curve dynamically
|
||||
const newCurve = {
|
||||
nq: {
|
||||
"1": {
|
||||
x: [0, 25, 50, 75, 100],
|
||||
y: [0, 125, 250, 375, 500]
|
||||
}
|
||||
},
|
||||
np: {
|
||||
"1": {
|
||||
x: [0, 25, 50, 75, 100],
|
||||
y: [0, 75, 150, 225, 300]
|
||||
}
|
||||
}
|
||||
};
|
||||
machine.updateCurve(newCurve);
|
||||
const updatedCurves = machine.showCurve();
|
||||
this.assert(
|
||||
updatedCurves.flowCurve["1"].y[2] === 250,
|
||||
'Should update curve with new values'
|
||||
);
|
||||
|
||||
// Test 4: Verify curve interpolation
|
||||
machine.measurements.type("pressure").variant("measured").position("downstream").value(800);
|
||||
const midpointCtrl = machine.calcCtrl(250); // Should interpolate between points
|
||||
const calculatedFlow = machine.calcFlow(midpointCtrl);
|
||||
this.assert(
|
||||
Math.abs(calculatedFlow - 250) < 1, // Allow small numerical error
|
||||
'Should accurately interpolate between curve points'
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Test failed with error:', error);
|
||||
this.failedTests++;
|
||||
}
|
||||
}
|
||||
|
||||
async runAllTests() {
|
||||
console.log('Starting Machine Tests...\n');
|
||||
|
||||
await this.testBasicOperations();
|
||||
await this.testPredictions();
|
||||
await this.testSequenceExecution();
|
||||
await this.testMeasurementHandling();
|
||||
await this.testCurveHandling();
|
||||
|
||||
console.log('\nTest Summary:');
|
||||
console.log(`Total Tests: ${this.totalTests}`);
|
||||
console.log(`Passed: ${this.passedTests}`);
|
||||
console.log(`Failed: ${this.failedTests}`);
|
||||
|
||||
process.exit(this.failedTests > 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Run the tests
|
||||
const tester = new MachineTester();
|
||||
tester.runAllTests().catch(console.error);
|
||||
381
dependencies/rotatingMachine/rotatingMachineConfig.json
vendored
Normal file
381
dependencies/rotatingMachine/rotatingMachineConfig.json
vendored
Normal file
@@ -0,0 +1,381 @@
|
||||
{
|
||||
"general": {
|
||||
"name": {
|
||||
"default": "Rotating Machine",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "A human-readable name or label for this machine configuration."
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"default": null,
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "A unique identifier for this configuration. If not provided, defaults to null."
|
||||
}
|
||||
},
|
||||
"unit": {
|
||||
"default": "m3/h",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "The default measurement unit for this configuration (e.g., 'meters', 'seconds', 'unitless')."
|
||||
}
|
||||
},
|
||||
"logging": {
|
||||
"logLevel": {
|
||||
"default": "info",
|
||||
"rules": {
|
||||
"type": "enum",
|
||||
"values": [
|
||||
{
|
||||
"value": "debug",
|
||||
"description": "Log messages are printed for debugging purposes."
|
||||
},
|
||||
{
|
||||
"value": "info",
|
||||
"description": "Informational messages are printed."
|
||||
},
|
||||
{
|
||||
"value": "warn",
|
||||
"description": "Warning messages are printed."
|
||||
},
|
||||
{
|
||||
"value": "error",
|
||||
"description": "Error messages are printed."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"enabled": {
|
||||
"default": true,
|
||||
"rules": {
|
||||
"type": "boolean",
|
||||
"description": "Indicates whether logging is active. If true, log messages will be generated."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"functionality": {
|
||||
"softwareType": {
|
||||
"default": "machine",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "Specified software type for this configuration."
|
||||
}
|
||||
},
|
||||
"role": {
|
||||
"default": "RotationalDeviceController",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "Indicates the role this configuration plays within the system."
|
||||
}
|
||||
}
|
||||
},
|
||||
"asset": {
|
||||
"uuid": {
|
||||
"default": null,
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"nullable": true,
|
||||
"description": "A universally unique identifier for this asset. May be null if not assigned."
|
||||
}
|
||||
},
|
||||
"geoLocation": {
|
||||
"default": {},
|
||||
"rules": {
|
||||
"type": "object",
|
||||
"description": "An object representing the asset's physical coordinates or location.",
|
||||
"schema": {
|
||||
"x": {
|
||||
"default": 0,
|
||||
"rules": {
|
||||
"type": "number",
|
||||
"description": "X coordinate of the asset's location."
|
||||
}
|
||||
},
|
||||
"y": {
|
||||
"default": 0,
|
||||
"rules": {
|
||||
"type": "number",
|
||||
"description": "Y coordinate of the asset's location."
|
||||
}
|
||||
},
|
||||
"z": {
|
||||
"default": 0,
|
||||
"rules": {
|
||||
"type": "number",
|
||||
"description": "Z coordinate of the asset's location."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"supplier": {
|
||||
"default": "Unknown",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "The supplier or manufacturer of the asset."
|
||||
}
|
||||
},
|
||||
"type": {
|
||||
"default": "pump",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "A general classification of the asset tied to the specific software. This is not chosen from the asset dropdown menu."
|
||||
}
|
||||
},
|
||||
"subType": {
|
||||
"default": "Centrifugal",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "A more specific classification within 'type'. For example, 'centrifugal' for a centrifugal pump."
|
||||
}
|
||||
},
|
||||
"model": {
|
||||
"default": "Unknown",
|
||||
"rules": {
|
||||
"type": "string",
|
||||
"description": "A user-defined or manufacturer-defined model identifier for the asset."
|
||||
}
|
||||
},
|
||||
"accuracy": {
|
||||
"default": null,
|
||||
"rules": {
|
||||
"type": "number",
|
||||
"nullable": true,
|
||||
"description": "The accuracy of the machine or sensor, typically as a percentage or absolute value."
|
||||
}
|
||||
},
|
||||
"machineCurve": {
|
||||
"default": {
|
||||
"nq": {
|
||||
"1": {
|
||||
"x": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
],
|
||||
"y": [
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
40,
|
||||
50
|
||||
]
|
||||
}
|
||||
},
|
||||
"np": {
|
||||
"1": {
|
||||
"x": [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5
|
||||
],
|
||||
"y": [
|
||||
10,
|
||||
20,
|
||||
30,
|
||||
40,
|
||||
50
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"type": "machineCurve",
|
||||
"description": "All machine curves must have a 'nq' and 'np' curve. nq stands for the flow curve, np stands for the power curve. Together they form the efficiency curve."
|
||||
}
|
||||
}
|
||||
},
|
||||
"mode": {
|
||||
"current": {
|
||||
"default": "auto",
|
||||
"rules": {
|
||||
"type": "enum",
|
||||
"values": [
|
||||
{
|
||||
"value": "auto",
|
||||
"description": "Machine accepts setpoints from a parent controller and runs autonomously."
|
||||
},
|
||||
{
|
||||
"value": "virtualControl",
|
||||
"description": "Controlled via GUI setpoints; ignores parent commands."
|
||||
},
|
||||
{
|
||||
"value": "fysicalControl",
|
||||
"description": "Controlled via physical buttons or switches; ignores external automated commands."
|
||||
},
|
||||
{
|
||||
"value": "maintenance",
|
||||
"description": "No active control from auto, virtual, or fysical sources."
|
||||
}
|
||||
],
|
||||
"description": "The operational mode of the machine."
|
||||
}
|
||||
},
|
||||
"allowedActions":{
|
||||
"default":{},
|
||||
"rules": {
|
||||
"type": "object",
|
||||
"schema":{
|
||||
"auto": {
|
||||
"default": ["statusCheck", "execMovement", "execSequence", "emergencyStop"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Actions allowed in auto mode."
|
||||
}
|
||||
},
|
||||
"virtualControl": {
|
||||
"default": ["statusCheck", "execMovement", "execSequence", "emergencyStop"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Actions allowed in virtualControl mode."
|
||||
}
|
||||
},
|
||||
"fysicalControl": {
|
||||
"default": ["statusCheck", "emergencyStop"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Actions allowed in fysicalControl mode."
|
||||
}
|
||||
},
|
||||
"maintenance": {
|
||||
"default": ["statusCheck"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Actions allowed in maintenance mode."
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Information about valid command sources recognized by the machine."
|
||||
}
|
||||
},
|
||||
"allowedSources":{
|
||||
"default": {},
|
||||
"rules": {
|
||||
"type": "object",
|
||||
"schema":{
|
||||
"auto": {
|
||||
"default": ["parent", "GUI", "fysical"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Sources allowed in auto mode."
|
||||
}
|
||||
},
|
||||
"virtualControl": {
|
||||
"default": ["GUI", "fysical"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Sources allowed in virtualControl mode."
|
||||
}
|
||||
},
|
||||
"fysicalControl": {
|
||||
"default": ["fysical"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Sources allowed in fysicalControl mode."
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Information about valid command sources recognized by the machine."
|
||||
}
|
||||
}
|
||||
},
|
||||
"source": {
|
||||
"default": "parent",
|
||||
"rules": {
|
||||
"type": "enum",
|
||||
"values": [
|
||||
{
|
||||
"value": "parent",
|
||||
"description": "Commands are received from a parent controller."
|
||||
},
|
||||
{
|
||||
"value": "GUI",
|
||||
"description": "Commands are received from a graphical user interface."
|
||||
},
|
||||
{
|
||||
"value": "fysical",
|
||||
"description": "Commands are received from physical buttons or switches."
|
||||
}
|
||||
],
|
||||
"description": "Information about valid command sources recognized by the machine."
|
||||
}
|
||||
},
|
||||
"sequences":{
|
||||
"default":{},
|
||||
"rules": {
|
||||
"type": "object",
|
||||
"schema": {
|
||||
"startup": {
|
||||
"default": ["starting","warmingup","operational"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Sequence of states for starting up the machine."
|
||||
}
|
||||
},
|
||||
"shutdown": {
|
||||
"default": ["stopping","coolingdown","idle"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Sequence of states for shutting down the machine."
|
||||
}
|
||||
},
|
||||
"emergencystop": {
|
||||
"default": ["emergencystop","off"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Sequence of states for an emergency stop."
|
||||
}
|
||||
},
|
||||
"boot": {
|
||||
"default": ["idle","starting","warmingup","operational"],
|
||||
"rules": {
|
||||
"type": "set",
|
||||
"itemType": "string",
|
||||
"description": "Sequence of states for booting up the machine."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Predefined sequences of states for the machine."
|
||||
|
||||
},
|
||||
"calculationMode": {
|
||||
"default": "medium",
|
||||
"rules": {
|
||||
"type": "enum",
|
||||
"values": [
|
||||
{
|
||||
"value": "low",
|
||||
"description": "Calculations run at fixed intervals (time-based)."
|
||||
},
|
||||
{
|
||||
"value": "medium",
|
||||
"description": "Calculations run when new setpoints arrive or measured changes occur (event-driven)."
|
||||
},
|
||||
{
|
||||
"value": "high",
|
||||
"description": "Calculations run on all event-driven info, including every movement."
|
||||
}
|
||||
],
|
||||
"description": "The frequency at which calculations are performed."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
28
package.json
Normal file
28
package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"name": "rotatingMachine",
|
||||
"version": "1.0.3",
|
||||
"description": "Control module rotatingMachine",
|
||||
"main": "rotatingMachine.js",
|
||||
"scripts": {
|
||||
"test": "node rotatingMachine.js"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://gitea.centraal.wbd-rd.nl/RnD/rotatingMachine.git"
|
||||
},
|
||||
"keywords": [
|
||||
"rotatingMachine",
|
||||
"node-red"
|
||||
],
|
||||
"author": "Rene De Ren",
|
||||
"license": "SEE LICENSE",
|
||||
"dependencies": {
|
||||
"generalFunctions": "git+https://gitea.centraal.wbd-rd.nl/RnD/generalFunctions.git",
|
||||
"convert": "git+https://gitea.centraal.wbd-rd.nl/RnD/convert.git"
|
||||
},
|
||||
"node-red": {
|
||||
"nodes": {
|
||||
"rotatingMachine": "rotatingMachine.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
22
readme/Training_data
Normal file
22
readme/Training_data
Normal file
@@ -0,0 +1,22 @@
|
||||
let ctrl0 = [0,0.4,1.4,2.4,3.4,4.4,5.4,6.4,7.4,8.4,9.4,10.4,11.6,12.6,13.8,14.8,15.8,16.8,17.8,18.8,19.8,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,51.5,52,53,54,55,56,57,58.2,59.2,60.2,61.2,62.2,63.2,64.2,65.2,66.2,67.2,68.2,69.2,70.2,71.2,72.2,73.2,74.2,75.2,76.2,77.4,78.6,79.8,80.8,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97.4,95.4,93.4,91.4,89.4,87.4,85.4,83.4,81.4,79.4,77.4,75.4,73.4,71.4,69.4,67.4,65.4,63.4,61.4,59.4,57.4,55.4,53.4,51.4,49.4,48.3,47.2,45.2,43.2,41,39,37,35,33,31,29,27,25,23,21,19,17,15,13,11,9,7,5,3,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30.2,31.4,32.4,33.4,34.4,35.4,36.4,37.4,38.4,39.4,40.4,41.4,42.4,43.6,44.2,44.8,45.8,46.8,47.8,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97,95,93,91,89,87,84.8,82.8,80.8,78.8,76.6,74.6,72.6,70.6,68.6,66.6,64.6,62.4,60.4,58.4,56.4,54.4,53.3,52.2,50.2,48,46,44,41.8,39.8,37.8,35.8,33.6,31.6,29.6,27.6,25.6,23.6,21.6,19.6,17.6,15.6,13.6,11.6,9.6,7.4,5.4,3.4,1.4,1.6,2.6,3.6,4.6,5.8,6.8,7.8,8.8,9.8,10.8,11.8,12.8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,32.5,33,34,35,36.2,37.4,38.4,39.4,40.4,41.4,42.6,43.6,44.6,45.6,46.6,47.6,48.8,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,67.5,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97,95,93,91,89,87,85,83,81,78.8,76.8,74.8,72.8,70.8,68.8,66.8,64.8,62.8,60.8,58.8,56.8,54.8,52.8,50.8,48.8,46.8,44.8,42.8,40.8,38.8,36.8,34.8,32.8,30.8,28.8,26.6,24.6,22.6,20.6,18.6,16.6,14.6,12.6,10.6,8.6,6.6,4.6,2.6,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21.2,22.4,23.4,24.4,25.4,26.4,27.4,28.4,29.4,30.4,31.4,32.4,33.6,34.2,34.8,35.8,36.8,37.8,38.8,39.8,40.8,41.8,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97.4,95.4,93.4,91.4,89.4,87.4,85.4,83.4,81.4,79.4,77.4,75.4,73.4,71.4,69.2,67.2,65.2,63.2,61.2,59.2,57.2,55,53,51,48.8,46.8,44.8,42.8,40.8,38.8,36.8,34.8,32.8,30.8,28.8,26.8,24.8,22.8,20.8,18.8,16.8,14.8,12.8,10.8,8.6,6.6,4.6,2.6,1,2,3,4,5,6,6.5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23.2,24.2,25.4,26.6,27.6,28.6,29.6,30.6,31.6,32.6,33.6,34.8,35.8,36.8,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,64.5,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80.2,81.2,82.2,83.4,84.4,85.4,86.4,87.4,88.4,89.4,90.6,91.6,92.8,94,95,96,97,98,99,98,96,94,92,90,88,86,84,82,79.8,77.8,75.8,73.8,71.8,69.8,67.8,65.8,63.8,61.8,59.8,57.8,55.8,53.8,51.8,49.8,47.8,45.8,43.8,41.8,39.8,37.8,35.6,33.6,31.6,29.6,27.6,25.6,23.6,21.6,19.6,17.6,15.6,13.6,11.6,9.6,7.6,5.6,3.6,2.5,1.4,1.6,2.6,3.6,4.8,5.8,6.8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66.2,67.2,68.2,69.2,70.2,71.4,72.4,73.4,74.4,75.4,76.4,77.4,78.6,79.6,80.6,81.6,82.2,82.8,83.8,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99];
|
||||
let ctrl1 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30.2,31.4,32.4,33.4,34.4,35.4,36.4,37.4,38.4,39.4,40.4,41.4,42.4,43.6,44.2,44.8,45.8,46.8,47.8,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97,95,93,91,89,87,84.8,82.8,80.8,78.8,76.6,74.6,72.6,70.6,68.6,66.6,64.6,62.4,60.4,58.4,56.4,54.4,53.3,52.2,50.2,48,46,44,41.8,39.8,37.8,35.8,33.6,31.6,29.6,27.6,25.6,23.6,21.6,19.6,17.6,15.6,13.6,11.6,9.6,7.4,5.4,3.4,1.4,1.6,2.6,3.6,4.6,5.8,6.8,7.8,8.8,9.8,10.8,11.8,12.8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,32.5,33,34,35,36.2,37.4,38.4,39.4,40.4,41.4,42.6,43.6,44.6,45.6,46.6,47.6,48.8,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,67.5,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97,95,93,91,89,87,85,83,81,78.8,76.8,74.8,72.8,70.8,68.8,66.8,64.8,62.8,60.8,58.8,56.8,54.8,52.8,50.8,48.8,46.8,44.8,42.8,40.8,38.8,36.8,34.8,32.8,30.8,28.8,26.6,24.6,22.6,20.6,18.6,16.6,14.6,12.6,10.6,8.6,6.6,4.6,2.6,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21.2,22.4,23.4,24.6,25.6,26.6,27.2,27.8,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97.4,95.4,93.4,91.4,89.4,87.4,85.4,83.4,81.4,79.4,77.4,75.4,73.4,71.4,69.2,67.2,65.2,63.2,61.2,59.2,57.2,55,53,51,48.8,46.8,44.8,42.8,40.8,38.8,36.8,34.8,32.8,30.8,28.8,26.8,24.8,22.8,20.8,18.8,16.8,14.8,12.8,10.8,8.6,6.6,4.6,2.6,1,2,3,4,5,6,6.5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23.2,24.2,25.4,26.6,27.6,28.6,29.6,30.6,31.6,32.6,33.6,34.8,35.8,36.8,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,64.5,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80.2,81.2,82.2,83.4,84.4,85.4,86.4,87.4,88.4,89.4,90.6,91.6,92.8,94,95,96,97,98,99,98,96,94,92,90,88,86,84,82,79.8,77.8,75.8,73.8,71.8,69.8,67.8,65.8,63.8,61.8,59.8,57.8,55.8,53.8,51.8,49.8,47.8,45.8,43.8,41.8,39.8,37.8,35.6,33.6,31.6,29.6,27.6,25.6,23.6,21.6,19.6,17.6,15.6,13.6,12.5,11.4,9.4,7.4,5.4,3.4,1.4,1.6,2.6,3.6,4.8,5.8,6.8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66.2,67.2,68.2,69.2,70.2,71.4,72.4,73.4,74.4,75.4,76.4,77.4,78.6,79.6,80.6,81.6,82.2,82.8,83.8,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99];
|
||||
let ctrl2 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.6,1.6,2.6,3.6,4.6,5.8,6.8,7.8,8.8,9.8,10.8,11.8,12.8,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,32.5,33,34,35,36.2,37.4,38.4,39.4,40.4,41.4,42.6,43.6,44.6,45.6,46.6,47.6,48.8,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,67.5,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97,95,93,91,89,87,85,83,81,78.8,76.8,74.8,72.8,70.8,68.8,66.8,64.8,62.8,60.8,58.8,56.8,54.8,52.8,50.8,48.8,46.8,44.8,42.8,40.8,38.8,36.8,34.8,32.8,30.8,28.8,26.6,24.6,22.6,20.6,18.6,16.6,14.6,12.6,10.6,8.6,6.6,4.6,2.6,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21.2,22.4,23.4,24.6,25.6,26.6,27.2,27.8,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97.4,95.4,93.4,91.4,89.4,87.4,85.4,83.4,81.4,79.4,77.4,75.4,73.4,71.4,69.2,67.2,65.2,63.2,61.2,59.2,57.2,55,53,51,48.8,46.8,44.8,42.8,40.8,38.8,36.8,34.8,32.8,30.8,28.8,26.8,24.8,22.8,20.8,18.8,16.8,14.8,12.8,10.8,8.6,6.6,4.6,2.6,1,2,3,4,5,6,6.5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23.2,24.2,25.4,26.6,27.6,28.6,29.6,30.6,31.6,32.6,33.6,34.8,35.8,36.8,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,64.5,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80.2,81.2,82.2,83.4,84.4,85.4,86.4,87.4,88.4,89.4,90.6,91.6,92.8,94,95,96,97,98,99,98,96,94,92,90,88,86,84,82,79.8,77.8,75.8,73.8,71.8,69.8,67.8,65.8,63.8,61.8,59.8,57.8,55.8,53.8,51.8,49.8,47.8,45.8,43.8,41.8,39.8,37.8,35.6,34.5,33.4,31.4,29.4,27.4,25.4,23.4,21.4,19.4,17.4,15.4,13.4,11.4,9.4,7.4,5.4,3.4,1.4,1.6,2.6,3.6,4.8,5.8,6.8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66.2,67.2,68.2,69.2,70.2,71.4,72.4,73.4,74.4,75.4,76.4,77.4,78.6,79.6,80.6,81.6,82.2,82.8,83.8,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99];
|
||||
let ctrl3 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21.2,22.4,23.4,24.6,25.6,26.6,27.2,27.8,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,97.4,95.4,93.4,91.4,89.4,87.4,85.4,83.4,81.4,79.4,77.4,75.4,73.4,71.4,69.2,67.2,65.2,63.2,61.2,59.2,57.2,55,53,51,48.8,46.8,44.8,42.8,40.8,38.8,36.8,34.8,32.8,30.8,28.8,26.8,24.8,22.8,20.8,18.8,16.8,14.8,12.8,10.8,8.6,6.6,4.6,2.6,1,2,3,4,5,6,6.5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23.2,24.2,25.4,26.6,27.6,28.6,29.6,30.6,31.6,32.6,33.6,34.8,35.8,36.8,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,64.5,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80.2,81.2,82.2,83.4,84.4,85.4,86.4,87.4,88.4,89.4,90.6,91.6,92.8,94,95,96,97,98,99,98,96,94,92,90,88,86,84,82,79.8,77.8,75.8,73.8,71.8,69.8,67.8,65.8,63.8,61.8,59.8,57.8,55.8,53.8,51.8,49.8,47.8,45.8,43.8,41.8,39.8,37.8,35.6,34.5,33.4,31.4,29.4,27.4,25.4,23.4,21.4,19.4,17.4,15.4,13.4,11.4,9.4,7.4,5.4,3.4,1.4,1.6,2.6,3.6,4.8,5.8,6.8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66.2,67.2,68.2,69.2,70.2,71.4,72.4,73.4,74.4,75.4,76.4,77.4,78.6,79.6,80.6,81.6,82.2,82.8,83.8,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99];
|
||||
let ctrl4 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,2,3,4,5,6,6.5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23.2,24.2,25.4,26.6,27.6,28.6,29.6,30.6,31.6,32.6,33.6,34.8,35.8,36.8,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,64.5,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80.2,81.2,82.2,83.4,84.4,85.4,86.4,87.4,88.4,89.4,90.6,91.6,92.8,94,95,96,97,98,99,98,96,94,92,90,88,86,84,82,79.8,77.8,75.8,73.8,71.8,69.8,67.8,65.8,63.8,61.8,59.8,57.8,55.8,53.8,51.8,49.8,47.8,45.8,43.8,41.8,39.8,37.8,35.6,34.5,33.4,31.4,29.4,27.4,25.4,23.4,21.4,19.4,17.4,15.4,13.4,11.4,9.4,7.4,5.4,3.4,1.4,1.6,2.6,3.6,4.8,5.8,6.8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66.2,67.2,68.2,69.2,70.2,71.4,72.4,73.4,74.4,75.4,76.4,77.4,78.4,79.4,80.4,81.4,82.6,83.6,84.6,85.6,86.6,87.6,88.6,89.6,90.6,92,92.6,93.6,94.6,95.6,96.2,96.8,97.8,98.8];
|
||||
let ctrl5 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.6,1.6,2.6,3.6,4.8,5.8,6.8,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66.2,67.2,68.2,69.2,70.2,71.4,72.4,73.4,74.4,75.4,76.4,77.4,78.4,79.4,80.4,81.4,82.6,83.6,84.6,85.6,86.6,87.6,88.6,89.6,90.6,92,92.6,93.6,94.6,95.6,96.2,96.8,97.8,98.8];
|
||||
|
||||
let PT_1 = [85.9,87.4,90.5,93.4,96.8,99.9,103,107,110,114,118,121,125,129,133,137,140,143,147,150,153,155,157,159,161,162,163,165,166,168,169,170,171,172,174,174,176,177,178,179,181,181,182,184,184,185,186,187,188,189,190,191,193,194,195,196,196,197,199,199,201,201,202,203,204,206,206,207,208,210,210,211,213,214,215,215,217,218,219,219,219,219,219,219,219,219,219,219,219,219,219,219,218,219,218,218,218,218,219,219,219,219,218,219,219,218,218,218,218,219,220,218,216,215,212,210,208,206,204,202,200,198,197,194,193,190,189,186,184,182,180,178,175,173,171,168,166,163,159,156,152,147,142,134,127,119,112,104,97.2,92.1,92.2,95.2,98.6,102,105,109,112,116,119,123,127,131,135,138,142,144,147,150,152,154,156,159,160,162,164,165,167,168,169,170,172,173,174,175,177,178,179,180,181,182,183,184,185,184,185,186,187,188,189,190,191,192,193,195,195,197,198,198,199,201,202,203,204,205,206,207,208,208,210,211,212,212,213,215,216,217,217,217,217,218,218,217,217,218,217,217,217,217,217,217,217,217,217,217,218,217,217,217,217,218,218,217,217,217,217,217,218,217,217,216,215,212,210,209,206,204,202,200,198,197,194,191,190,187,186,184,182,179,178,175,173,170,168,165,163,160,156,152,148,143,137,130,123,115,107,101,93.4,90.2,92.1,95.1,98.7,102,106,109,113,116,121,124,129,132,135,139,142,144,147,150,152,154,156,157,159,161,163,164,166,167,169,170,171,172,173,175,176,177,179,180,181,181,182,184,184,185,186,187,188,189,190,191,192,193,194,195,196,197,199,200,200,202,203,204,205,206,207,208,209,210,209,210,211,212,214,215,216,216,217,217,216,217,217,217,217,216,217,217,217,217,217,217,217,217,218,217,217,218,218,217,218,217,217,217,217,217,217,217,217,217,217,215,213,211,209,207,204,203,201,198,196,194,192,190,189,187,185,183,181,179,177,175,172,170,167,165,162,158,155,150,145,140,132,126,118,110,102,96,90.3,90.9,93.8,96.4,100,103,107,111,115,118,122,125,130,133,136,138,141,144,146,148,151,153,155,157,158,160,161,163,165,166,168,169,170,171,173,173,175,176,178,178,179,181,181,183,183,184,185,186,187,187,188,188,190,190,192,192,194,194,195,196,197,198,200,201,202,203,204,205,206,208,209,209,210,211,213,214,211,207,206,206,205,206,206,206,206,206,206,206,205,206,205,206,206,205,205,205,205,205,206,206,205,206,205,206,205,205,206,205,206,205,204,202,200,197,195,193,191,189,186,184,182,180,178,175,174,172,171,172,177,175,173,171,169,167,164,161,157,154,150,146,141,134,128,121,113,106,99.4,93,90,92.4,95.7,98.7,102,105,109,112,116,120,124,128,131,134,136,139,141,143,145,147,149,151,153,155,156,158,160,161,162,164,166,166,168,169,171,172,173,174,175,177,177,177,178,179,180,180,181,182,184,184,185,186,187,189,189,190,191,191,193,194,195,194,188,187,189,190,191,192,193,195,196,197,198,200,200,202,203,204,205,206,205,205,205,205,206,205,205,205,205,205,205,205,205,206,205,205,205,205,205,206,206,205,204,205,205,204,205,205,204,203,201,198,195,193,191,189,186,184,182,178,176,175,173,170,169,167,164,163,160,159,155,156,161,159,156,154,150,147,143,138,133,128,121,115,108,102,95.3,89.5,89.8,92.3,95.5,98.9,102,106,110,114,117,120,124,127,130,133,135,136,138,139,140,142,144,146,148,150,151,153,154,155,157,159,160,162,163,164,166,167,167,168,169,170,171,173,174,175,175,177,178,178,179,180,181,181,183,178,173,176,177,177,179,181,182,183,184,186,186,188,189,190,191,192,193,195,196,197,198,199,201,201,202,203,203,203,203,202,203,204,204,203,204,203,204,203,203,203,204,204,204,154];
|
||||
let PT_2 = [47.9,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.7,47.6,47.6,47.5,47.5,47.4,47.3,47.2,47.2,47,46.9,46.8,46.5,46.4,46.2,46.1,45.9,45.6,45.5,45.4,45.3,45.1,44.9,44.6,44.6,44.3,44,43.8,43.5,43.7,43.4,43.2,43,42.7,42.4,42.4,42,41.9,41.6,41.6,41.2,41.3,40.7,40.6,40.4,40.3,40,39.5,39.3,39.2,38.8,38.5,38.3,37.7,37.8,37.4,37.3,36.7,36.5,36.4,35.8,35.5,35.2,35.2,34.9,35,34.8,34.9,35,35.1,35.3,34.9,35.1,34.9,35,34.8,35,34.8,34.7,34.8,34.8,34.9,34.7,35,34.9,34.9,56.9,80.8,81,81.1,81.6,81.5,81.3,81.5,81.7,81.4,81.9,82.2,82.8,83.3,84.2,84.6,85.3,85.7,86.1,86.7,87.3,87.7,88.1,88.6,88.9,89.5,89.9,90.3,90.5,91.1,91.2,91.5,92.3,92.7,93,93.4,93.8,93.9,94.1,94.2,94.5,94.7,94.8,94.8,94.9,94.9,94.9,95,96.8,99.9,103,106,110,114,117,121,124,128,132,136,140,144,148,152,153,158,161,163,165,167,169,170,172,174,176,178,178,181,182,184,185,186,186,189,190,191,192,193,195,195,196,197,199,200,201,202,203,204,206,207,208,209,209,210,212,213,214,215,216,217,218,219,220,222,223,223,225,227,227,229,230,230,232,233,234,236,236,237,237,237,238,237,237,237,237,237,237,237,237,237,237,237,236,237,236,237,236,236,236,236,236,237,236,237,236,236,237,236,234,231,229,226,224,222,220,218,215,213,211,209,207,204,202,200,198,196,194,191,189,186,184,180,177,174,171,168,164,160,155,148,141,133,125,117,110,103,99.8,102,105,109,112,116,120,123,127,132,135,140,143,147,150,154,157,160,162,164,166,168,170,171,173,175,176,178,179,181,183,184,185,186,188,189,191,192,192,194,195,197,198,198,200,201,202,203,204,205,206,207,208,210,210,212,212,214,215,216,217,218,220,221,223,222,224,225,227,227,228,228,229,230,231,233,234,235,236,236,236,237,236,236,235,237,236,236,236,237,236,236,237,236,236,235,236,236,236,236,236,237,235,236,236,236,235,235,235,234,231,229,226,224,222,220,217,215,213,210,209,207,205,203,201,199,196,195,192,190,187,184,182,179,176,172,169,165,162,157,151,143,136,127,120,112,105,100,100,104,107,110,114,118,122,125,129,134,138,141,144,147,151,153,156,159,162,164,167,169,169,170,172,173,175,176,178,180,181,182,184,186,186,188,189,191,192,194,194,195,197,197,198,200,201,201,202,202,203,205,206,207,208,209,211,211,212,214,215,216,217,218,219,220,222,222,223,225,227,227,227,230,231,227,223,224,224,224,225,225,225,224,225,225,225,225,225,224,224,225,225,224,225,225,224,225,224,224,223,224,225,225,224,224,225,224,223,221,218,216,213,211,209,206,203,201,199,197,194,192,190,188,186,183,186,190,187,185,183,180,178,175,172,169,166,161,157,151,145,138,131,122,114,107,102,98.2,100,104,107,111,114,118,122,126,130,134,138,141,144,146,148,151,152,154,157,160,163,165,166,168,171,174,176,179,180,181,178,180,182,183,184,186,187,188,189,190,190,191,192,193,194,196,197,197,199,199,201,202,203,204,205,205,207,208,209,209,208,203,202,204,205,206,207,208,210,211,213,213,214,216,217,219,219,221,222,222,223,224,224,223,224,224,224,224,223,223,222,222,223,222,223,223,223,223,223,224,224,224,222,223,223,223,222,222,219,217,213,211,208,205,203,200,198,195,194,191,189,186,185,183,180,177,175,173,171,167,168,174,172,169,166,163,159,154,149,144,139,132,126,118,111,104,98.4,98.6,102,105,109,112,116,120,124,127,131,135,138,140,143,145,147,149,150,150,153,155,157,160,161,164,168,169,171,173,174,176,178,179,181,183,184,183,184,184,184,185,186,188,188,189,190,191,193,193,195,195,196,196,193,187,191,191,192,194,196,196,198,200,200,202,203,205,206,207,208,210,212,213,213,215,217,218,220,220,221,221,223,222,224,224,223,224,224,223,223,224,223,223,224,224,223,223,189];
|
||||
let PT_3 = [47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.7,47.7,47.7,47.7,47.7,47.7,47.6,47.6,47.5,47.5,47.4,47.3,47.2,47.1,47,46.8,46.6,46.5,46.3,46.2,46.1,45.9,45.7,45.6,45.4,45.1,45,44.9,44.7,44.4,44.2,44.2,44,43.8,43.4,43.3,43.1,42.9,42.8,42.7,42.3,42.3,42.1,41.8,41.4,41.4,40.9,40.9,40.3,40.5,40.2,39.8,39.6,39.4,39.1,38.9,38.4,38.3,38.3,37.8,37.6,37.1,36.9,36.6,36.3,36.1,35.7,35.4,35.1,35.3,35.1,35,34.8,35.1,34.8,34.8,35,34.9,34.7,34.9,35,34.9,35.1,35.2,35.4,35.1,35.2,35,35.1,35,34.9,35.1,34.8,35,34.9,34.6,34.7,34.8,35,34.8,35,34.9,35.6,36.2,36.8,37.2,37.8,38.2,38.9,39.3,40,40.7,41,41.3,41.8,42.1,42.5,42.9,43.4,43.7,44.1,44.5,44.8,45.1,45.5,45.8,46.1,46.5,46.7,47,47.3,47.4,47.6,47.7,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.8,47.7,47.7,47.7,47.7,47.7,47.6,47.1,46.8,46.3,46,45.7,45.3,44.8,44.4,43.9,43.6,43,42.6,42,41.3,40.8,40.3,39.7,39,38.4,37.7,37.2,36.4,35.8,35.2,34.5,33.9,33,32.6,32.5,31.7,31.1,30.4,29.6,29,28.2,27.3,26.7,25.9,25.1,24.1,23.5,23,22,21.3,20,19.3,18.5,17.4,16.5,15.2,14.4,13.3,12.5,12.1,10.8,9.61,8.65,7.39,6.48,5.23,4.37,3.25,3.11,3.11,2.53,3.09,2.77,2.54,2.36,2.77,2.29,2.61,2.59,2.59,2.57,2.36,2.63,2.73,2.97,3.01,2.64,2.72,2.6,3.51,49,49.1,49.7,49.1,49.5,49.7,49.2,49.4,49.1,49.7,51,52.9,55.2,56.7,59.3,61,62.7,64.7,66.4,68.4,69.9,71.3,73.1,74.3,75.8,77.6,78.6,79.9,81.2,82.8,84,85.1,86.5,87.7,88.7,89.6,90.5,91.5,92.4,93,93.6,94,94.1,94.4,94.3,94.4,94.4,94.8,97.4,100,104,107,111,114,118,121,125,129,134,138,142,146,149,153,156,159,161,164,166,168,170,172,173,175,176,178,179,181,182,183,185,186,187,189,190,191,192,193,194,195,196,197,199,200,201,202,204,204,205,206,207,208,210,210,212,213,214,215,215,217,218,219,221,221,223,224,224,224,225,226,227,227,229,230,231,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,232,231,232,231,231,232,232,233,232,232,232,232,231,232,231,229,227,224,223,221,219,215,214,212,209,208,206,203,201,200,198,196,194,191,189,186,184,181,178,176,173,169,166,161,156,149,142,134,126,118,111,105,98.8,98.9,102,106,109,113,116,120,123,127,131,135,139,143,146,149,152,155,158,160,162,164,166,168,170,171,173,175,176,178,179,180,182,183,185,186,187,188,190,190,192,193,194,196,196,197,199,200,201,201,201,202,204,205,206,206,207,209,210,211,213,214,214,216,217,218,219,221,221,223,224,224,226,226,229,229,226,222,222,222,222,221,222,222,222,222,221,222,222,223,222,221,221,222,222,221,222,222,222,222,222,221,222,221,222,222,221,221,221,222,219,217,214,212,209,208,205,202,200,198,196,194,191,190,187,185,183,186,189,187,185,183,180,178,175,172,168,165,161,156,150,143,137,128,122,114,108,101,98.1,100,104,107,111,114,118,121,125,130,133,137,140,143,146,149,151,153,155,158,160,162,164,166,167,169,170,172,174,176,177,178,180,182,182,184,185,187,187,189,190,190,191,191,193,194,195,196,197,198,199,200,202,203,203,205,205,206,207,208,210,208,204,201,205,206,207,209,210,210,213,215,215,216,217,219,219,221,222,223,222,224,222,222,223,222,223,222,222,222,223,223,222,222,222,222,223,223,222,223,222,223,223,222,222,222,223,223,221,220,217,215,213,210,208,204,202,199,197,195,192,190,188,185,184,181,179,177,174,173,169,170,176,173,170,167,164,159,154,149,144,137,131,123,117,110,104,98,98.3,101,104,108,111,115,119,123,126,130,133,136,139,141,144,147,148,150,151,153,155,158,160,163,164,167,168,169,171,173,174,176,177,178,179,181,181,182,183,184,186,186,188,188,190,191,191,193,194,195,196,197,197,192,187,191,191,194,194,196,196,199,199,200,202,203,205,207,208,209,211,211,214,214,216,218,219,220,220,222,223,225,224,226,224,224,223,224,224,223,224,224,225,224,223,224,224,171];
|
||||
let PT_4 = [104,104,105,105,105,105,105,104,104,105,104,104,105,105,104,104,104,105,104,103,104,104,104,104,104,103,104,104,103,103,103,103,102,102,102,102,102,102,102,101,101,102,100,99.3,100,101,99.9,99.4,100,99.5,98.9,99.5,99.4,98.9,97.6,98.2,98.1,97.6,96.7,97,97.5,96.2,95.8,96.3,95.9,94.8,96,95,94.2,94,94.4,94.1,93.7,93.1,92.3,91.7,93.2,92,91.3,91.9,92.3,91,91.1,93,90.4,91.2,92.4,90.6,91.5,91.4,90.1,92,92.6,90.8,91,92.9,91.7,91.1,90.5,91.6,92.4,91.2,91.4,91.8,92.2,90.9,91.7,92.8,91.7,90.5,92.4,91.5,91.3,92.6,94.7,94.4,94.3,95.2,96.5,97,96,97,98.1,97.5,98.6,99.6,98.8,100,101,101,101,100,101,103,103,102,103,103,103,103,104,105,104,104,106,105,104,105,105,104,105,105,104,105,105,104,105,106,104,104,106,105,104,103,105,104,103,103,103,102,102,101,101,101,100,99.7,98.6,99.4,98.8,97.5,95.9,96.8,96.2,95.5,94.5,92.9,92.7,93.3,92.3,90,89.3,90.1,89.7,88.3,87.5,87.4,87.3,86.7,84.9,83.4,84.4,83.5,81.7,81.7,81.1,79.1,79,79.1,77.5,76.3,76.5,74.9,73.2,73.4,71.4,69.7,70.3,69.8,67.6,66.1,66.2,65.8,63.2,62.6,60.8,61.2,59.1,58.4,60.1,59,58.3,59,59.3,59.5,58.1,58.8,58.8,59.5,58.5,58.5,59.4,58.8,58.6,59.8,59.6,58.5,57.8,59.4,58.6,58.4,59.1,60.5,58.1,58.4,58.9,58.8,58.6,59,57.6,60.9,63.2,64.3,66.5,69.8,71.2,72.8,74.1,76.8,79.2,79.1,80.7,82.8,85.6,85.7,86.6,89.6,90.9,90.8,92.3,94.3,95.5,95.5,98.3,99.3,99.6,101,103,102,103,103,105,105,104,104,105,104,104,104,104,105,106,104,105,105,104,104,105,105,104,104,105,104,102,102,103,102,101,99.7,98.5,98.7,97.9,95.4,94.8,94.1,93.4,92.3,91.1,89.9,87,87.7,86.5,84.6,82.8,82.2,80.8,79.8,78.3,76.4,76.8,75.3,73,71.6,72,68.1,66.5,67,65.2,63.1,61.3,58.9,57.7,58.1,55,53.6,52.9,50,47.6,45.6,45.2,43,40.1,40,37,34.7,32.6,31.6,29.5,27.2,24.4,22.1,21,17.9,15.3,13.5,13.6,12.9,11,11.3,12.6,13.9,12.5,11.6,13.4,12.6,12.8,13.1,13.2,12.9,11.9,13,13.5,11.6,11.9,13.3,13.2,12.1,12.6,13,14,12.4,11,12.7,13.1,13,12.5,13,15.1,18.3,21.8,26.3,31.3,36.2,38.9,42,46.8,49.7,52.6,56.5,59.3,61.3,64.8,69.4,71.7,73.8,77.5,80.7,81.5,84.2,87.4,89.8,91.8,94.1,96.9,97.8,99,102,103,104,104,104,105,104,104,103,107,112,111,121,126,132,135,137,144,149,153,156,158,154,151,153,154,155,156,156,157,157,158,160,160,161,162,162,162,163,163,163,165,165,166,166,167,168,168,169,170,170,170,172,172,173,174,175,174,175,175,176,176,177,178,178,178,179,179,179,180,181,181,182,181,182,183,184,183,185,184,185,186,185,186,186,183,178,178,178,179,180,183,182,182,182,182,181,183,182,183,182,182,182,183,181,181,182,182,182,182,182,181,181,182,182,181,180,179,176,175,175,173,172,171,170,169,168,167,166,164,164,162,160,159,157,156,159,162,160,159,156,154,152,149,151,148,146,142,143,141,137,134,132,129,124,117,110,106,109,114,118,122,127,132,136,142,146,151,156,159,162,164,165,164,155,156,157,159,161,160,161,162,163,163,163,163,165,165,166,166,167,168,168,168,170,170,170,171,170,170,171,171,176,174,174,176,177,175,176,177,178,178,179,179,179,181,179,181,178,173,169,172,172,172,174,174,174,176,176,175,177,178,179,180,179,182,182,183,185,185,186,187,187,187,187,188,188,188,188,188,187,187,188,188,188,189,188,188,187,187,187,188,187,186,184,182,180,179,177,176,173,173,172,171,170,168,166,165,163,163,160,158,154,153,151,149,147,144,145,154,151,148,147,145,145,142,140,137,134,131,129,124,119,110,102,102,105,110,113,118,123,128,133,138,142,148,151,156,159,162,163,166,162,156,157,157,157,156,158,159,161,161,163,164,165,166,166,166,167,168,169,168,168,169,170,171,171,172,172,173,174,174,174,175,176,176,177,175,171,167,170,170,171,171,171,172,172,171,172,175,175,177,177,178,177,178,179,179,181,181,181,183,183,185,183,186,184,189,186,188,190,189,191,192,192,192,193,192,192,191,191,192,176];
|
||||
let PT_5 = [46.7,46.7,46.7,46.7,46.7,46.7,46.7,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.5,46.5,46.5,46.4,46.4,46.3,46.1,46,46,45.8,45.7,45.6,45.4,45.3,45.1,44.9,44.7,44.6,44.5,44.3,44,43.9,43.8,43.6,43.2,43.2,43.1,42.8,42.6,42.4,42.1,42,41.9,41.7,41.4,41.3,40.9,40.8,40.6,40.5,39.9,40.1,39.5,39.4,39.2,39.1,38.7,38.6,38.2,38,37.9,37.5,37.2,37.1,36.7,36.4,36,35.7,35.5,34.9,35.1,34.6,34.2,33.9,33.7,33.9,33.7,33.9,33.8,34.1,34.1,33.9,33.9,33.9,33.8,33.8,33.8,34.1,33.7,34.2,33.8,33.9,34,33.8,33.8,33.7,33.7,33.7,33.9,33.8,33.7,33.7,33.8,33.7,33.8,33.7,33.9,34.5,34.7,35.5,36.1,36.7,37.3,37.7,38.2,38.9,39.2,39.9,40.3,40.4,40.9,41.4,41.8,42.3,42.6,43,43.4,43.6,43.9,44.4,44.7,44.8,45.1,45.6,45.8,46.1,46.3,46.5,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.5,46.5,46.5,46.5,46.5,46.5,46.5,46.5,46.4,46,45.6,45.2,44.8,44.5,44.1,43.8,43.3,42.8,42.3,41.9,41.3,40.8,40.1,39.9,39.2,38.6,37.9,37.2,36.5,35.9,35.3,34.7,34.1,33.3,32.6,32.2,31.3,31.5,30.6,29.9,29.2,28.4,27.9,27.2,26.4,25.5,24.9,24,23.3,22.4,21.8,21.1,20.2,18.9,18.3,17.2,16.4,15.7,14.3,13.6,12.3,11.3,10.9,9.45,8.51,7.33,6.51,5.29,4.28,3.36,2.06,2.07,2.11,1.58,2.35,1.93,2,1.24,1.62,1.38,1.4,1.56,1.43,1.61,1.32,1.59,2.01,1.79,1.88,1.65,1.61,1.68,1.53,1.61,1.56,1.92,1.15,1.89,1.8,1.51,1.88,1.63,2.33,2.96,5.33,7.41,9.19,11.3,13.5,15.3,17.2,18.8,20.7,22.5,24,25.6,26.9,28.3,30,31.1,32.4,33.7,35.1,36.2,37.5,38.6,40,40.9,41.8,42.9,43.7,44.6,45.1,45.9,46.3,46.6,46.6,46.7,46.6,46.6,46.6,46.7,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.5,46.5,46.4,46.4,45.9,45.4,44.9,44.3,43.6,42.8,42,41.2,40.3,39.4,38.5,37.6,36.4,35.4,34.3,33,32,30.7,29.4,28.2,27,26,24.7,23.6,22.2,20.9,19.6,18.5,17.2,15.5,14.3,13,11.3,10.3,8.34,7.2,5.62,4.49,2.5,1.41,0.382,0.025,0.0282,0.0315,0.0347,0.0379,0.0411,0.0444,0.0476,0.0508,0.054,0.0573,0.0605,0.0637,0.067,0.0702,0.0734,0.0766,0.0799,0.0831,0.0863,0.0895,0.0928,0.096,0.0992,0.102,0.106,0.109,0.112,0.115,0.119,0.122,0.125,0.128,0.132,0.135,0.138,0.141,0.144,0.148,0.151,0.154,0.157,0.161,0.164,0.167,0.17,0.173,0.177,0.18,0.183,0.186,0.19,0.193,0.196,0.199,0.203,0.206,0.209,0.212,0.215,0.219,0.222,0.225,0.228,0.232,0.235,1.98,5.13,8.15,11.1,14,16.5,19.4,22,24.6,27.1,29.4,31.9,34.1,36.2,38.3,40,42,43.3,45,45.8,46.2,46.6,46.6,46.6,46.6,46.6,46.7,46.7,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.6,46.5,46.3,45,43.9,42.9,41.9,40.7,39.7,38,36.6,35.1,33.4,31.5,29.7,27.8,25.9,23.7,21.7,19.9,17.9,16.3,14.1,11.8,10,7.41,5.78,3.03,1.18,0.088,0.0904,0.0929,0.0953,0.0977,0.1,0.103,0.105,0.107,0.11,0.112,0.115,0.117,0.12,0.122,0.124,0.127,0.129,0.132,0.134,0.137,0.139,0.141,0.144,0.146,0.149,0.151,0.153,0.156,0.158,0.161,0.163,0.166,0.168,0.17,0.173,0.175,0.178,0.18,0.183,0.185,0.187,0.19,0.192,0.195,0.197,0.2,0.202,0.204,0.207,0.209,0.212,0.214,0.217,0.219,0.221,0.224,0.226,0.229,0.231,0.234,0.236,0.238,0.241,0.243,0.246,0.248,0.25,0.253,0.255,0.258,0.26,0.263,0.265,0.267,0.27,0.272,0.275,0.277,0.28,4.98,9.21,14.5,20.3,25.4,31.4,35.3,40.9,46.1,54.4,58.7,64.2,68.1,73.1,76.9,81.1,85.3,88.7,91.9,96,98.8,101,103,104,105,106,106,106,107,110,113,117,121,125,129,133,138,142,147,152,157,154,158,159,161,162,163,164,165,166,167,168,169,170,170,171,172,173,174,174,175,176,177,177,178,178,179,180,180,181,180,181,182,183,183,184,185,186,186,187,188,188,189,188,190,191,191,191,192,193,191,184,182,184,184,184,185,186,186,188,187,188,190,189,190,191,191,193,194,195,196,195,193,193,196,193,194,194,195,193,194,194,194,194,193,193,194,193,193,193,193,193,193,193,192,191,190,191,188,185,182,183,181,180,179,178,177,176,175,173,172,171,170,169,168,166,165,164,163,160,163,171,171,170,169,167,165,164,161,159,157,152,144,136,128,120,112,113,116,120,124,128,133,137,143,147,151,153,154,157,159,160,161,162,163,164,165,166,167,168,169,169,170,171,172,173,173,174,175,176,177,177,177,177,178,179,179,180,180,181,182,183,184,184,185,186,187,187,188,188,183,177,180,181,181,182,183,184,184,185,186,186,186,188,188,189,190,190,191,192,192,193,193,194,196,197,198,199,199,199,201,203,203,205,204,203,204,204,204,203,204,204,204,204,173];
|
||||
let PT_6 = [40.7,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.5,40.4,40.4,40.3,40.2,40.2,40.1,39.9,39.8,39.6,39.5,39.4,39.2,39.1,39,38.8,38.6,38.3,38.2,38,37.9,37.7,37.5,37.4,37.1,36.9,36.6,36.5,36.4,36.2,36,35.7,35.5,35.4,35.1,35,35,34.6,34.1,34.2,33.7,33.6,33.3,33.3,33,32.8,32.3,32.2,31.9,31.4,31.3,31,30.5,30.3,30,30,29.5,29.4,29.3,28.8,28.5,28,27.9,27.9,27.7,27.6,27.5,27.6,27.3,27.8,27.6,27.5,27.5,27.8,27.4,27.6,27.5,27.5,27.4,27.6,27.6,27.5,27.8,27.6,27.5,27.6,27.6,27.5,27.5,27.8,27.7,27.6,27.8,27.5,27.6,27.8,28.4,28.8,29.5,30.1,30.5,30.9,31.6,32.2,32.5,33.3,33.7,34.1,34.6,35,35.5,35.9,36.2,36.5,36.8,37.2,37.6,38.2,38.3,38.7,39.1,39.3,39.6,39.8,40.1,40.3,40.4,40.6,40.6,40.7,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.5,40.5,40.5,40.5,40.4,40.4,40.4,40.4,40,39.5,39.2,38.8,38.4,38.1,37.6,37.1,36.7,36.4,35.9,35.3,34.7,34.2,33.6,33,32.5,31.7,31.1,30.6,30,29.1,28.5,28,27.4,26.6,25.9,25.2,25.1,24.5,23.8,23,22.3,21.9,20.8,19.9,19.5,18.6,17.9,17.1,16,15.3,14.8,13.9,12.8,11.8,11.1,10.1,9.26,7.9,7.08,6.04,5.08,4.58,3.56,2.48,0.97,0.201,0.063,0.0668,0.0706,0.0744,0.0782,0.0819,0.0857,0.0895,0.0933,0.0971,0.101,0.105,0.108,0.112,0.116,0.12,0.124,0.127,0.131,0.135,0.139,0.143,0.146,0.15,0.154,0.158,0.162,0.165,0.169,0.173,0.177,0.18,0.184,0.188,0.192,0.196,0.199,0.203,1.21,2.65,5.08,6.68,8.61,10.8,12.6,14.5,16,17.5,19.3,20.7,22.3,23.6,25,26.1,27.5,28.8,30,31.2,32.6,33.8,34.8,35.8,36.9,37.6,38.5,39.2,39.9,40.3,40.4,40.6,40.5,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.5,40.5,40.5,40.4,39.8,39.3,38.9,38.2,37.6,36.8,36,35,34.1,33.3,32.4,31.2,30.2,29.3,28.2,26.8,25.7,24.6,23.4,22.1,20.8,19.6,18.3,17.4,15.9,14.6,13.3,12.3,10.5,9.36,7.87,6.53,4.95,3.66,2.13,0.752,0.088,0.0901,0.0921,0.0942,0.0962,0.0983,0.1,0.102,0.104,0.106,0.109,0.111,0.113,0.115,0.117,0.119,0.121,0.123,0.125,0.127,0.129,0.131,0.133,0.135,0.137,0.139,0.141,0.143,0.146,0.148,0.15,0.152,0.154,0.156,0.158,0.16,0.162,0.164,0.166,0.168,0.17,0.172,0.174,0.176,0.178,0.18,0.183,0.185,0.187,0.189,0.191,0.193,0.195,0.197,0.199,0.201,0.203,0.205,0.207,0.209,0.211,0.213,0.215,0.217,0.22,0.222,0.224,0.226,0.228,0.23,0.232,0.234,0.236,1.58,4.62,7.89,10.5,13.2,15.6,18.4,20.7,23.4,25.6,28,30.1,32.2,33.9,35.9,37.3,38.7,39.7,40.3,40.6,40.6,40.6,40.6,40.5,40.5,40.5,40.5,40.5,40.5,40.5,40.5,40.5,40.6,40.5,40.5,40.3,40.2,39,37.8,36.9,35.8,34.5,33.4,31.9,30.4,28.8,27.2,25.3,23.5,21.5,19.5,17.4,15.6,13.7,11.5,10.1,7.57,5.54,3.41,1.2,0.038,0.0398,0.0415,0.0433,0.0451,0.0468,0.0486,0.0504,0.0521,0.0539,0.0557,0.0575,0.0592,0.061,0.0628,0.0645,0.0663,0.0681,0.0698,0.0716,0.0734,0.0751,0.0769,0.0787,0.0804,0.0822,0.084,0.0857,0.0875,0.0893,0.0911,0.0928,0.0946,0.0964,0.0981,0.0999,0.102,0.103,0.105,0.107,0.109,0.111,0.112,0.114,0.116,0.118,0.119,0.121,0.123,0.125,0.126,0.128,0.13,0.132,0.133,0.135,0.137,0.139,0.141,0.142,0.144,0.146,0.148,0.149,0.151,0.153,0.155,0.156,0.158,0.16,0.162,0.164,0.165,0.167,0.169,0.171,0.172,0.174,0.176,0.178,0.179,0.181,0.183,0.185,0.187,0.188,0.19,0.192,0.194,0.195,0.197,0.199,0.201,0.202,0.204,3.13,7.4,11.8,15.7,19.6,23.1,26.9,30,32.8,35.5,37.3,38.8,39.6,40.2,40.4,40.5,40.5,40.5,40.5,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.6,40.5,39.5,38.1,36.6,34.7,33,30.1,28.2,26.2,24.2,21.9,19.7,17,14.7,12.2,9.74,7.14,4.29,1.51,0.044,0.0451,0.0461,0.0472,0.0483,0.0494,0.0504,0.0515,0.0526,0.0537,0.0547,0.0558,0.0569,0.058,0.059,0.0601,0.0612,0.0623,0.0633,0.0644,0.0655,0.0666,0.0676,0.0687,0.0698,0.0709,0.0719,0.073,0.0741,0.0752,0.0762,0.0773,0.0784,0.0795,0.0805,0.0816,0.0827,0.0838,0.0848,0.0859,0.087,0.0881,0.0891,0.0902,0.0913,0.0924,0.0934,0.0945,0.0956,0.0966,0.0977,0.0988,0.0999,0.101,0.102,0.103,0.104,0.105,0.106,0.107,0.108,0.11,0.111,0.112,0.113,0.114,0.115,0.116,0.117,0.118,0.119,0.12,0.121,0.122,0.124,0.125,0.126,0.127,0.128,0.129,0.13,0.131,0.132,0.133,0.134,0.135,0.136,0.137,0.139,0.14,0.141,0.142,0.143,0.144,5.14,11.5,17.4,24.3,29.9,36.9,42,50.6,61.2,66.7,72.5,78.1,82.8,87.5,90.9,94.8,97.6,101,103,104,105,106,106,108,111,115,120,124,128,133,138,142,145,148,150,152,154,155,156,155,157,158,159,160,162,162,164,164,165,167,168,168,169,170,171,172,172,173,174,175,174,175,176,177,178,179,179,181,181,182,182,183,183,185,186,186,186,181,175,179,179,180,180,181,182,183,183,183,183,185,186,186,186,187,188,188,190,190,191,192,194,195,196,197,196,200,199,202,203,203,203,202,203,203,201,201,204,203,203,202,202,154];
|
||||
|
||||
let FT_1 = [0.138,0.131,0.124,0.117,0.122,0.128,0.133,0.138,0.145,0.152,0.159,0.169,0.179,0.199,0.209,0.219,0.266,0.335,0.357,0.425,0.467,0.509,0.551,0.595,0.639,0.682,0.729,0.773,0.816,0.859,0.903,0.947,0.989,1.01,1.05,1.1,1.12,1.16,1.2,1.22,1.27,1.29,1.33,1.36,1.38,1.42,1.44,1.46,1.5,1.53,1.57,1.59,1.61,1.63,1.68,1.7,1.72,1.76,1.78,1.8,1.82,1.87,1.89,1.93,1.95,1.97,2.01,2.03,2.06,2.1,2.12,2.14,2.16,2.21,2.23,2.25,2.29,2.31,2.33,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.35,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.34,2.33,2.29,2.23,2.18,2.11,2.07,2.02,1.96,1.89,1.85,1.78,1.74,1.67,1.62,1.56,1.51,1.44,1.39,1.33,1.26,1.19,1.12,1.06,0.984,0.892,0.819,0.725,0.64,0.569,0.451,0.345,0.249,0.186,0.123,0.056,0.028,0.007,0.00988,0.0128,0.0156,0.0185,0.0214,0.0243,0.0271,0.105,0.117,0.128,0.152,0.163,0.173,0.195,0.238,0.284,0.326,0.371,0.44,0.487,0.532,0.577,0.62,0.641,0.686,0.73,0.773,0.793,0.836,0.879,0.92,0.964,0.984,1.03,1.07,1.09,1.13,1.15,1.2,1.22,1.24,1.28,1.3,1.35,1.35,1.36,1.37,1.39,1.43,1.45,1.47,1.5,1.54,1.56,1.58,1.6,1.62,1.67,1.69,1.71,1.75,1.77,1.79,1.81,1.85,1.88,1.9,1.94,1.96,1.98,2,2.05,2.07,2.09,2.13,2.15,2.17,2.19,2.19,2.19,2.19,2.19,2.19,2.19,2.19,2.19,2.19,2.19,2.19,2.19,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.17,2.17,2.17,2.17,2.17,2.13,2.06,2.01,1.95,1.9,1.84,1.79,1.74,1.67,1.63,1.58,1.52,1.47,1.4,1.36,1.3,1.25,1.18,1.13,1.07,0.998,0.903,0.834,0.771,0.699,0.629,0.558,0.464,0.368,0.268,0.198,0.123,0.028,0.007,0.00964,0.0123,0.0149,0.0175,0.0202,0.0228,0.0255,0.0281,0.0307,0.0334,0.063,0.09,0.0987,0.107,0.116,0.19,0.21,0.252,0.295,0.339,0.404,0.449,0.472,0.515,0.56,0.606,0.627,0.671,0.692,0.736,0.779,0.799,0.844,0.885,0.906,0.951,0.992,1.01,1.04,1.08,1.1,1.12,1.17,1.19,1.21,1.25,1.27,1.29,1.31,1.35,1.38,1.4,1.42,1.44,1.46,1.5,1.53,1.55,1.57,1.59,1.61,1.63,1.67,1.69,1.71,1.73,1.75,1.78,1.82,1.84,1.86,1.88,1.91,1.95,1.97,1.99,2.03,2.05,2.07,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.09,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.08,2.07,2.07,2.03,1.99,1.92,1.87,1.83,1.76,1.72,1.68,1.61,1.57,1.52,1.47,1.43,1.36,1.32,1.25,1.2,1.16,1.09,1.03,0.961,0.919,0.851,0.76,0.688,0.623,0.553,0.48,0.381,0.285,0.21,0.135,0.034,0.01,0.0116,0.0133,0.0149,0.0166,0.0182,0.0199,0.0215,0.0232,0.0248,0.0265,0.0281,0.0298,0.0314,0.0331,0.0347,0.0364,0.116,0.181,0.226,0.247,0.291,0.335,0.377,0.421,0.442,0.486,0.529,0.55,0.593,0.614,0.636,0.677,0.699,0.721,0.763,0.784,0.826,0.848,0.89,0.911,0.932,0.975,0.996,1.02,1.04,1.06,1.08,1.1,1.12,1.15,1.19,1.21,1.23,1.25,1.27,1.29,1.32,1.34,1.36,1.38,1.4,1.44,1.46,1.49,1.51,1.53,1.55,1.59,1.61,1.63,1.66,1.68,1.7,1.74,1.76,1.78,1.8,1.82,1.87,1.89,1.91,1.91,1.91,1.91,1.91,1.9,1.9,1.9,1.9,1.9,1.9,1.9,1.9,1.9,1.89,1.89,1.89,1.89,1.89,1.89,1.89,1.89,1.89,1.9,1.9,1.9,1.9,1.9,1.9,1.91,1.91,1.91,1.9,1.87,1.82,1.78,1.74,1.67,1.63,1.58,1.53,1.49,1.45,1.4,1.36,1.29,1.27,1.2,1.18,1.12,1.03,0.983,0.937,0.87,0.802,0.74,0.67,0.623,0.556,0.491,0.418,0.342,0.274,0.21,0.142,0.043,0.019,0.0208,0.0226,0.0245,0.0263,0.0281,0.0299,0.0318,0.0336,0.0354,0.0372,0.0391,0.0409,0.0427,0.0445,0.0464,0.0482,0.073,0.148,0.191,0.212,0.233,0.256,0.278,0.323,0.345,0.389,0.41,0.432,0.474,0.518,0.539,0.56,0.581,0.625,0.636,0.668,0.679,0.711,0.732,0.754,0.776,0.797,0.819,0.841,0.862,0.904,0.915,0.926,0.947,0.968,0.989,1.01,1.03,1.05,1.07,1.09,1.14,1.16,1.18,1.2,1.22,1.24,1.26,1.3,1.32,1.37,1.41,1.42,1.45,1.47,1.49,1.51,1.54,1.56,1.6,1.62,1.64,1.65,1.66,1.68,1.7,1.72,1.72,1.71,1.71,1.7,1.69,1.68,1.68,1.68,1.68,1.68,1.68,1.68,1.67,1.67,1.67,1.67,1.67,1.67,1.67,1.67,1.67,1.67,1.66,1.66,1.66,1.66,1.66,1.67,1.68,1.7,1.69,1.68,1.64,1.59,1.55,1.5,1.45,1.41,1.37,1.29,1.25,1.18,1.13,1.09,1.05,1.03,0.979,0.938,0.891,0.848,0.801,0.757,0.694,0.606,0.537,0.491,0.421,0.375,0.305,0.26,0.213,0.191,0.113,0.021,0.0000000000000216,0.0015,0.003,0.0045,0.006,0.0075,0.009,0.0105,0.012,0.0135,0.015,0.0165,0.018,0.0195,0.021,0.0225,0.024,0.0255,0.027,0.0285,0.108,0.156,0.164,0.171,0.179,0.2,0.221,0.263,0.284,0.305,0.326,0.347,0.367,0.408,0.43,0.45,0.471,0.515,0.537,0.558,0.58,0.602,0.623,0.644,0.664,0.685,0.706,0.727,0.738,0.748,0.79,0.801,0.812,0.834,0.855,0.875,0.886,0.896,0.941,0.962,0.982,1,1.03,1.05,1.09,1.11,1.13,1.15,1.17,1.2,1.22,1.26,1.28,1.3,1.32,1.34,1.36,1.38,1.41,1.45,1.47,1.49,1.49,1.49,1.48,1.48,1.48,1.47,1.47,1.47,1.46,1.45,1.44,1.44,1.44,1.43,1.43,1.43,1.43,1.42,1.42,1.42,1.41];
|
||||
let FT_2 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.228,0.33,0.395,0.441,0.488,0.533,0.577,0.619,0.664,0.687,0.729,0.751,0.792,0.814,0.859,0.9,0.922,0.966,0.986,1.03,1.05,1.09,1.11,1.14,1.18,1.2,1.22,1.24,1.29,1.31,1.33,1.35,1.37,1.42,1.44,1.46,1.48,1.5,1.54,1.57,1.59,1.61,1.65,1.67,1.69,1.72,1.74,1.78,1.8,1.82,1.86,1.88,1.91,1.93,1.95,1.99,2.01,2.03,2.05,2.07,2.12,2.14,2.16,2.17,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.18,2.17,2.17,2.17,2.17,2.17,2.17,2.17,2.17,2.17,2.17,2.17,2.17,2.17,2.16,2.16,2.16,2.16,2.16,2.16,2.16,2.16,2.14,2.09,2.05,2,1.93,1.89,1.84,1.8,1.73,1.69,1.62,1.57,1.53,1.49,1.42,1.37,1.33,1.28,1.22,1.17,1.1,1.05,0.984,0.917,0.85,0.784,0.713,0.641,0.54,0.469,0.371,0.279,0.19,0.094,0.069,0.018,0.0204,0.0227,0.0251,0.0275,0.0298,0.0322,0.0345,0.0369,0.0393,0.0416,0.071,0.0768,0.0825,0.0883,0.094,0.164,0.206,0.252,0.322,0.369,0.415,0.458,0.501,0.546,0.568,0.613,0.654,0.677,0.719,0.741,0.784,0.805,0.827,0.869,0.889,0.91,0.931,0.975,0.996,1.02,1.06,1.08,1.12,1.15,1.19,1.21,1.23,1.25,1.29,1.32,1.34,1.36,1.38,1.4,1.44,1.46,1.49,1.51,1.53,1.55,1.57,1.61,1.63,1.65,1.67,1.7,1.72,1.74,1.78,1.8,1.82,1.84,1.86,1.89,1.91,1.95,1.97,1.99,2.02,2.04,2.06,2.08,2.08,2.08,2.08,2.08,2.07,2.07,2.07,2.07,2.07,2.07,2.07,2.07,2.07,2.07,2.07,2.07,2.07,2.06,2.06,2.06,2.06,2.06,2.06,2.06,2.06,2.06,2.06,2.06,2.06,2.06,2.01,1.97,1.92,1.88,1.83,1.79,1.72,1.67,1.63,1.58,1.52,1.47,1.43,1.38,1.32,1.28,1.23,1.17,1.1,1.05,0.982,0.936,0.869,0.826,0.762,0.694,0.623,0.548,0.479,0.386,0.311,0.192,0.123,0.047,0.018,0.0198,0.0216,0.0234,0.0253,0.0271,0.0289,0.0307,0.0325,0.0343,0.0361,0.0379,0.0398,0.0416,0.0434,0.0452,0.047,0.12,0.185,0.23,0.274,0.316,0.337,0.38,0.4,0.441,0.486,0.53,0.552,0.596,0.618,0.66,0.683,0.704,0.749,0.771,0.793,0.815,0.836,0.878,0.899,0.921,0.942,0.963,0.985,1.01,1.03,1.05,1.07,1.11,1.13,1.16,1.18,1.2,1.22,1.26,1.28,1.3,1.32,1.35,1.37,1.39,1.41,1.43,1.47,1.5,1.52,1.54,1.56,1.58,1.6,1.62,1.64,1.69,1.71,1.73,1.75,1.77,1.79,1.84,1.86,1.88,1.9,1.91,1.92,1.92,1.92,1.92,1.92,1.92,1.92,1.92,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.91,1.9,1.9,1.9,1.9,1.9,1.9,1.9,1.88,1.84,1.79,1.74,1.7,1.66,1.62,1.57,1.52,1.45,1.41,1.37,1.32,1.28,1.23,1.19,1.14,1.08,1.01,0.962,0.917,0.872,0.805,0.76,0.695,0.625,0.555,0.49,0.443,0.375,0.281,0.186,0.116,0.089,0.045,0.017,0.0184,0.0198,0.0212,0.0226,0.0241,0.0255,0.0269,0.0283,0.0297,0.0311,0.0325,0.0339,0.0354,0.0368,0.0382,0.0396,0.11,0.134,0.155,0.175,0.219,0.288,0.3,0.357,0.4,0.421,0.465,0.472,0.479,0.486,0.507,0.528,0.549,0.617,0.66,0.682,0.702,0.724,0.746,0.767,0.788,0.809,0.853,0.874,0.894,0.917,0.938,0.959,0.98,0.991,1.02,1.03,1.04,1.06,1.09,1.11,1.12,1.13,1.15,1.17,1.19,1.21,1.22,1.23,1.27,1.32,1.33,1.34,1.35,1.36,1.38,1.4,1.44,1.47,1.49,1.53,1.55,1.57,1.59,1.62,1.64,1.65,1.66,1.67,1.68,1.67,1.66,1.66,1.65,1.65,1.65,1.65,1.65,1.65,1.65,1.64,1.64,1.64,1.64,1.64,1.64,1.64,1.64,1.64,1.65,1.65,1.65,1.65,1.66,1.68,1.66,1.64,1.59,1.55,1.48,1.44,1.39,1.35,1.3,1.24,1.2,1.18,1.14,1.11,1.07,1.05,1.01,0.983,0.941,0.92,0.876,0.833,0.79,0.747,0.649,0.576,0.51,0.465,0.396,0.349,0.306,0.211,0.144,0.099,0.073,0.044,0.017,0.0186,0.0202,0.0217,0.0233,0.0249,0.0265,0.0281,0.0296,0.0312,0.0328,0.0344,0.0359,0.0375,0.0391,0.0407,0.0423,0.0438,0.0454,0.101,0.144,0.166,0.176,0.186,0.206,0.229,0.251,0.261,0.295,0.363,0.385,0.427,0.448,0.469,0.49,0.5,0.511,0.532,0.554,0.565,0.599,0.62,0.642,0.686,0.696,0.727,0.737,0.748,0.769,0.791,0.812,0.833,0.844,0.855,0.875,0.895,0.916,0.937,0.957,0.999,1.01,1.02,1.04,1.06,1.08,1.11,1.13,1.15,1.17,1.19,1.21,1.23,1.28,1.3,1.32,1.34,1.36,1.38,1.4,1.42,1.44,1.47,1.47,1.47,1.48,1.48,1.49,1.51,1.49,1.48,1.47,1.47,1.46,1.46,1.46,1.46,1.46,1.45,1.45,1.45,1.45,1.44];
|
||||
let FT_3 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.086,0.257,0.299,0.345,0.392,0.435,0.48,0.525,0.566,0.609,0.653,0.674,0.696,0.74,0.763,0.808,0.831,0.876,0.898,0.92,0.964,0.984,1,1.03,1.05,1.07,1.09,1.11,1.16,1.18,1.2,1.22,1.24,1.26,1.29,1.33,1.35,1.37,1.39,1.41,1.43,1.46,1.48,1.5,1.52,1.54,1.56,1.58,1.62,1.64,1.67,1.69,1.71,1.73,1.75,1.78,1.82,1.84,1.86,1.88,1.9,1.92,1.94,1.96,1.96,1.96,1.96,1.96,1.96,1.96,1.96,1.96,1.96,1.96,1.96,1.96,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.95,1.94,1.94,1.94,1.94,1.94,1.94,1.9,1.85,1.81,1.77,1.72,1.65,1.61,1.56,1.52,1.47,1.43,1.38,1.34,1.29,1.25,1.2,1.14,1.09,1.05,1,0.94,0.869,0.801,0.736,0.691,0.624,0.555,0.443,0.351,0.276,0.205,0.098,0.018,0.0193,0.0207,0.022,0.0233,0.0247,0.026,0.0273,0.0287,0.03,0.0313,0.0327,0.034,0.0353,0.0367,0.038,0.0393,0.0407,0.139,0.188,0.228,0.25,0.293,0.314,0.359,0.403,0.424,0.466,0.511,0.553,0.575,0.619,0.641,0.683,0.705,0.728,0.749,0.77,0.791,0.813,0.859,0.879,0.9,0.921,0.943,0.963,1.01,1.03,1.05,1.07,1.09,1.11,1.13,1.16,1.18,1.2,1.22,1.24,1.26,1.27,1.28,1.31,1.33,1.35,1.39,1.41,1.43,1.45,1.47,1.5,1.52,1.54,1.56,1.58,1.6,1.64,1.66,1.68,1.71,1.73,1.75,1.77,1.79,1.79,1.79,1.79,1.79,1.79,1.79,1.78,1.78,1.78,1.78,1.78,1.78,1.78,1.78,1.78,1.78,1.78,1.78,1.78,1.77,1.77,1.77,1.77,1.77,1.77,1.77,1.77,1.77,1.77,1.77,1.77,1.77,1.76,1.72,1.68,1.64,1.59,1.55,1.5,1.46,1.41,1.37,1.32,1.28,1.23,1.19,1.17,1.12,1.07,0.986,0.944,0.899,0.831,0.789,0.724,0.679,0.611,0.546,0.471,0.401,0.326,0.26,0.196,0.079,0.052,0.029,0.009,0.0104,0.0119,0.0133,0.0147,0.0162,0.0176,0.0191,0.0205,0.0219,0.0234,0.0248,0.0262,0.0277,0.0291,0.0306,0.032,0.125,0.193,0.213,0.223,0.234,0.277,0.299,0.32,0.343,0.386,0.408,0.451,0.474,0.517,0.54,0.585,0.607,0.628,0.65,0.671,0.692,0.735,0.756,0.777,0.798,0.82,0.83,0.841,0.882,0.903,0.913,0.924,0.946,0.966,0.988,1.01,1.03,1.05,1.06,1.07,1.09,1.12,1.14,1.16,1.18,1.2,1.22,1.24,1.29,1.33,1.34,1.37,1.39,1.41,1.43,1.46,1.48,1.5,1.52,1.54,1.56,1.58,1.6,1.63,1.64,1.65,1.64,1.64,1.63,1.63,1.62,1.6,1.61,1.61,1.61,1.61,1.61,1.61,1.61,1.61,1.61,1.61,1.61,1.62,1.62,1.62,1.62,1.62,1.62,1.62,1.62,1.62,1.62,1.63,1.62,1.61,1.6,1.56,1.51,1.47,1.43,1.38,1.34,1.29,1.25,1.21,1.17,1.12,1.1,1.06,1.03,0.989,0.944,0.901,0.881,0.835,0.792,0.749,0.651,0.589,0.525,0.453,0.409,0.34,0.265,0.222,0.179,0.074,0.0615,0.00000000000000455,0.00105,0.0021,0.00315,0.0042,0.00525,0.0063,0.00735,0.0084,0.00945,0.0105,0.0116,0.0126,0.0137,0.0147,0.0158,0.0168,0.0179,0.0189,0.02,0.116,0.159,0.182,0.192,0.202,0.244,0.265,0.285,0.306,0.328,0.349,0.37,0.413,0.424,0.434,0.454,0.476,0.518,0.54,0.561,0.604,0.626,0.647,0.669,0.69,0.711,0.733,0.754,0.775,0.796,0.817,0.828,0.838,0.86,0.88,0.89,0.9,0.921,0.944,0.964,0.985,1.01,1.03,1.05,1.07,1.09,1.11,1.13,1.16,1.18,1.2,1.22,1.24,1.26,1.3,1.33,1.35,1.37,1.39,1.41,1.43,1.45,1.46,1.46,1.47,1.48,1.49,1.5,1.49,1.48,1.45,1.45,1.45,1.45,1.45,1.44,1.44,1.44,1.44,1.43,1.43,1.43,1.38];
|
||||
let FT_4 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.0235,0.0236,0.0236,0.0237,0.0237,0.0238,0.0238,0.0239,0.0239,0.125,0.138,0.15,0.248,0.325,0.525,0.734,0.803,0.847,0.892,0.958,1.03,1.07,1.11,1.16,1.18,1.22,1.26,1.31,1.35,1.39,1.42,1.46,1.47,1.48,1.5,1.55,1.57,1.61,1.63,1.67,1.72,1.74,1.78,1.8,1.85,1.87,1.89,1.94,1.96,2,2.04,2.07,2.09,2.13,2.15,2.2,2.22,2.26,2.3,2.31,2.32,2.32,2.34,2.36,2.37,2.39,2.4,2.41,2.43,2.44,2.45,2.46,2.47,2.5,2.51,2.52,2.54,2.56,2.6,2.64,2.69,2.73,2.8,2.84,2.89,2.93,2.95,2.95,2.94,2.93,2.93,2.93,2.93,2.93,2.93,2.93,2.93,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.92,2.91,2.91,2.91,2.84,2.75,2.65,2.6,2.55,2.53,2.51,2.47,2.44,2.42,2.38,2.36,2.34,2.3,2.25,2.2,2.14,2.07,2,1.96,1.91,1.81,1.75,1.7,1.63,1.58,1.51,1.46,1.37,1.32,1.26,1.19,1.12,1.01,0.938,0.832,0.678,0.549,0.4,0.259,0.133,0.019,0.0215,0.024,0.0265,0.029,0.0315,0.034,0.0365,0.039,0.0415,0.066,0.11,0.178,0.244,0.318,0.43,0.554,0.786,0.854,0.895,0.917,0.939,0.985,1.03,1.05,1.09,1.14,1.18,1.22,1.24,1.29,1.31,1.33,1.37,1.39,1.44,1.46,1.48,1.52,1.54,1.58,1.6,1.65,1.67,1.71,1.72,1.73,1.78,1.8,1.82,1.86,1.91,1.93,1.95,1.97,2.01,2.03,2.05,2.07,2.08,2.09,2.1,2.14,2.16,2.17,2.18,2.19,2.2,2.22,2.23,2.23,2.24,2.25,2.26,2.27,2.28,2.28,2.33,2.37,2.39,2.43,2.48,2.03,2.55,2.59,2.64,2.66,2.66,2.66,2.65,2.65,2.65,2.65,2.65,2.65,2.65,2.65,2.65,2.64,2.64,2.64,2.64,2.64,2.64,2.64,2.64,2.61,2.52,2.44,2.37,2.32,2.28,2.26,2.24,2.21,2.19,2.17,2.16,2.15,2.13,2.08,2.04,2,1.95,1.89,1.84,1.8,1.76,1.69,1.65,1.6,1.56,1.44,1.4,1.36,1.29,1.25,1.16,1.12,1.05,0.947,0.905,0.79,0.662,0.534,0.384,0.18,0.059,0.037,0.008,0.00983,0.0117,0.0135,0.0153,0.0172,0.019,0.0208,0.0227,0.0245,0.0263,0.0282,0.109,0.131,0.201,0.272,0.438,0.771,0.819,0.866,0.932,0.974,1.02,1.04,1.05,1.08,1.1,1.14,1.17,1.19,1.21,1.25,1.27,1.29,1.31,1.36,1.38,1.4,1.42,1.44,1.48,1.49,1.53,1.55,1.59,1.61,1.63,1.65,1.69,1.71,1.73,1.76,1.8,1.82,1.86,1.87,1.88,1.9,1.91,1.91,1.92,1.93,1.95,1.95,1.96,1.96,1.96,1.97,1.98,1.98,1.99,2,2,2.01,2.02,2.03,2.08,2.1,1.71,1.73,2.18,1.46,1.66,2.28,2.32,2.34,2.36,2.37,2.34,2.35,2.36,2.36,2.37,2.38,2.39,2.26,2.14];
|
||||
let FT_5 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.205,0.594,0.685,0.707,0.751,0.772,0.815,0.836,0.877,0.92,0.941,1,1.03,1.07,1.11,1.13,1.16,1.2,1.22,1.24,1.28,1.3,1.32,1.37,1.39,1.41,1.45,1.47,1.49,1.52,1.56,1.58,1.6,1.62,1.66,1.68,1.7,1.73,1.77,1.79,1.81,1.83,1.85,1.89,1.91,1.93,1.96,1.97,1.98,1.99,2.02,2.04,2.05,2.06,2.07,2.08,2.08,2.09,2.1,2.1,2.12,2.14,2.15,2.16,2.17,2.18,2.21,2.25,2.3,2.34,2.38,2.43,2.47,2.5,2.54,2.54,2.54,2.54,2.53,2.53,2.53,2.53,2.53,2.53,2.53,2.53,2.53,2.53,2.52,2.52,2.52,2.52,2.52,2.52,2.45,2.38,2.29,2.22,2.2,2.18,2.15,2.13,2.11,2.1,2.07,2.05,2.04,2.01,1.97,1.92,1.88,1.83,1.77,1.72,1.68,1.61,1.56,1.5,1.45,1.38,1.28,1.24,1.17,1.11,1.04,0.97,0.875,0.805,0.737,0.611,0.438,0.292,0.113,0.01,0.0125,0.015,0.0175,0.02,0.0225,0.025,0.0275,0.03,0.0325,0.035,0.0375,0.04,0.0425,0.227,0.509,0.637,0.679,0.7,0.743,0.765,0.776,0.81,0.831,0.873,0.893,0.935,0.956,0.978,1,1.04,1.06,1.08,1.11,1.13,1.15,1.19,1.21,1.24,1.26,1.28,1.32,1.34,1.36,1.39,1.41,1.43,1.45,1.47,1.49,1.53,1.56,1.58,1.6,1.62,1.64,1.68,1.7,1.73,1.75,1.77,1.78,1.79,1.8,1.8,1.81,1.81,1.82,1.83,1.84,1.85,1.85,1.86,1.87,1.88,1.89,1.89,1.9,1.91,1.93,1.94,1.98,2,2.02,2.07,2.12,2.16,2.18,2.2,2.25,2.24,2.23,2.23,2.22,2.21,2.21,2.2,2.19,2.18,2.18,2.17];
|
||||
let FT_6 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.072,0.0825,0.093,0.103,0.114,0.135,0.18,0.253,0.327,0.455,0.526,0.591,0.66,0.703,0.794,0.838,0.86,0.88,0.901,0.922,0.965,0.986,1.01,1.05,1.07,1.11,1.14,1.16,1.2,1.22,1.24,1.26,1.31,1.33,1.35,1.37,1.41,1.43,1.45,1.47,1.52,1.54,1.56,1.58,1.6,1.64,1.66,1.68,1.7,1.75,1.77,1.79,1.83,1.88,1.92,1.94,1.95,1.96,1.97,1.97,1.98,1.99,1.99,2,2.01,2.02,2.02,2.03,2.04,2.07,2.07,2.08,2.08,2.08,2.09,2.11,2.13,2.17,2.21,2.25,2.27,2.35,2.39,2.41,2.43,2.45,2.45,2.45,2.45,2.45,2.45,2.44,2.44,2.44,2.44,2.44,2.43];
|
||||
|
||||
let ET_1 = [8.19,7.63,7.63,8.37,8.34,9.13,9,9.22,9.93,9.67,10.7,10.7,11.3,11.9,12.1,12.4,13.3,14.8,15.8,16.6,17.5,18.4,20,21.3,22.6,23.8,24.9,26.6,28.1,29.4,31.2,32.4,34.1,35.5,37.1,38.6,40.6,42.5,44.5,45.9,48.1,50.2,52.4,54.3,56.1,57.7,60,62.7,64.8,66.4,68.4,71.5,73.7,76,78.5,81.2,83.3,86.8,89.2,91.9,94.4,103,107,110,114,117,121,125,129,134,136,140,145,149,153,157,162,169,172,172,173,174,175,175,174,175,174,175,174,174,174,173,174,174,174,175,175,174,175,174,175,174,176,174,175,174,175,174,175,174,175,174,167,159,151,141,134,126,119,113,105,98.3,92.2,83.2,76.9,72,67.3,62.6,58.8,54.6,51.2,46.8,43.4,39.3,35.7,32.7,29.8,26.9,24.3,21.7,18.9,16.9,14.3,12.6,11.2,10,9.24,9.08,8.08,7.55,7.96,7.84,7.97,8.83,9.03,9.44,9.65,10.1,10.4,11.1,10.9,11.5,12.6,13.2,14,15,16,17.2,18.1,19.2,20.4,21.6,22.8,24.5,25.2,27,28.2,29.6,31.6,33.1,33.9,35.9,37.8,39.1,41.1,42.6,44.3,46.4,48.8,50.6,51.8,54.2,56.2,56.8,58.7,61,62.8,64.5,67.1,69.4,71.4,74,76.8,78.8,81.4,84,86.9,90.2,93.4,95.7,105,108,111,114,118,122,125,130,133,137,141,144,149,153,158,163,165,166,167,165,167,166,167,167,167,166,166,167,167,165,166,165,166,167,167,166,166,166,167,167,167,166,166,166,166,166,167,166,167,165,158,149,140,132,125,117,111,104,97.3,91.2,80.9,76.2,70.9,67.1,61.9,58,53.8,49.8,46.5,43,39,36.2,33,29.6,26.3,24.6,21.8,19,17.4,15.2,13.2,12.4,10.3,9.61,8.81,8.53,8.03,7.77,8.03,7.8,8.27,8.6,8.79,9.07,9.58,9.87,10.5,10.4,10.4,11.3,12.7,13.1,14.4,14.9,15.5,17.2,18.2,19,19.7,21.5,22.8,23.8,24.8,26.5,27.8,29,30.4,32.1,33.7,35.2,36.8,38.5,40.6,42.1,44.1,45.6,47,49.5,51.1,52.7,55.1,57,58.5,60.9,62.8,65.2,67.7,70.1,72.3,74.6,76.9,79.6,81.1,84.4,87.2,90.2,92.9,96.7,105,108,112,115,118,121,125,130,133,136,141,145,149,154,158,163,164,164,165,162,164,164,164,164,165,164,164,164,164,164,164,164,164,165,164,165,164,164,165,164,165,165,165,164,165,165,164,164,165,158,149,141,134,125,118,112,105,98.4,91.9,82.1,77,73,68.1,62.7,59,54.9,50.9,47.7,43.6,39.8,36.7,33.6,30,27.4,25.1,22.5,19.9,17.8,15.9,14,12.1,11.1,9.94,9.04,8.5,8.09,7.71,8.18,8.18,8.4,8.47,8.75,9.35,8.97,9.38,9.96,10.2,10.3,10.8,11.2,11.9,12.7,14.1,14.9,15.7,16.3,17.2,18.5,19.4,20.8,21.6,22.7,24.2,25.7,27,27.9,29.6,30.8,32.7,34.2,35.4,37.1,38.9,40.5,42,44,45.5,47.5,49.2,51.2,53.1,54.7,56.7,58.3,60.3,62.5,64.5,67.2,69.3,71.1,73.5,76.9,79.5,81.5,82.4,85.8,89.6,92.1,93.5,104,107,111,114,117,120,125,128,133,137,141,145,149,154,159,161,160,161,161,160,160,160,160,161,160,160,161,160,161,160,160,160,160,159,160,160,161,160,160,160,159,160,160,161,160,160,161,159,147,140,132,125,118,111,104,97.1,86.4,81.2,75.7,70.9,66.4,62.3,58.3,54.6,50.5,46.6,43.2,39.5,36,32.7,30.1,26.8,24.5,22,21.3,17.5,15.7,14.3,12,11.9,10.3,9.4,9.11,8.63,7.98,7.6,7.83,7.7,8.58,9.57,9.38,9.12,9.7,9.56,10.5,10.6,10.5,11,12,12.8,13.1,14.1,14.5,15,16.2,17.5,18.3,18.8,20,21.1,22.3,23,24.3,25.5,27.4,28.9,29.5,30.9,32.2,33.8,35,37.4,38.5,40.6,41,43.9,45.2,47.3,48.7,50.6,52,54,56.2,57.7,60,61.8,63.6,65.6,68,70.4,73.1,75.1,77,80.6,83.5,86,90.1,93,96.6,104,108,111,116,119,123,126,130,133,138,141,146,149,153,156,157,157,157,157,157,157,158,156,158,156,157,156,157,157,158,157,159,158,157,156,157,157,157,156,157,157,157,157,158,157,154,146,138,130,122,115,109,102,95.3,81.5,79.2,72.4,67.9,63.7,60.2,55.8,52.2,48.7,44.7,41.7,41.7,35.4,31.8,28.2,25.5,23.4,20.8,18.7,16.8,15.4,14.1,12.9,11,10.3,9.82,9.5,8.7,8.19,7.6,7.22,8.27,7.91,8.42,8.61,8.83,9.16,9.57,9.66,9.95,9.99,10.5,10.9,12.1,11.9,12.5,13.9,14.3,14.2,15.2,16.1,17.3,17.3,18.4,19.6,20.6,21.5,22.1,23.7,24.6,26.1,27.2,28.7,30,31.9,32.8,34,35.6,36.7,38.3,40.3,41.6,43.1,44.8,46.5,49,49.9,52,53.4,55.9,58,59.8,62.3,64.8,67,69.4,72,73.2,76.4,79.3,82.4,85.5,88.6,91,94.2,97.9,106,110,113,117,120,124,126,132,134,139,140,143,148,150,150,152,154,153,152,153,152,152,152,152,152,153,152,152,154,153,154,154];
|
||||
49
readme/measured_curve.json
Normal file
49
readme/measured_curve.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"100": {
|
||||
"is_valid": false,
|
||||
"error": 0,
|
||||
"ctrl_curve": { "50": 50 },
|
||||
"flow_curve": { "50": 0.019667187500000002 },
|
||||
"power_curve": { "50": 8.482656250000002 }
|
||||
},
|
||||
"125": {
|
||||
"is_valid": false,
|
||||
"error": 0,
|
||||
"ctrl_curve": { "100": 100 },
|
||||
"flow_curve": { "100": 0.0835 },
|
||||
"power_curve": { "100": 10.4 }
|
||||
},
|
||||
"150": {
|
||||
"is_valid": false,
|
||||
"error": 0,
|
||||
"ctrl_curve": { "200": 200 },
|
||||
"flow_curve": { "200": 0.32146874999999997 },
|
||||
"power_curve": { "200": 16.7125 }
|
||||
},
|
||||
"175": {
|
||||
"is_valid": true,
|
||||
"error": 0,
|
||||
"ctrl_curve": { "0": 0, "350": 350, "550": 550, "600": 600, "1000": 1000 },
|
||||
"flow_curve": {
|
||||
"0": 0,
|
||||
"350": 0.9294287109375,
|
||||
"550": 0.941,
|
||||
"600": 1.05,
|
||||
"1000": 1.922000000000001
|
||||
},
|
||||
"power_curve": {
|
||||
"0": 5.076000000000002,
|
||||
"350": 39.11787109375,
|
||||
"550": 64.8,
|
||||
"600": 76.4,
|
||||
"1000": 169.20000000000007
|
||||
}
|
||||
},
|
||||
"200": {
|
||||
"is_valid": false,
|
||||
"error": 0,
|
||||
"ctrl_curve": { "550": 550 },
|
||||
"flow_curve": { "550": 1.8175000000000001 },
|
||||
"power_curve": { "550": 94.55 }
|
||||
}
|
||||
}
|
||||
297
rotatingMachine.html
Normal file
297
rotatingMachine.html
Normal file
@@ -0,0 +1,297 @@
|
||||
<script type="module">
|
||||
|
||||
import * as menuUtils from "/generalFunctions/helper/menuUtils.js";
|
||||
|
||||
RED.nodes.registerType("rotatingMachine", {
|
||||
category: "digital twin",
|
||||
color: "#4f8582",
|
||||
|
||||
defaults: {
|
||||
// Define default properties
|
||||
name: { value: "", required: true },
|
||||
enableLog: { value: false },
|
||||
logLevel: { value: "error" },
|
||||
|
||||
// Define specific properties
|
||||
speed: { value: 1, required: true },
|
||||
startup: { value: 0 },
|
||||
warmup: { value: 0 },
|
||||
shutdown: { value: 0 },
|
||||
cooldown: { value: 0 },
|
||||
|
||||
//define general asset properties
|
||||
supplier: { value: "" },
|
||||
subType: { value: "" },
|
||||
model: { value: "" },
|
||||
unit: { value: "" },
|
||||
|
||||
//define specific asset properties
|
||||
machineCurve : { value: {}},
|
||||
},
|
||||
|
||||
inputs: 1,
|
||||
outputs: 4,
|
||||
inputLabels: ["Machine Input"],
|
||||
outputLabels: ["process", "dbase", "upstreamParent", "downstreamParent"],
|
||||
icon: "font-awesome/fa-cogs",
|
||||
|
||||
label: function () {
|
||||
return this.name || "Rotating Machine";
|
||||
},
|
||||
|
||||
oneditprepare: function () {
|
||||
const node = this;
|
||||
|
||||
console.log("Rotating Machine Node: Edit Prepare");
|
||||
|
||||
const elements = {
|
||||
// Basic fields
|
||||
name: document.getElementById("node-input-name"),
|
||||
// specific fields
|
||||
speed: document.getElementById("node-input-speed"),
|
||||
startup: document.getElementById("node-input-startup"),
|
||||
warmup: document.getElementById("node-input-warmup"),
|
||||
shutdown: document.getElementById("node-input-shutdown"),
|
||||
cooldown: document.getElementById("node-input-cooldown"),
|
||||
// Logging fields
|
||||
logCheckbox: document.getElementById("node-input-enableLog"),
|
||||
logLevelSelect: document.getElementById("node-input-logLevel"),
|
||||
rowLogLevel: document.getElementById("row-logLevel"),
|
||||
// Asset fields
|
||||
supplier: document.getElementById("node-input-supplier"),
|
||||
subType: document.getElementById("node-input-subType"),
|
||||
model: document.getElementById("node-input-model"),
|
||||
unit: document.getElementById("node-input-unit"),
|
||||
};
|
||||
|
||||
const projecSettingstURL = "http://localhost:1880/generalFunctions/settings/projectSettings.json";
|
||||
|
||||
try{
|
||||
|
||||
// Fetch project settings
|
||||
menuUtils.fetchProjectData(projecSettingstURL)
|
||||
.then((projectSettings) => {
|
||||
|
||||
//assign to node vars
|
||||
node.configUrls = projectSettings.configUrls;
|
||||
|
||||
const { cloudConfigURL, localConfigURL } = menuUtils.getSpecificConfigUrl("rotatingMachine",node.configUrls.cloud.taggcodeAPI);
|
||||
node.configUrls.cloud.config = cloudConfigURL; // first call
|
||||
node.configUrls.local.config = localConfigURL; // backup call
|
||||
|
||||
node.locationId = projectSettings.locationId;
|
||||
node.uuid = projectSettings.uuid;
|
||||
|
||||
// Gets the ID of the active workspace (Flow)
|
||||
const activeFlowId = RED.workspaces.active(); //fetches active flow id
|
||||
node.processId = activeFlowId;
|
||||
|
||||
// UI elements
|
||||
menuUtils.initBasicToggles(elements);
|
||||
menuUtils.fetchAndPopulateDropdowns(node.configUrls, elements, node); // function for all assets
|
||||
|
||||
})
|
||||
|
||||
}catch(e){
|
||||
console.log("Error fetching project settings", e);
|
||||
}
|
||||
|
||||
if(node.d){
|
||||
//this means node is disabled
|
||||
console.log("Current status of node is disabled");
|
||||
}
|
||||
},
|
||||
|
||||
oneditsave: function () {
|
||||
const node = this;
|
||||
|
||||
console.log(`------------ Saving changes to node ------------`);
|
||||
console.log(`${node.uuid}`);
|
||||
|
||||
//save basic properties
|
||||
["name", "unit", "supplier", "subType", "model"].forEach(
|
||||
(field) => {
|
||||
const element = document.getElementById(`node-input-${field}`);
|
||||
if (element) {
|
||||
node[field] = element.value || "";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Save numeric and boolean properties
|
||||
["speed", "startup", "warmup", "shutdown", "cooldown"].forEach(
|
||||
(field) => {
|
||||
const element = document.getElementById(`node-input-${field}`);
|
||||
if (element) {
|
||||
node[field] = Number(element.value) || 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
/*
|
||||
//local db
|
||||
node[field] = node["modelMetadata"][field];
|
||||
//central db
|
||||
node[field] = node["modelMetadata"]["product_model_meta"][field];
|
||||
*/
|
||||
|
||||
//save meta data curve central db
|
||||
["machineCurve"].forEach(
|
||||
(field) => {
|
||||
node[field] = node.modelMetadata.product_model_meta
|
||||
? node.modelMetadata.product_model_meta[field]
|
||||
: node.modelMetadata[field];
|
||||
//console.log(node[field]);
|
||||
console.log("Machine curve saved");
|
||||
}
|
||||
);
|
||||
|
||||
const logLevelElement = document.getElementById("node-input-logLevel");
|
||||
node.logLevel = logLevelElement ? logLevelElement.value || "info" : "info";
|
||||
|
||||
if (!node.unit) {
|
||||
RED.notify("Unit selection is required.", "error");
|
||||
}
|
||||
|
||||
if (node.subType && !node.unit) {
|
||||
RED.notify("Unit must be set when specifying a subtype.", "error");
|
||||
}
|
||||
|
||||
try{
|
||||
console.log("Saving assetID and tagnumber");
|
||||
console.log(node.assetTagCode);
|
||||
// Fetch project settings
|
||||
menuUtils.apiCall(node,node.configUrls)
|
||||
.then((response) => {
|
||||
|
||||
console.log(" ====<<>>>> API call response", response);
|
||||
|
||||
//save response to node information
|
||||
node.assetId = response.asset_id;
|
||||
node.assetTagCode = response.asset_tag_number;
|
||||
})
|
||||
.catch((error) => {
|
||||
console.log("Error during API call", error);
|
||||
});
|
||||
}catch(e){
|
||||
console.log("Error saving assetID and tagnumber", e);
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Main UI Template -->
|
||||
<script type="text/html" data-template-name="rotatingMachine">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="node-input-name"
|
||||
placeholder="Machine Name"
|
||||
style="width:70%;"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-speed"><i class="fa fa-clock-o"></i> Reaction Speed</label>
|
||||
<input type="number" id="node-input-speed" placeholder="1" />
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-startup"><i class="fa fa-clock-o"></i> Startup Time</label>
|
||||
<input type="number" id="node-input-startup" placeholder="0" />
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-warmup"><i class="fa fa-clock-o"></i> Warmup Time</label>
|
||||
<input type="number" id="node-input-warmup" placeholder="0" />
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-shutdown"><i class="fa fa-clock-o"></i> Shutdown Time</label>
|
||||
<input type="number" id="node-input-shutdown" placeholder="0" />
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-cooldown"><i class="fa fa-clock-o"></i> Cooldown Time</label>
|
||||
<input type="number" id="node-input-cooldown" placeholder="0" />
|
||||
</div>
|
||||
|
||||
<!-- Optional Extended Fields: supplier, type, subType, model -->
|
||||
<hr />
|
||||
<div class="form-row">
|
||||
<label for="node-input-supplier"
|
||||
><i class="fa fa-industry"></i> Supplier</label
|
||||
>
|
||||
<select id="node-input-supplier" style="width:60%;">
|
||||
<option value="">(optional)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-subType"
|
||||
><i class="fa fa-puzzle-piece"></i> SubType</label
|
||||
>
|
||||
<select id="node-input-subType" style="width:60%;">
|
||||
<option value="">(optional)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-model"><i class="fa fa-wrench"></i> Model</label>
|
||||
<select id="node-input-model" style="width:60%;">
|
||||
<option value="">(optional)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-unit"><i class="fa fa-balance-scale"></i> Unit</label>
|
||||
<select id="node-input-unit" style="width:60%;"></select>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<!-- loglevel checkbox -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-enableLog"
|
||||
><i class="fa fa-cog"></i> Enable Log</label
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
id="node-input-enableLog"
|
||||
style="width:20px; vertical-align:baseline;"
|
||||
/>
|
||||
<span>Enable logging</span>
|
||||
</div>
|
||||
|
||||
<div class="form-row" id="row-logLevel">
|
||||
<label for="node-input-logLevel"><i class="fa fa-cog"></i> Log Level</label>
|
||||
<select id="node-input-logLevel" style="width:60%;">
|
||||
<option value="info">Info</option>
|
||||
<option value="debug">Debug</option>
|
||||
<option value="warn">Warn</option>
|
||||
<option value="error">Error</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="rotatingMachine">
|
||||
<p>
|
||||
<b>Rotating Machine Node</b>: Configure the behavior of a rotating machine
|
||||
used in a digital twin.
|
||||
</p>
|
||||
<ul>
|
||||
<li><b>Supplier:</b> Select a supplier to populate machine options.</li>
|
||||
<li><b>SubType:</b> Select a subtype if applicable to further categorize the asset.</li>
|
||||
<li><b>Model:</b> Define the specific model for more granular asset configuration.</li>
|
||||
<li><b>Unit:</b> Assign a unit to standardize measurements or operations.</li>
|
||||
<li><b>Speed:</b> Reaction speed of the machine in response to inputs.</li>
|
||||
<li><b>Startup:</b> Define the startup time for the machine.</li>
|
||||
<li><b>Warmup:</b> Define the warmup time for the machine.</li>
|
||||
<li><b>Shutdown:</b> Define the shutdown time for the machine.</li>
|
||||
<li><b>Cooldown:</b> Define the cooldown time for the machine.</li>
|
||||
<li><b>Enable Log:</b> Enable or disable logging for the machine.</li>
|
||||
<li><b>Log Level:</b> Set the log level (Info, Debug, Warn, Error).</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
247
rotatingMachine.js
Normal file
247
rotatingMachine.js
Normal file
@@ -0,0 +1,247 @@
|
||||
module.exports = function (RED) {
|
||||
function rotatingMachine(config) {
|
||||
RED.nodes.createNode(this, config);
|
||||
var node = this;
|
||||
|
||||
try {
|
||||
// Load Machine class and curve data
|
||||
const Machine = require("./dependencies/machine/machine");
|
||||
const OutputUtils = require("../generalFunctions/helper/outputUtils");
|
||||
|
||||
const machineConfig = {
|
||||
general: {
|
||||
name: config.name || "Default Machine",
|
||||
id: node.id,
|
||||
logging: {
|
||||
enabled: config.eneableLog,
|
||||
logLevel: config.logLevel
|
||||
}
|
||||
},
|
||||
asset: {
|
||||
supplier: config.supplier || "Unknown",
|
||||
type: config.machineType || "generic",
|
||||
subType: config.subType || "generic",
|
||||
model: config.model || "generic",
|
||||
machineCurve: config.machineCurve
|
||||
}
|
||||
};
|
||||
|
||||
const stateConfig = {
|
||||
general: {
|
||||
logging: {
|
||||
enabled: config.eneableLog,
|
||||
logLevel: config.logLevel
|
||||
}
|
||||
},
|
||||
movement: {
|
||||
speed: Number(config.speed)
|
||||
},
|
||||
time: {
|
||||
starting: Number(config.startup),
|
||||
warmingup: Number(config.warmup),
|
||||
stopping: Number(config.shutdown),
|
||||
coolingdown: Number(config.cooldown)
|
||||
}
|
||||
};
|
||||
|
||||
// Create machine instance
|
||||
const m = new Machine(machineConfig, stateConfig);
|
||||
|
||||
// put m on node memory as source
|
||||
node.source = m;
|
||||
|
||||
//load output utils
|
||||
const output = new OutputUtils();
|
||||
|
||||
function updateNodeStatus() {
|
||||
try {
|
||||
const mode = m.currentMode;
|
||||
const state = m.state.getCurrentState();
|
||||
const flow = Math.round(m.measurements.type("flow").variant("predicted").position('downstream').getCurrentValue());
|
||||
const power = Math.round(m.measurements.type("power").variant("predicted").position('upstream').getCurrentValue());
|
||||
let symbolState;
|
||||
switch(state){
|
||||
case "off":
|
||||
symbolState = "⬛";
|
||||
break;
|
||||
case "idle":
|
||||
symbolState = "⏸️";
|
||||
break;
|
||||
case "operational":
|
||||
symbolState = "⏵️";
|
||||
break;
|
||||
case "starting":
|
||||
symbolState = "⏯️";
|
||||
break;
|
||||
case "warmingup":
|
||||
symbolState = "🔄";
|
||||
break;
|
||||
case "accelerating":
|
||||
symbolState = "⏩";
|
||||
break;
|
||||
case "stopping":
|
||||
symbolState = "⏹️";
|
||||
break;
|
||||
case "coolingdown":
|
||||
symbolState = "❄️";
|
||||
break;
|
||||
case "decelerating":
|
||||
symbolState = "⏪";
|
||||
break;
|
||||
}
|
||||
const position = m.state.getCurrentPosition();
|
||||
const roundedPosition = Math.round(position * 100) / 100;
|
||||
|
||||
let status;
|
||||
switch (state) {
|
||||
case "off":
|
||||
status = { fill: "red", shape: "dot", text: `${mode}: OFF` };
|
||||
break;
|
||||
case "idle":
|
||||
status = { fill: "blue", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "operational":
|
||||
status = { fill: "green", shape: "dot", text: `${mode}: ${symbolState} | ${roundedPosition}% | 💨${flow}m³/h | ⚡${power}kW` };
|
||||
break;
|
||||
case "starting":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "warmingup":
|
||||
status = { fill: "green", shape: "dot", text: `${mode}: ${symbolState} | ${roundedPosition}% | 💨${flow}m³/h | ⚡${power}kW` };
|
||||
break;
|
||||
case "accelerating":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState} | ${roundedPosition}%| 💨${flow}m³/h | ⚡${power}kW` };
|
||||
break;
|
||||
case "stopping":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "coolingdown":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
break;
|
||||
case "decelerating":
|
||||
status = { fill: "yellow", shape: "dot", text: `${mode}: ${symbolState} - ${roundedPosition}% | 💨${flow}m³/h | ⚡${power}kW` };
|
||||
break;
|
||||
default:
|
||||
status = { fill: "grey", shape: "dot", text: `${mode}: ${symbolState}` };
|
||||
}
|
||||
return status;
|
||||
} catch (error) {
|
||||
node.error("Error in updateNodeStatus: " + error.message);
|
||||
return { fill: "red", shape: "ring", text: "Status Error" };
|
||||
}
|
||||
}
|
||||
|
||||
function tick() {
|
||||
try {
|
||||
const status = updateNodeStatus();
|
||||
node.status(status);
|
||||
|
||||
//get output
|
||||
const classOutput = m.getOutput();
|
||||
const dbOutput = output.formatMsg(classOutput, m.config, "influxdb");
|
||||
const pOutput = output.formatMsg(classOutput, m.config, "process");
|
||||
|
||||
//console.log(pOutput);
|
||||
|
||||
//only send output on values that changed
|
||||
let msgs = [];
|
||||
msgs[0] = pOutput;
|
||||
msgs[1] = dbOutput;
|
||||
|
||||
node.send(msgs);
|
||||
|
||||
} catch (error) {
|
||||
node.error("Error in tick function: " + error);
|
||||
node.status({ fill: "red", shape: "ring", text: "Tick Error" });
|
||||
}
|
||||
}
|
||||
|
||||
// register child on first output this timeout is needed because of node - red stuff
|
||||
setTimeout(
|
||||
() => {
|
||||
|
||||
/*---execute code on first start----*/
|
||||
let msgs = [];
|
||||
|
||||
msgs[2] = { topic : "registerChild" , payload: node.id, positionVsParent: "upstream" };
|
||||
msgs[3] = { topic : "registerChild" , payload: node.id, positionVsParent: "downstream" };
|
||||
|
||||
//send msg
|
||||
this.send(msgs);
|
||||
},
|
||||
100
|
||||
);
|
||||
|
||||
//declare refresh interval internal node
|
||||
|
||||
setTimeout(
|
||||
() => {
|
||||
//---execute code on first start----
|
||||
this.interval_id = setInterval(function(){ tick() },1000)
|
||||
},
|
||||
1000
|
||||
);
|
||||
|
||||
node.on("input", function(msg, send, done) {
|
||||
try {
|
||||
|
||||
/* Update to complete event based node by putting the tick function after an input event */
|
||||
|
||||
|
||||
switch(msg.topic) {
|
||||
case 'registerChild':
|
||||
const childId = msg.payload;
|
||||
const childObj = RED.nodes.getNode(childId);
|
||||
m.childRegistrationUtils.registerChild(childObj.source ,msg.positionVsParent);
|
||||
break;
|
||||
case 'setMode':
|
||||
m.setMode(msg.payload);
|
||||
break;
|
||||
case 'execSequence':
|
||||
const { source, action, parameter } = msg.payload;
|
||||
m.handleInput(source, action, parameter);
|
||||
break;
|
||||
case 'execMovement':
|
||||
const { source: mvSource, action: mvAction, setpoint } = msg.payload;
|
||||
m.handleInput(mvSource, mvAction, Number(setpoint));
|
||||
break;
|
||||
case 'flowMovement':
|
||||
const { source: fmSource, action: fmAction, setpoint: fmSetpoint } = msg.payload;
|
||||
m.handleInput(fmSource, fmAction, Number(fmSetpoint));
|
||||
|
||||
break;
|
||||
case 'emergencystop':
|
||||
const { source: esSource, action: esAction } = msg.payload;
|
||||
m.handleInput(esSource, esAction);
|
||||
break;
|
||||
case 'showCompleteCurve':
|
||||
m.showCompleteCurve();
|
||||
send({ topic : "Showing curve" , payload: m.showCompleteCurve() });
|
||||
break;
|
||||
case 'CoG':
|
||||
m.showCoG();
|
||||
send({ topic : "Showing CoG" , payload: m.showCoG() });
|
||||
break;
|
||||
}
|
||||
|
||||
if (done) done();
|
||||
} catch (error) {
|
||||
node.error("Error processing input: " + error.message);
|
||||
if (done) done(error);
|
||||
}
|
||||
});
|
||||
|
||||
node.on('close', function(done) {
|
||||
if (node.interval_id) clearTimeout(node.interval_id);
|
||||
if (node.tick_interval) clearInterval(node.tick_interval);
|
||||
if (done) done();
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
node.error("Fatal error in node initialization: " + error.stack);
|
||||
node.status({fill: "red", shape: "ring", text: "Fatal Error"});
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType("rotatingMachine", rotatingMachine);
|
||||
};
|
||||
Reference in New Issue
Block a user