Skip to content

La previsione sta nella lista dei comuni, con il suo timer; colonna più larga - #147

Merged
gzileni merged 3 commits into
mainfrom
sidebar-previsione
Sep 30, 2026
Merged

gzileni merged 3 commits into
mainfrom
sidebar-previsione

Conversation

@gzileni

@gzileni gzileni commented Sep 30, 2026

Copy link
Copy Markdown
Contributor

La previsione nel grafico dei comuni

È il cuore dell'applicazione e viveva solo in un pannello a parte, per regione e in forma di elenco: «nessuna regione prevista sopra soglia» è una risposta, ma non dice se il tuo comune sta salendo.

Ora la stessa linea attraversa l'adesso e prosegue tratteggiata fino a +72 ore:

  • una riga verticale «ora» separa il fatto dal calcolo — senza, una linea che sale a destra si legge come qualcosa che è già successo;
  • la previsione parte dall'ultima misura, non da mezz'aria: un tratteggio che comincia sospeso sembra un'altra serie;
  • i punti previsti sono vuoti invece che pieni;
  • la legenda dice dove si va oltre a dove si è (frane 0,32 → 0,58): un 0,58 previsto non significa niente finché non si sa che adesso è 0,32;
  • e sotto c'è scritto che è un calcolo, non un fatto.

Il backend restituisce {observed, forecast} e compone lui il momento a cui la previsione si riferisce — +48h sommato all'ora della corsa — perché è l'unico posto che conosce entrambi. Si tiene l'ultima corsa per orizzonte, non tutte: il previsionale gira ogni sei ore e le corse precedenti darebbero tre linee sovrapposte per lo stesso futuro. 52 ms misurati.

Oggi solo le frane hanno righe previsionali, quindi il tratteggio compare solo lì; gli altri due disegnano il passato e basta, che è corretto.

La colonna si allarga

Da 320-360 px a 380-440 px. C'era un secondo grid-template-columns più in basso che sovrascriveva il primo, quindi va fatto in due posti o non si vede. Il massimo resta legato alla mappa: oltre i 440 px si comincia a togliere territorio per fare spazio a una lista.

Il quadro nazionale si ordina, e smette di contraddirsi

La testata diceva «Incendio: 5024 aree in classe Alta» e le quattro caselle subito sotto dicevano «0 High+». Non era un errore: le caselle sono di un pericolo, perché le celle non si sommano fra pericoli — sono le stesse celle. Ma il nome del pericolo stava in una riga staccata, facile da non leggere. Ora sta sopra le caselle, attaccato ai numeri, perché è la loro unità di misura.

Il resto — dettaglio per pericolo, cascate, report ML — va dietro un pannello a scomparsa: sono numeri che si consultano, non che si sorvegliano, e tenerli aperti spingeva i comuni sotto la piega.


Apre #146: la riga delle cascate conta 309.097 celle su 312.550 come «aree bruciate con rischio allagamento più alto», cioè il 99 % d'Italia. months_since_fire è uno scalare per AOI copiato su ogni cella, e il moltiplicatore che ne deriva sposta davvero le classi dell'alluvione.

126 test frontend, mypy --strict pulito.

🤖 Generated with Claude Code

… ordina

## La previsione nel grafico dei comuni

È il cuore dell'applicazione e viveva solo in un pannello a parte, per
regione e in forma di elenco: «nessuna regione prevista sopra soglia» è una
risposta, ma non dice se il *tuo* comune sta salendo.

Ora la stessa linea attraversa l'adesso e prosegue tratteggiata fino a
+72 ore. Il confine è una riga verticale «ora»: senza, una linea che sale a
destra si legge come qualcosa che è già successo. La previsione parte
dall'ultima misura e non da mezz'aria, i punti previsti sono vuoti invece
che pieni, e la legenda dice dove si va oltre a dove si è — un 0,58 previsto
non significa niente finché non si sa che adesso è 0,32.

Il backend restituisce `{observed, forecast}` e compone lui il momento a cui
la previsione si riferisce: `+48h` sommato all'ora della corsa. Si tiene
l'**ultima corsa per orizzonte**, non tutte — il calcolo previsionale gira
ogni sei ore, e le corse precedenti darebbero tre linee sovrapposte per lo
stesso futuro. Misurata: 52 ms.

## La colonna si allarga

Da 320-360 px a 380-440 px. C'era un secondo `grid-template-columns` più in
basso che sovrascriveva il primo, quindi la modifica va fatta in due posti o
non si vede. Il massimo resta legato alla mappa: oltre i 440 px si comincia
a togliere territorio per fare spazio a una lista.

## Il quadro nazionale si ordina, e smette di contraddirsi

La testata diceva «Incendio: 5024 aree in classe Alta» e le quattro caselle
subito sotto dicevano «0 High+». Non era un errore: le caselle sono di **un**
pericolo, perché le celle non si sommano fra pericoli — sono le stesse celle.
Ma il nome del pericolo stava in una riga staccata, facile da non leggere.
Ora sta sopra le caselle, attaccato ai numeri, perché è la loro unità di
misura.

Il resto — dettaglio per pericolo, cascate, report ML — va dietro un pannello
a scomparsa: sono numeri che si consultano, non che si sorvegliano, e tenerli
aperti spingeva i comuni sotto la piega.

Vedi #146 per la riga delle cascate, che conta il 99 % d'Italia come area
bruciata.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 030883c8cf

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/limen/data/repos/comune_risk.py Outdated
#: darebbe tre linee sovrapposte per lo stesso futuro.
_PREVISIONE_COMUNE = f"""
WITH peggiori AS ({_CELLE_PEGGIORI})
SELECT DISTINCT ON (p.hazard_type, ra.horizon)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude forecasts superseded by a below-threshold run

When a scheduled run lowers this cell below Moderate, persist_forecast_run omits the cell and deletes prior rows only for the retained cell_ids; therefore this DISTINCT ON still selects the previous above-threshold row for up to 24 hours and the chart presents it as the latest forecast. Select rows belonging to the actual latest run for each horizon, or clear forecasts for evaluated cells that the new run omitted.

Useful? React with 👍 / 👎.

Il pannello «Previsioni» diceva una cosa per regione — «nessuna regione
prevista sopra soglia» — mentre la domanda è per comune: *il mio* sta
salendo? Il pannello non c'è più. La previsione è entrata nella lista.

## In ogni riga

«Previsto: frana 0,62 alto · in salita · +48 h (gio 14)». Il pericolo con il
picco previsto più alto, di quanto sale rispetto ad adesso, e quando. La
freccia porta il verso; il colore lo ribadisce ma non da solo — «in salita»
è scritto accanto.

Un pericolo senza riga previsionale può voler dire due cose, e la riga le
distingue. Se la corsa per quel pericolo c'è stata, vuol dire **previsto
sotto Moderato**. Se non c'è stata affatto — oggi incendio e alluvione non
hanno una previsione per cella — la riga lo tace invece di dirlo tranquillo.

## Un selettore: adesso, o fra 72 ore

La stessa lista, due domande. «Chi è messo peggio» e «chi sta per esserlo»:
la seconda è quella per cui la previsione esiste, e trova il comune che oggi
è sotto soglia e domani no. L'attenzione prevista si compone con la stessa
regola di quella di adesso, così i due numeri si confrontano.

## Il timer, anzi due

Sono due calcoli e la testata li mostra entrambi. La previsione **per
cella** — quella delle righe e del grafico — gira una volta al giorno, nel
job notturno; ogni sei ore gira l'allerta **per regione**. Un solo conto
alla rovescia, quello da sei ore, farebbe credere che la curva di un comune
si aggiorni quattro volte al giorno.

Il prossimo scatto lo pubblica il **worker**, a ogni battito, in cache con
scadenza di tre battiti. L'API non lo può leggere da sé — lo scheduler vive
in memoria in quel processo — e dedurlo dall'ultima corsa (`started_at +
intervallo`) sbaglia proprio dopo un riavvio, quando `_deferred_interval`
sposta il primo scatto a un intervallo dal boot: cioè esattamente quando
qualcuno guarda il timer. Se il worker muore la chiave scade e la testata
dice «non disponibile» invece di contare verso un calcolo che nessuno farà.

## `latest_forecast` (057)

Lo stato corrente della previsione, come `latest_risk` lo è dell'adesso. La
previsione viveva solo nello storico partizionato: 755 ms per un comune
piccolo, venti secondi per i trenta della colonna. Ora 22 ms per la pagina,
315 ms per ordinare tutti i comuni sul futuro.

Il futuro di un comune è ora il massimo su **tutte** le sue celle, non la
cella peggiore di oggi: la previsione serve proprio a vedere il versante che
adesso è tranquillo e domani no. Il writer ci cancella anche le celle scese
sotto soglia — lo storico non lo faceva, e una cella prevista Moderata ieri
restava lì a dirlo oggi.

Popolata dalla corsa di stanotte: ~105.000 celle per orizzonte.

## La colonna

Da 320-360 px a `minmax(460px, min(34vw, 600px))`: cresce con lo schermo
fino a 600 px, oltre si toglie territorio alla mappa.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gzileni gzileni changed the title La previsione entra nel grafico, la colonna si allarga e si ordina La previsione sta nella lista dei comuni, con il suo timer; colonna più larga Sep 30, 2026
`_heartbeat_loop` ora riceve lo scheduler per pubblicare il prossimo scatto,
e il sostituto del test aveva ancora la firma di prima. In locale era
sfuggito perché avevo girato solo i test del codice toccato: la suite intera
lo prende.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gzileni
gzileni merged commit 76dc114 into main Sep 30, 2026
6 checks passed
@gzileni
gzileni deleted the sidebar-previsione branch September 30, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant