@sailingrotevista/rotevista-dash 5.0.7 → 5.0.8
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 +47 -39
- package/index.js +32 -8
- package/package.json +1 -1
package/app.js
CHANGED
|
@@ -927,8 +927,8 @@ function manageHistory(type, value) {
|
|
|
927
927
|
}
|
|
928
928
|
|
|
929
929
|
/**
|
|
930
|
-
* Gestione dinamica delle scale dei grafici (Involucro Elastico e Safety Zoom)
|
|
931
|
-
* Implementa
|
|
930
|
+
* Gestione dinamica delle scale dei grafici (Involucro Elastico Snapped e Safety Zoom)
|
|
931
|
+
* Implementa lo "Snap a Griglia" basato sull'hercSpan senza padding per tutti i sensori.
|
|
932
932
|
*/
|
|
933
933
|
function calculateScale(type, data, mode) {
|
|
934
934
|
const s = CONFIG.scales[type];
|
|
@@ -947,14 +947,14 @@ function calculateScale(type, data, mode) {
|
|
|
947
947
|
let currentScale = store.herculesScales[type];
|
|
948
948
|
|
|
949
949
|
// ==========================================================================
|
|
950
|
-
// SEZIONE PROFONDITÀ (
|
|
950
|
+
// 1. SEZIONE PROFONDITÀ (DEDICATA A 2 MINUTI DI SICUREZZA, MINIMO FISSO A 0)
|
|
951
951
|
// ==========================================================================
|
|
952
952
|
if (type === 'depth') {
|
|
953
953
|
const shallowThreshold = Math.max(s.stdMax, 10); // Es. 20m
|
|
954
954
|
if (store.depthProtectedActive === undefined) store.depthProtectedActive = false;
|
|
955
955
|
|
|
956
956
|
const now = Date.now();
|
|
957
|
-
const depthSafetyWindowMs = 120000; // 2 minuti
|
|
957
|
+
const depthSafetyWindowMs = 120000; // 2 minuti fissi per la sicurezza
|
|
958
958
|
|
|
959
959
|
// Estrazione dati reali degli ultimi 2 minuti con timestamp
|
|
960
960
|
const recentPoints = store.histories.depth.filter(p => (now - p.time) <= depthSafetyWindowMs);
|
|
@@ -963,49 +963,40 @@ function calculateScale(type, data, mode) {
|
|
|
963
963
|
const localMax = recentVals.length > 0 ? Math.max(...recentVals) : currentVal;
|
|
964
964
|
const localMin = recentVals.length > 0 ? Math.min(...recentVals) : currentVal;
|
|
965
965
|
|
|
966
|
-
// --- NORMALE PROFONDITÀ (CON SOGLIA STANDARD E FILTRO 2 MINUTI) ---
|
|
966
|
+
// --- 1.1 NORMALE PROFONDITÀ (CON SOGLIA STANDARD E FILTRO 2 MINUTI) ---
|
|
967
967
|
if (mode !== 'hercules') {
|
|
968
|
-
// Entrata istantanea sotto lo Standard Max (sicurezza immediata)
|
|
969
968
|
if (!store.depthProtectedActive && currentVal <= shallowThreshold) {
|
|
970
969
|
store.depthProtectedActive = true;
|
|
971
970
|
}
|
|
972
|
-
|
|
973
|
-
// Uscita ritardata: usciamo solo se il minimo degli ultimi 2 minuti è sopra soglia
|
|
974
971
|
if (store.depthProtectedActive) {
|
|
975
972
|
if (localMin > shallowThreshold) {
|
|
976
973
|
store.depthProtectedActive = false;
|
|
977
974
|
}
|
|
978
975
|
}
|
|
979
|
-
|
|
980
976
|
if (store.depthProtectedActive) {
|
|
981
|
-
return { min: 0, max: shallowThreshold };
|
|
977
|
+
return { min: 0, max: shallowThreshold };
|
|
982
978
|
}
|
|
983
|
-
|
|
984
|
-
// Se siamo fuori, scala dinamica normale basata sull'intero buffer passato
|
|
985
979
|
const maxHistorico = Math.max(...data);
|
|
986
980
|
return { min: 0, max: Math.max(s.stdMax, Math.ceil(maxHistorico / s.step) * s.step) };
|
|
987
981
|
}
|
|
988
982
|
|
|
989
|
-
// --- HERCULES PROFONDITÀ (0 IN BASSO,
|
|
983
|
+
// --- 1.2 HERCULES PROFONDITÀ (0 IN BASSO, SNAP SUL MAX SENZA PADDING) ---
|
|
990
984
|
if (mode === 'hercules') {
|
|
991
|
-
const
|
|
985
|
+
const roundStep = s.hercSpan; // Passo di griglia selezionato dall'utente
|
|
992
986
|
|
|
993
|
-
// Calcoliamo i limiti ideali basati solo sugli ultimi 2 minuti
|
|
994
987
|
let targetMin = 0;
|
|
995
|
-
let targetMax = Math.ceil(localMax
|
|
988
|
+
let targetMax = Math.ceil(localMax / roundStep) * roundStep;
|
|
996
989
|
|
|
997
|
-
// Impediamo una scala
|
|
990
|
+
// Impediamo una scala inferiore a 4 metri per sicurezza visiva
|
|
998
991
|
const absoluteMinSpan = 4;
|
|
999
992
|
if (targetMax < absoluteMinSpan) {
|
|
1000
993
|
targetMax = absoluteMinSpan;
|
|
1001
994
|
}
|
|
1002
995
|
|
|
1003
|
-
// Regola asimmetrica
|
|
996
|
+
// Regola asimmetrica per il MAX (Espansione istantanea, contrazione a 2 minuti)
|
|
1004
997
|
if (currentVal > currentScale.max) {
|
|
1005
|
-
// Se andiamo verso il fondo profondo, allarghiamo istantaneamente
|
|
1006
998
|
currentScale.max = targetMax;
|
|
1007
999
|
} else {
|
|
1008
|
-
// Stringiamo lo zoom solo se tutti i dati degli ultimi 2 minuti sono inferiori al target
|
|
1009
1000
|
const allStableInTarget = recentVals.every(val => val <= targetMax);
|
|
1010
1001
|
if (allStableInTarget) {
|
|
1011
1002
|
currentScale.max = targetMax;
|
|
@@ -1018,34 +1009,51 @@ function calculateScale(type, data, mode) {
|
|
|
1018
1009
|
}
|
|
1019
1010
|
|
|
1020
1011
|
// ==========================================================================
|
|
1021
|
-
// ALTRI GRAFICI (STW, SOG, TWS):
|
|
1012
|
+
// 2. ALTRI GRAFICI (STW, SOG, TWS): COMPORTAMENTO ADATTIVO SU TERZO DEL GRAFICO
|
|
1022
1013
|
// ==========================================================================
|
|
1023
|
-
|
|
1014
|
+
|
|
1015
|
+
// --- 2.1 MODALITÀ NORMALE ---
|
|
1016
|
+
if (mode !== 'hercules') {
|
|
1017
|
+
const maxHistorico = Math.max(...data);
|
|
1018
|
+
return { min: 0, max: Math.max(s.stdMax, Math.ceil(maxHistorico / s.step) * s.step) };
|
|
1019
|
+
}
|
|
1024
1020
|
|
|
1021
|
+
// --- 2.2 MODALITÀ HERCULES AD ALTO CONTRASTO (SNAP SENZA PADDING) ---
|
|
1025
1022
|
if (mode === 'hercules') {
|
|
1026
|
-
const
|
|
1023
|
+
const roundStep = s.hercSpan; // Passo di griglia (ex hercSpan)
|
|
1024
|
+
|
|
1025
|
+
const oneThirdCount = Math.max(1, Math.floor(data.length / 3));
|
|
1026
|
+
const recentThirdData = data.slice(-oneThirdCount);
|
|
1027
|
+
|
|
1028
|
+
const localMin = Math.min(...recentThirdData);
|
|
1029
|
+
const localMax = Math.max(...recentThirdData);
|
|
1027
1030
|
|
|
1028
|
-
|
|
1029
|
-
let
|
|
1031
|
+
// Applichiamo lo snap diretto ai multipli della griglia
|
|
1032
|
+
let targetMin = Math.max(0, Math.floor(localMin / roundStep) * roundStep);
|
|
1033
|
+
let targetMax = Math.ceil(localMax / roundStep) * roundStep;
|
|
1030
1034
|
|
|
1031
|
-
//
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
const diff = s.hercSpan - currentSpan;
|
|
1035
|
-
min = Math.max(0, min - Math.floor(diff / 2));
|
|
1036
|
-
max = min + s.hercSpan;
|
|
1035
|
+
// Se lo span calcolato è nullo (es. velocità costante), forziamo lo span minimo
|
|
1036
|
+
if (targetMax - targetMin === 0) {
|
|
1037
|
+
targetMax = targetMin + roundStep;
|
|
1037
1038
|
}
|
|
1038
1039
|
|
|
1039
|
-
//
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1040
|
+
// APPLICAZIONE REGOLE ASIMMETRICHE ANTI-CLIPPING
|
|
1041
|
+
// A. Espansione ISTANTANEA in alto o in basso (sicurezza)
|
|
1042
|
+
if (currentVal < currentScale.min || currentVal > currentScale.max) {
|
|
1043
|
+
currentScale.min = Math.min(currentScale.min, targetMin);
|
|
1044
|
+
currentScale.max = Math.max(currentScale.max, targetMax);
|
|
1045
|
+
}
|
|
1046
|
+
// B. Contrazione RITARDATA (solo se tutto il terzo recente si è assestato nel target)
|
|
1047
|
+
else {
|
|
1048
|
+
const allStableInTarget = recentThirdData.every(val => val >= targetMin && val <= targetMax);
|
|
1049
|
+
if (allStableInTarget) {
|
|
1050
|
+
currentScale.min = targetMin;
|
|
1051
|
+
currentScale.max = targetMax;
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1043
1054
|
|
|
1044
|
-
return { min, max };
|
|
1055
|
+
return { min: currentScale.min, max: currentScale.max };
|
|
1045
1056
|
}
|
|
1046
|
-
|
|
1047
|
-
// Scala Standard (Autocompressione a scatti)
|
|
1048
|
-
return { min: 0, max: Math.max(s.stdMax, Math.ceil(aMax / s.step) * s.step) };
|
|
1049
1057
|
}
|
|
1050
1058
|
|
|
1051
1059
|
function updateScaleLabels(t, min, max) {
|
package/index.js
CHANGED
|
@@ -127,10 +127,10 @@ module.exports = function (app) {
|
|
|
127
127
|
default: 0.5
|
|
128
128
|
},
|
|
129
129
|
stabilityThreshold: {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
type: 'number',
|
|
131
|
+
title: 'Steering Precision (Sensitivity)',
|
|
132
|
+
description: "How strictly the system judges data coherence (0.0 to 1.0). Due to internal smoothing, 0.97-0.98 requires racing precision; 0.93-0.95 is ideal for cruising in waves. Below this, the display rarely alerts for instability.",
|
|
133
|
+
default: 0.95
|
|
134
134
|
},
|
|
135
135
|
stabilityBreakout: {
|
|
136
136
|
type: 'number',
|
|
@@ -152,7 +152,13 @@ module.exports = function (app) {
|
|
|
152
152
|
properties: {
|
|
153
153
|
stdMax: { type: 'number', title: 'Standard Max', description: "Default top limit of the graph.", default: 12 },
|
|
154
154
|
step: { type: 'number', title: 'Scale Jump', description: "Amount the scale increases when you exceed the limit.", default: 2 },
|
|
155
|
-
hercSpan: {
|
|
155
|
+
hercSpan: {
|
|
156
|
+
type: 'number',
|
|
157
|
+
title: 'Hercules Grid Step (Resolution)',
|
|
158
|
+
description: "Select the multiplier step for the Hercules zoom. The scale boundaries will always snap to multiples of this value.",
|
|
159
|
+
enum: [0.5, 1.0, 2.0, 3.0],
|
|
160
|
+
default: 1.0
|
|
161
|
+
}
|
|
156
162
|
}
|
|
157
163
|
},
|
|
158
164
|
sog: {
|
|
@@ -161,7 +167,13 @@ module.exports = function (app) {
|
|
|
161
167
|
properties: {
|
|
162
168
|
stdMax: { type: 'number', title: 'Standard Max', default: 12 },
|
|
163
169
|
step: { type: 'number', title: 'Scale Jump', default: 2 },
|
|
164
|
-
hercSpan: {
|
|
170
|
+
hercSpan: {
|
|
171
|
+
type: 'number',
|
|
172
|
+
title: 'Hercules Grid Step (Resolution)',
|
|
173
|
+
description: "Select the multiplier step for the Hercules zoom. The scale boundaries will always snap to multiples of this value.",
|
|
174
|
+
enum: [0.5, 1.0, 2.0, 3.0],
|
|
175
|
+
default: 1.0
|
|
176
|
+
}
|
|
165
177
|
}
|
|
166
178
|
},
|
|
167
179
|
tws: {
|
|
@@ -170,7 +182,13 @@ module.exports = function (app) {
|
|
|
170
182
|
properties: {
|
|
171
183
|
stdMax: { type: 'number', title: 'Standard Max', default: 25 },
|
|
172
184
|
step: { type: 'number', title: 'Scale Jump', default: 5 },
|
|
173
|
-
hercSpan: {
|
|
185
|
+
hercSpan: {
|
|
186
|
+
type: 'number',
|
|
187
|
+
title: 'Hercules Grid Step (Resolution)',
|
|
188
|
+
description: "Select the multiplier step for the Hercules zoom. The scale boundaries will always snap to multiples of this value.",
|
|
189
|
+
enum: [1, 2, 3, 5, 10],
|
|
190
|
+
default: 2
|
|
191
|
+
}
|
|
174
192
|
}
|
|
175
193
|
},
|
|
176
194
|
depth: {
|
|
@@ -179,7 +197,13 @@ module.exports = function (app) {
|
|
|
179
197
|
properties: {
|
|
180
198
|
stdMax: { type: 'number', title: 'Standard Max', default: 20 },
|
|
181
199
|
step: { type: 'number', title: 'Scale Jump', default: 10 },
|
|
182
|
-
hercSpan: {
|
|
200
|
+
hercSpan: {
|
|
201
|
+
type: 'number',
|
|
202
|
+
title: 'Hercules Grid Step (Resolution)',
|
|
203
|
+
description: "Select the multiplier step for the Hercules zoom. The scale boundaries will always snap to multiples of this value.",
|
|
204
|
+
enum: [1, 2, 3, 5, 10],
|
|
205
|
+
default: 2
|
|
206
|
+
}
|
|
183
207
|
}
|
|
184
208
|
}
|
|
185
209
|
}
|