@sailingrotevista/rotevista-dash 5.0.6 → 5.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app.js +93 -12
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -33,7 +33,7 @@ let CONFIG = {
|
|
|
33
33
|
};
|
|
34
34
|
|
|
35
35
|
const RENDER_INTERVAL_MS = 1000;
|
|
36
|
-
const TIMEOUT_MS =
|
|
36
|
+
const TIMEOUT_MS = 15000;
|
|
37
37
|
const SIM_SAMPLE_INTERVAL = 1000;
|
|
38
38
|
const DASH_VERSION = "3.8"; // Major Update: Smart Source Locking & Breathing Hercules Scale
|
|
39
39
|
|
|
@@ -75,6 +75,8 @@ const sourceLocks = {};
|
|
|
75
75
|
const store = {
|
|
76
76
|
raw: {},
|
|
77
77
|
timestamps: {},
|
|
78
|
+
depthProtectedActive: false, // Memoria per lo stato della protezione profondità
|
|
79
|
+
herculesScales: {}, // Memoria per i limiti attivi della modalità Hercules
|
|
78
80
|
smoothBuf: { hdg: [], cog: [], awa: [], twa: [], twd: [] },
|
|
79
81
|
longBuf: { hdg: [], cog: [], awa: [], twa: [], twd: [] },
|
|
80
82
|
histories: { stw: [], sog: [], depth: [], tws: [], vmg: [], aws: [] },
|
|
@@ -926,28 +928,107 @@ function manageHistory(type, value) {
|
|
|
926
928
|
|
|
927
929
|
/**
|
|
928
930
|
* Gestione dinamica delle scale dei grafici (Involucro Elastico e Safety Zoom)
|
|
931
|
+
* Implementa la logica di sicurezza disaccoppiata a 2 minuti per la profondità.
|
|
929
932
|
*/
|
|
930
933
|
function calculateScale(type, data, mode) {
|
|
931
934
|
const s = CONFIG.scales[type];
|
|
932
|
-
|
|
935
|
+
const currentVal = data[data.length - 1];
|
|
933
936
|
|
|
934
|
-
//
|
|
935
|
-
if (
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
937
|
+
// Fallback di emergenza se il buffer è momentaneamente vuoto
|
|
938
|
+
if (currentVal === undefined || currentVal === null) {
|
|
939
|
+
return { min: 0, max: s ? s.stdMax : 10 };
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
// Inizializzazione della memoria delle scale nello store se non esiste
|
|
943
|
+
if (!store.herculesScales) store.herculesScales = {};
|
|
944
|
+
if (!store.herculesScales[type]) {
|
|
945
|
+
store.herculesScales[type] = { min: 0, max: s ? s.stdMax : 10 };
|
|
946
|
+
}
|
|
947
|
+
let currentScale = store.herculesScales[type];
|
|
948
|
+
|
|
949
|
+
// ==========================================================================
|
|
950
|
+
// SEZIONE PROFONDITÀ (REGOLA DI SICUREZZA DISACCOPPIATA A 2 MINUTI)
|
|
951
|
+
// ==========================================================================
|
|
952
|
+
if (type === 'depth') {
|
|
953
|
+
const shallowThreshold = Math.max(s.stdMax, 10); // Es. 20m
|
|
954
|
+
if (store.depthProtectedActive === undefined) store.depthProtectedActive = false;
|
|
955
|
+
|
|
956
|
+
const now = Date.now();
|
|
957
|
+
const depthSafetyWindowMs = 120000; // 2 minuti di stabilizzazione fissi per la sicurezza
|
|
958
|
+
|
|
959
|
+
// Estrazione dati reali degli ultimi 2 minuti con timestamp
|
|
960
|
+
const recentPoints = store.histories.depth.filter(p => (now - p.time) <= depthSafetyWindowMs);
|
|
961
|
+
const recentVals = recentPoints.map(p => p.val);
|
|
962
|
+
|
|
963
|
+
const localMax = recentVals.length > 0 ? Math.max(...recentVals) : currentVal;
|
|
964
|
+
const localMin = recentVals.length > 0 ? Math.min(...recentVals) : currentVal;
|
|
965
|
+
|
|
966
|
+
// --- NORMALE PROFONDITÀ (CON SOGLIA STANDARD E FILTRO 2 MINUTI) ---
|
|
967
|
+
if (mode !== 'hercules') {
|
|
968
|
+
// Entrata istantanea sotto lo Standard Max (sicurezza immediata)
|
|
969
|
+
if (!store.depthProtectedActive && currentVal <= shallowThreshold) {
|
|
970
|
+
store.depthProtectedActive = true;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
// Uscita ritardata: usciamo solo se il minimo degli ultimi 2 minuti è sopra soglia
|
|
974
|
+
if (store.depthProtectedActive) {
|
|
975
|
+
if (localMin > shallowThreshold) {
|
|
976
|
+
store.depthProtectedActive = false;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
if (store.depthProtectedActive) {
|
|
981
|
+
return { min: 0, max: shallowThreshold }; // Blocco a [0 - 20m]
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// Se siamo fuori, scala dinamica normale basata sull'intero buffer passato
|
|
985
|
+
const maxHistorico = Math.max(...data);
|
|
986
|
+
return { min: 0, max: Math.max(s.stdMax, Math.ceil(maxHistorico / s.step) * s.step) };
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
// --- HERCULES PROFONDITÀ (0 IN BASSO, ZOOM SUL MASSIMO DEI 2 MINUTI) ---
|
|
990
|
+
if (mode === 'hercules') {
|
|
991
|
+
const padding = 1.0; // 1 metro di margine sopra il fondo
|
|
992
|
+
|
|
993
|
+
// Calcoliamo i limiti ideali basati solo sugli ultimi 2 minuti
|
|
994
|
+
let targetMin = 0;
|
|
995
|
+
let targetMax = Math.ceil(localMax + padding);
|
|
996
|
+
|
|
997
|
+
// Impediamo una scala troppo stretta (minimo 4 metri di range totale per sicurezza)
|
|
998
|
+
const absoluteMinSpan = 4;
|
|
999
|
+
if (targetMax < absoluteMinSpan) {
|
|
1000
|
+
targetMax = absoluteMinSpan;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// Regola asimmetrica di aggiornamento
|
|
1004
|
+
if (currentVal > currentScale.max) {
|
|
1005
|
+
// Se andiamo verso il fondo profondo, allarghiamo istantaneamente
|
|
1006
|
+
currentScale.max = targetMax;
|
|
1007
|
+
} else {
|
|
1008
|
+
// Stringiamo lo zoom solo se tutti i dati degli ultimi 2 minuti sono inferiori al target
|
|
1009
|
+
const allStableInTarget = recentVals.every(val => val <= targetMax);
|
|
1010
|
+
if (allStableInTarget) {
|
|
1011
|
+
currentScale.max = targetMax;
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
currentScale.min = 0;
|
|
1016
|
+
return { min: currentScale.min, max: currentScale.max };
|
|
940
1017
|
}
|
|
941
1018
|
}
|
|
942
|
-
|
|
943
|
-
//
|
|
1019
|
+
|
|
1020
|
+
// ==========================================================================
|
|
1021
|
+
// ALTRI GRAFICI (STW, SOG, TWS): MANTENGONO IL COMPORTAMENTO ORIGINALE
|
|
1022
|
+
// ==========================================================================
|
|
1023
|
+
let aMin = Math.min(...data), aMax = Math.max(...data);
|
|
1024
|
+
|
|
944
1025
|
if (mode === 'hercules') {
|
|
945
1026
|
const padding = (type === 'stw' || type === 'sog') ? 0.5 : 1.0;
|
|
946
1027
|
|
|
947
1028
|
let min = Math.max(0, Math.floor(aMin - padding));
|
|
948
1029
|
let max = Math.ceil(aMax + padding);
|
|
949
1030
|
|
|
950
|
-
// Garantisce
|
|
1031
|
+
// Garantisce lo span minimo
|
|
951
1032
|
const currentSpan = max - min;
|
|
952
1033
|
if (currentSpan < s.hercSpan) {
|
|
953
1034
|
const diff = s.hercSpan - currentSpan;
|
|
@@ -955,7 +1036,7 @@ function calculateScale(type, data, mode) {
|
|
|
955
1036
|
max = min + s.hercSpan;
|
|
956
1037
|
}
|
|
957
1038
|
|
|
958
|
-
// Arrotonda la griglia numerica a step prefissati
|
|
1039
|
+
// Arrotonda la griglia numerica a step prefissati
|
|
959
1040
|
const roundStep = (type === 'stw' || type === 'sog') ? 0.5 : 1.0;
|
|
960
1041
|
min = Math.floor(min / roundStep) * roundStep;
|
|
961
1042
|
max = Math.ceil(max / roundStep) * roundStep;
|