Seantral: com’è fatta dentro, e le cose che si sono rotte
· 8 min · marine, forecast, edge, testing
Previsioni meteo-marine tradotte in un verdetto onesto. La parte facile era la mappa. La parte difficile era non mentire quando i dati mancano.
È nata da una domanda banale, ricorrente prima di ogni uscita in mare: com’è oggi, davvero, in questo punto preciso? I siti meteo danno numeri. Vento 14 nodi, onda 0,8 metri. Ma tradurre quei numeri in “vale la pena o no” era un calcolo a mente, ogni volta un po’ diverso. L’idea: quel pezzo di traduzione si può scrivere una volta e tenere onesto.
Da dove arrivano i numeri
I dati sono di Open-Meteo (Weather + Marine, licenza CC-BY 4.0). La cosa che pochi fanno e che qui conta: non si prende un modello solo. Se ne fondono quattro meteo e tre di onde per ciascuna variabile, e invece di una media secca si tiene la distribuzione: media, dispersione, percentili. La dispersione tra i modelli non si butta: diventa la confidenza mostrata a schermo. Quando i modelli sono d’accordo, il verdetto è netto. Quando litigano, l’app lo dice.
Un cron orario rinfresca la cache di tutti gli spot curati, in blocco. Il client legge dalla cache, non chiama i fornitori dal browser. Sembra un dettaglio ma cambia due cose: la mappa è veloce, e i fornitori non sanno chi sta guardando cosa.
Un paio di accortezze che sembrano paranoia finché non servono. Quando la cache scade e va rinfrescata, un solo richiedente esegue il fetch e gli altri aspettano il suo risultato, invece di partire tutti insieme a martellare il fornitore (anti-stampede). E se il fetch fallisce, viene servita l’ultima cache marcata come non aggiornata, con l’avviso: mai un buco silenzioso. La mappa scarica un riassunto compatto per spot; il dettaglio si carica solo quando apri la scheda.
Il verdetto, e perché è volutamente pessimista
Il motore prende onda, vento, periodo, ridosso e fascia oraria e li combina in un punteggio 0–10 con una parola sopra (calmo, mosso, agitato). Ogni attività pesa gli stessi dati in modo diverso: chi nuota teme l’onda, chi va in barca guarda il vento, chi pesca tollera un po’ di moto. Nessuna scienza inventata: sono soglie “ideale/pessimo” per fattore, tarate a mano e in validazione sul campo, che spingono giù i punteggi mediocri invece di arrotondarli verso l’alto. Meglio dire “mosso” e trovare mare piatto, che il contrario.
La regola mai tradita: il punteggio è una lettura di comfort, nessuna valutazione di sicurezza. Per decidere se uscire fanno fede gli avvisi ufficiali, punto. La frase compare in tre punti diversi dell’app perché è quella su cui non deve esserci ambiguità.
Far sparire il dato, non il segnale
Dietro un solo numero c’è più roba di quanta ne voglia vedere chi guarda: sette modelli fusi in distribuzioni, le soglie per fattore, il vento riportato col tetto, la gestione del dato mancante. Quando tocchi uno spot, niente di tutto questo arriva a te. Ti arriva una parola (calmo, mosso, agitato), un punteggio 0–10 e la finestra migliore delle prossime ore. La parte difficile del progetto non è stata gestire il dato. È stata nasconderlo senza buttare via il segnale.
La mappa è l’app intera. Badge colorati per spot, leggibili a colpo d’occhio, senza un form da compilare né un’impostazione da scegliere. E la lente per attività: bagno, barca, pesca ripescano gli stessi dati con un tocco e cambiano la lettura, senza aggiungere un grammo di complessità sullo schermo. Sotto c’è tutto il lavoro; sopra, un interruttore.
Il resto se lo prende chi lo cerca. La mappa mostra un riassunto compatto; il breakdown dei fattori e l’andamento orario si caricano solo quando apri lo spot, così la prima vista resta leggera e veloce. E l’onestà non deve gridare: il flag ambra del dato mancante e la confidenza che viene dalla dispersione dei modelli stanno lì, discreti, per chi va a guardarli, non ti saltano addosso al primo sguardo.
Le funzioni AI vivono dentro questa stessa regola. L’assistente risponde a “dove vado a nuotare” dallo stesso motore della mappa, così chat e mappa non si contraddicono mai su uno spot. Il riscontro sul posto si lascia in tre tocchi (come previsto, meglio, peggio) e chiude l’anello verso la pagella futura. E i feedback grezzi li classifica l’AI in change request, così le segnalazioni non sommergono il lavoro. Il senso è sempre quello: tanto lavoro sotto, una cosa sola da guardare sopra.
La sera del “4,7” col mare piatto
Questo errore è costato una serata. L’app dava per uno spot un punteggio mediocre mentre fuori era una tavola. La serata è andata a cercare il bug nel motore, e il motore era giusto. Il problema stava a monte: Open-Meteo ogni tanto ha dei buchi notturni sulle ore 3–6, e il vento mancava per quella finestra. Il codice riportava avanti l’ultimo vento noto, cosa sensata, ma senza tetto, e senza dirlo.
La correzione ha reso il buco onesto invece di nasconderlo: il vento riportato ha un tetto di sei ore dall’origine del dato; oltre, degrada esplicitamente a “vento mancante”, il punteggio si limita intorno a 5 e appare un avviso ambra. Nessun fattore senza segnale viene penalizzato di nascosto: se un dato non c’è, si vede che non c’è. Il numero viaggia sempre con la sua parola, anche quando la parola è “non fidarti troppo”.
Un motore, due runtime, zero “su questo dispositivo è diverso”
Il calcolo del verdetto serve in due posti: nel browser (per rispondere subito quando tocchi uno spot) e nell’edge (quando l’assistente AI risponde a “dove vado a nuotare”). La tentazione è scrivere due volte la stessa logica. È esattamente il modo in cui poi, tre patch dopo, la mappa e l’AI ti danno due numeri diversi per lo stesso spot, e non esplode niente: divergono e basta. Un incubo da trovare.
La scelta è stata un solo modulo puro, condiviso tra client ed edge, chiuso con dei golden vector: una batteria di casi con input congelato e output atteso, eseguiti in CI su entrambi i runtime: Vitest sul lato browser, deno test sull’edge. Se una modifica fa divergere i due, la build fallisce prima che qualcuno se ne accorga a mano. È la rete che ha permesso di toccare il motore senza paura. E infatti, al riallineamento dell’AI con la lista degli spot, il bug era proprio lì: l’AI usava il nowcast congelato al fetch invece di proiettare all’ora corrente come fa la mappa. Stesso motore, ora di riferimento diversa, classifica diversa.
Il riscontro di chi è sul posto
La previsione è una previsione. La cosa che le manca è qualcuno in acqua che dice “sì, è come dice l’app” oppure “no, è peggio”. Per questo c’è un riscontro rapido: com’è rispetto al previsto: uguale, meglio, peggio. Con una condizione: per lasciarlo bisogna essere davvero lì. Il client calcola la distanza dallo spot (Haversine, soglia intorno ai 3 km) e senza posizione, o troppo lontano, il riscontro non parte. Si salva la distanza dichiarata, non le coordinate. È un soft-check, non un antifurto: serve a tenere i riscontri ancorati alla realtà, non a schedare nessuno.
Dove i riscontri divergono in modo netto dalla previsione, è un ponte verso la parte che conta di più a lungo termine: la pagella per spot. Confronto previsto contro osservato, e nel tempo le formule si tarano su dati veri invece che a occhio. Per ora i numeri sono pochi ed è tutto in validazione. Va detto chiaramente, perché la cosa peggiore sarebbe far passare un esperimento per scienza.
Dove sta andando
La direzione è due passi. Prima raccogliere segnale vero: i riscontri sul posto, le divergenze tra modelli, le webcam curate. Poi usarlo per ricalibrare le formule su dati invece che a occhio: una pagella per spot che confronta previsto contro osservato nel tempo. Sopra ci sono due esperimenti in lista: un indice di balneazione multi-fattore (acqua, aria, UV, vento) e una lettura di “mare sporco” a partire dalle fonti pubbliche sulla qualità delle acque, con un flag di torbidità quando ha appena piovuto.
Più in là, la parte più speculativa: un livello di misura sul posto, non solo previsione. Reti mareografiche esistenti, dati in-situ, e (come dimostratore, non come prodotto) una boa fatta in casa con microcontrollore, sensori di moto, GPS e pannellino solare. Il valore sta nel confronto tra quello che il modello dice e quello che il mare fa davvero, più che nell’hardware. È un’esplorazione, ed è segnata come tale.
Cosa ha insegnato
Che la parte difficile di un’app di previsioni è il comportamento quando il dato manca. Un motore che dà sempre un numero pieno è più semplice da scrivere e più facile da non fidarsi. Tutto il lavoro vero è stato costruire i modi onesti di dire “non lo so”: il tetto sul carry-forward, il fattore mancante visibile, la confidenza dalla dispersione dei modelli. E un motore solo, testato su due runtime, perché la fiducia si perde in fretta il giorno che due schermate della stessa app non concordano.