From 09ce52a1c682c9fa1d614934d081f9b2d9a785e2 Mon Sep 17 00:00:00 2001 From: Carlo Baratto Date: Wed, 2 Sep 2026 14:09:04 +0200 Subject: [PATCH] stato del mare: previsione onde Open-Meteo + scala Douglas (oggi/domani), EN/IT, context Sea --- qml/js/tides.js | 13 ++++++ qml/pages/DetailPage.qml | 79 +++++++++++++++++++++++++++++++++ translations/harbour-tide.ts | 16 +++++++ translations/harbour-tide_it.ts | 16 +++++++ 4 files changed, 124 insertions(+) diff --git a/qml/js/tides.js b/qml/js/tides.js index 93316e1..2a3b2e0 100644 --- a/qml/js/tides.js +++ b/qml/js/tides.js @@ -168,6 +168,19 @@ function fmtHM(t) { 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 function fmtDate(t, dn) { var d = new Date(t); diff --git a/qml/pages/DetailPage.qml b/qml/pages/DetailPage.qml index 3e5f500..4bcea53 100644 --- a/qml/pages/DetailPage.qml +++ b/qml/pages/DetailPage.qml @@ -91,11 +91,71 @@ Page { curveInfo.text = qsTr("Z₀ %1 m · 7 harmonic constituents").arg(port[4][0].toFixed(2)) } cv.requestPaint() + seaState() } catch (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: [ qsTr("New moon"), qsTr("Waxing crescent"), qsTr("First quarter"), qsTr("Waxing gibbous"), qsTr("Full moon"), qsTr("Waning gibbous"), qsTr("Last quarter"), qsTr("Waning crescent") @@ -109,6 +169,16 @@ Page { 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 { id: flick anchors.fill: parent @@ -297,6 +367,15 @@ Page { 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 } } } diff --git a/translations/harbour-tide.ts b/translations/harbour-tide.ts index 03ad9dc..d153ba5 100644 --- a/translations/harbour-tide.ts +++ b/translations/harbour-tide.ts @@ -84,4 +84,20 @@ Fri Sat + + Sea + Calm + Calm rippled + Smooth wavelets + Slight + Moderate + Rough + Very rough + High + Very high + Phenomenal + Sea state + Tomorrow + Unavailable (offline) + diff --git a/translations/harbour-tide_it.ts b/translations/harbour-tide_it.ts index 61e43fc..dba5551 100644 --- a/translations/harbour-tide_it.ts +++ b/translations/harbour-tide_it.ts @@ -84,4 +84,20 @@ FriVen SatSab + + Sea + CalmCalmo + Calm rippledQuasi calmo + Smooth waveletsPoco mosso + SlightMosso + ModerateMolto mosso + RoughAgitato + Very roughMolto agitato + HighGrosso + Very highMolto grosso + PhenomenalTempestoso + Sea stateStato del mare + TomorrowDomani + Unavailable (offline)Non disponibile (offline) +