stato del mare: previsione onde Open-Meteo + scala Douglas (oggi/domani), EN/IT, context Sea

This commit is contained in:
2026-09-02 14:09:04 +02:00
parent 60c777e650
commit 09ce52a1c6
4 changed files with 124 additions and 0 deletions
+13
View File
@@ -168,6 +168,19 @@ function fmtHM(t) {
return (hh < 10 ? "0" : "") + hh + ":" + (mm < 10 ? "0" : "") + mm; return (hh < 10 ? "0" : "") + hh + ":" + (mm < 10 ? "0" : "") + mm;
} }
// Scala Douglas (stato del mare) dall'altezza d'onda significativa in metri
// 0 Calmo, 1 Quasi calmo, 2 Poco mosso, 3 Mosso, 4 Molto mosso, 5 Agitato,
// 6 Molto agitato, 7 Grosso, 8 Molto grosso, 9 Tempestoso
function douglas(h) {
if (h <= 0) return 0;
var soglie = [0.1, 0.5, 1.25, 2.5, 4, 6, 9, 14];
var g = 1;
for (var i = 0; i < soglie.length; i++) {
if (h >= soglie[i]) g++;
}
return g;
}
// Formato data breve // Formato data breve
function fmtDate(t, dn) { function fmtDate(t, dn) {
var d = new Date(t); var d = new Date(t);
+79
View File
@@ -91,11 +91,71 @@ Page {
curveInfo.text = qsTr("Z₀ %1 m · 7 harmonic constituents").arg(port[4][0].toFixed(2)) curveInfo.text = qsTr("Z₀ %1 m · 7 harmonic constituents").arg(port[4][0].toFixed(2))
} }
cv.requestPaint() cv.requestPaint()
seaState()
} catch (e) { } catch (e) {
console.log("[tide] refresh error:", e) console.log("[tide] refresh error:", e)
} }
} }
function seaFail() {
seaLabel.text = qsTranslate("Sea", "Unavailable (offline)")
seaLabel.color = Theme.secondaryColor
seaSub.text = ""
}
function seaState() {
if (!port) return
console.log("[tide] seaState fetch:", port[0])
var xhr = new XMLHttpRequest()
var done = false
var to = setTimeout(function() {
if (!done) {
done = true
console.log("[tide] seaState timeout")
seaFail()
}
}, 12000)
xhr.open("GET",
"https://marine-api.open-meteo.com/v1/marine?latitude=" + port[2]
+ "&longitude=" + port[3]
+ "&daily=wave_height_max&timezone=auto&forecast_days=3",
true)
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
if (done) return
done = true
clearTimeout(to)
console.log("[tide] seaState status:", xhr.status)
if (xhr.status === 200) {
try {
var j = JSON.parse(xhr.responseText)
var wh = j.daily.wave_height_max
if (wh && wh.length > 0) {
var today = wh[0]
var i0 = Tides.douglas(today)
seaLabel.text = seaNames[i0] + " · " + Tides.fmtH(today, page.unit)
seaLabel.color = i0 >= 5 ? Theme.errorColor
: (i0 >= 4 ? Theme.secondaryColor : Theme.highlightColor)
if (wh.length > 1) {
var i1 = Tides.douglas(wh[1])
seaSub.text = qsTranslate("Sea", "Tomorrow") + ": " + seaNames[i1]
+ " · " + Tides.fmtH(wh[1], page.unit)
seaSub.color = Theme.secondaryColor
} else {
seaSub.text = ""
}
return
}
} catch (e) {
console.log("[tide] seaState parse err:", e)
}
}
seaFail()
}
}
xhr.send()
}
property var moonNames: [ property var moonNames: [
qsTr("New moon"), qsTr("Waxing crescent"), qsTr("First quarter"), qsTr("Waxing gibbous"), qsTr("New moon"), qsTr("Waxing crescent"), qsTr("First quarter"), qsTr("Waxing gibbous"),
qsTr("Full moon"), qsTr("Waning gibbous"), qsTr("Last quarter"), qsTr("Waning crescent") qsTr("Full moon"), qsTr("Waning gibbous"), qsTr("Last quarter"), qsTr("Waning crescent")
@@ -109,6 +169,16 @@ Page {
qsTranslate("Tide", "Sat") qsTranslate("Tide", "Sat")
] ]
// stato del mare: scala Douglas (0-9) — context "Sea" separato:
// "High" qui = "Grosso", non "Alta" degli eventi
property var seaNames: [
qsTranslate("Sea", "Calm"), qsTranslate("Sea", "Calm rippled"),
qsTranslate("Sea", "Smooth wavelets"), qsTranslate("Sea", "Slight"),
qsTranslate("Sea", "Moderate"), qsTranslate("Sea", "Rough"),
qsTranslate("Sea", "Very rough"), qsTranslate("Sea", "High"),
qsTranslate("Sea", "Very high"), qsTranslate("Sea", "Phenomenal")
]
SilicaFlickable { SilicaFlickable {
id: flick id: flick
anchors.fill: parent anchors.fill: parent
@@ -297,6 +367,15 @@ Page {
Label { id: rangeLabel; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter } Label { id: rangeLabel; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter }
} }
// Stato del mare (scala Douglas, previsione onde Open-Meteo)
Item { width: parent.width; height: Theme.itemSizeSmall
Label { text: "🌊 " + qsTranslate("Sea", "Sea state"); color: Theme.secondaryColor; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter }
Label { id: seaLabel; text: "…"; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin + 130; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter; horizontalAlignment: Text.AlignRight; truncationMode: TruncationMode.Fade }
}
Item { width: parent.width; height: Theme.itemSizeSmall
Label { id: seaSub; anchors.left: parent.left; anchors.leftMargin: Theme.horizontalPageMargin + 130; anchors.right: parent.right; anchors.rightMargin: Theme.horizontalPageMargin; anchors.verticalCenter: parent.verticalCenter; horizontalAlignment: Text.AlignRight; font.pixelSize: Theme.fontSizeSmall; truncationMode: TruncationMode.Fade }
}
Item { width: parent.width; height: Theme.paddingLarge } Item { width: parent.width; height: Theme.paddingLarge }
} }
} }
+16
View File
@@ -84,4 +84,20 @@
<message><source>Fri</source><translation type="unfinished"></translation></message> <message><source>Fri</source><translation type="unfinished"></translation></message>
<message><source>Sat</source><translation type="unfinished"></translation></message> <message><source>Sat</source><translation type="unfinished"></translation></message>
</context> </context>
<context>
<name>Sea</name>
<message><source>Calm</source><translation type="unfinished"></translation></message>
<message><source>Calm rippled</source><translation type="unfinished"></translation></message>
<message><source>Smooth wavelets</source><translation type="unfinished"></translation></message>
<message><source>Slight</source><translation type="unfinished"></translation></message>
<message><source>Moderate</source><translation type="unfinished"></translation></message>
<message><source>Rough</source><translation type="unfinished"></translation></message>
<message><source>Very rough</source><translation type="unfinished"></translation></message>
<message><source>High</source><translation type="unfinished"></translation></message>
<message><source>Very high</source><translation type="unfinished"></translation></message>
<message><source>Phenomenal</source><translation type="unfinished"></translation></message>
<message><source>Sea state</source><translation type="unfinished"></translation></message>
<message><source>Tomorrow</source><translation type="unfinished"></translation></message>
<message><source>Unavailable (offline)</source><translation type="unfinished"></translation></message>
</context>
</TS> </TS>
+16
View File
@@ -84,4 +84,20 @@
<message><source>Fri</source><translation>Ven</translation></message> <message><source>Fri</source><translation>Ven</translation></message>
<message><source>Sat</source><translation>Sab</translation></message> <message><source>Sat</source><translation>Sab</translation></message>
</context> </context>
<context>
<name>Sea</name>
<message><source>Calm</source><translation>Calmo</translation></message>
<message><source>Calm rippled</source><translation>Quasi calmo</translation></message>
<message><source>Smooth wavelets</source><translation>Poco mosso</translation></message>
<message><source>Slight</source><translation>Mosso</translation></message>
<message><source>Moderate</source><translation>Molto mosso</translation></message>
<message><source>Rough</source><translation>Agitato</translation></message>
<message><source>Very rough</source><translation>Molto agitato</translation></message>
<message><source>High</source><translation>Grosso</translation></message>
<message><source>Very high</source><translation>Molto grosso</translation></message>
<message><source>Phenomenal</source><translation>Tempestoso</translation></message>
<message><source>Sea state</source><translation>Stato del mare</translation></message>
<message><source>Tomorrow</source><translation>Domani</translation></message>
<message><source>Unavailable (offline)</source><translation>Non disponibile (offline)</translation></message>
</context>
</TS> </TS>