# Le due verita' della posizione di una foto

**Stato:** ✅ ATTUATO E PROVATO la sera del 2026-08-26, subito dopo il disegno.
Nasce da un difetto visto a schermo, non da una teoria: vedi sez. 1.
Gli esiti delle prove sono in sez. 6.

---

## 1. Il fatto che l'ha fatto nascere

Il 19/08/2026, giornata Campocecina-Pietrabuona. Le 23 foto del giorno:

| ora | cosa | posizione | nome sul cartellino |
|---|---|---|---|
| 10:05-10:27 | 16 foto, passeggiata ai prati | messa a mano col 📍 | **(niente)** |
| 12:42 | 1 foto, pranzo al parcheggio | messa a mano col 📍 | **(niente)** |
| 14:12-14:52 | 4 foto, Colonnata | dall'EXIF | `Colonnata (Carrara), Italia` |
| 21:11 | 2 foto, la notte | dall'EXIF | `Pietrabuona (Pescia), Italia` |

Le foto che abbiamo RADDRIZZATO sono le uniche senza nome del posto. E' il
contrario di quel che dovrebbe succedere.

**Perche':** il bottone 📍 scrive la posizione vera in
`maps/trips/<viaggio>/foto_posizioni.json` e azzera `fluoghi` nel map_points
("il nome lo rifa' il prossimo giro"). Ma il nome lo rifa'
`photo_gps.py::aggiungi_luoghi()`, che lo pesca da `lenostre.foto.localita` -
e quella colonna e' stata calcolata sulle coordinate dell'EXIF, cioe' su quelle
sbagliate. Nessuno ha mai detto all'indice che la posizione era cambiata.

**Lo stesso difetto, altra forma, chiuso il 26/08 mattina:** `via_points.py`
chiedeva a map_points DI QUALI foto fidarsi e poi rileggeva le coordinate
dall'EXIF per conto suo. Cinque foto gia' corrette rimandavano la strada in val
di Magra. E' la stessa radice: **due verita' e nessuna regola su chi comanda.**

## 2. Il timore di vitti, verificato

> "avevamo in progetto di cambiare l'indice delle foto, con i nomi e le
> coordinate manuali, cosi' se si rilegge l'exif non si perde il lavoro fatto"

Il progetto non era mai stato scritto (c'era solo una riga di promemoria in
bussola). Il timore invece e' fondato, ed e' verificabile in due punti:

- `wiz_foto/lenostre_index.php:127-129` - `ln_upsert()` fa
  `ON DUPLICATE KEY UPDATE ... lat=VALUES(lat), lon=VALUES(lon)`.
  **Rileggere l'EXIF di una cartella sovrascrive le coordinate.** (`localita`
  NON e' in quella lista: per questo i nomi sopravvivono a un import.)
- `wiz_foto/popola_foto_index.php:25` - la rigenerazione totale e' un
  `DELETE FROM foto`. I nomi si ripescano dalla cache subito dopo (riga 35), ma
  **una coordinata corretta a mano non avrebbe nessuna cache da cui tornare.**

Quindi: scrivere la posizione corretta dentro `foto.lat` sarebbe stato un
autogol. Serve un posto che l'EXIF non tocca.

## 3. La forma scelta: il file comanda, il DB e' una copia rifacibile

La tentazione e' "spostiamo la verita' nel DB". **No.** Vale la regola del
25/08: quel che sa un essere umano e il programma no si scrive in un file suo,
che i programmi leggono e non riscrivono mai.

| | dove sta | chi la scrive | si puo' perdere? |
|---|---|---|---|
| quel che dice la macchina | `foto.lat` / `foto.lon` | exiftool | si', e va bene: si rilegge |
| **quel che dicono vitti ed Elena** | `trips/<v>/foto_posizioni.json` | il bottone 📍 | **no, comanda** |
| la copia comoda | `foto.lat_mano` / `foto.lon_mano` | `ln_posizioni_fill()` | si', e non importa: si rifa' |
| quella che leggono tutti | `foto.lat_eff` / `foto.lon_eff` | la calcola il DB | - |

Il punto che tiene su tutto: **il DB non diventa la verita', diventa una copia
rifacibile.** Un `DELETE FROM foto` non fa danno, perche' i valori veri stanno
nei JSON e si riversano di nuovo. Non e' una seconda verita', e' una cache.

E `lat_eff` calcolata dal database serve a non ripetere l'errore di
`via_points.py`: **se la colonna giusta la calcola il DB, nessun lettore puo'
scordarsi di guardarla.**

## 4. L'ALTER (serve root: lenostre_app non ha ALTER)

```sql
ALTER TABLE lenostre.foto
  ADD COLUMN lat_mano DECIMAL(10,7) NULL AFTER lon,
  ADD COLUMN lon_mano DECIMAL(10,7) NULL AFTER lat_mano,
  ADD COLUMN lat_eff  DECIMAL(10,7) GENERATED ALWAYS AS (COALESCE(lat_mano, lat)) VIRTUAL,
  ADD COLUMN lon_eff  DECIMAL(10,7) GENERATED ALWAYS AS (COALESCE(lon_mano, lon)) VIRTUAL;
```

Solo aggiunte, nessuna colonna toccata, nessun dato riscritto: chi legge oggi
continua a leggere come prima. VIRTUAL = non occupa spazio, si calcola alla
lettura.

## 5. Il codice

### 5.1 `ln_posizioni_fill(PDO $pdo, ?string $trip = null): array` (nuova)
In `wiz_foto/lenostre_index.php`, accanto a `ln_localita_fill`.
Legge `maps/trips/*/foto_posizioni.json` (o di un viaggio solo), e per ogni
foto scrive `lat_mano`/`lon_mano`. **Dove il valore CAMBIA, azzera anche
`localita`**, cosi' il giro dopo il nome si rifa' sulla posizione nuova.
Torna `['foto'=>N, 'cambiate'=>N]`.

### 5.2 Chi la chiama
- il bottone 📍 (`maps/convalida_foto.php`, azione `place`): subito dopo aver
  scritto il JSON, per le foto toccate. Cosi' il nome si aggiorna senza aspettare.
- `wiz_foto/popola_foto_index.php`: dopo il re-scan e **prima** di
  `ln_localita_fill`, se no i nomi rinascono sulle coordinate vecchie.
- `wiz_foto/geocodifica_foto.php`: idem, cosi' l'attrezzo dell'arretrato si
  porta dietro anche le correzioni.

### 5.3 I lettori da spostare su `lat_eff`/`lon_eff`
Sono pochi, contati il 26/08:

| file | riga | cosa fa | tocca? |
|---|---|---|---|
| `wiz_foto/lenostre_index.php` | 247 | `ln_localita_fill`: SELECT id, lat, lon | **SI', e' il punto** |
| `wiz_foto/geocodifica_foto.php` | 25, 33 | i due contatori | si', per coerenza |
| `wiz_foto/popola_foto_index.php` | 39 | contatore "quante col GPS" | si', per coerenza |
| `lab/platform/lib/vrn_foto.php` | 29 | Ricerca foto: restituisce lat, lon | si' |
| `wiz_foto/gestore_foto.php` | 709 | SELECT lat (c'e'/non c'e' il GPS) | si' |
| `maps/photo_gps.py` | 100 | SELECT path, localita | **no**: non legge coordinate |

`ln_upsert()` NON si tocca: non nomina le colonne `_mano`, quindi un import non
puo' portarsele via. E' esattamente la proprieta' che si voleva.

## 6. Le prove, e come sono andate (26/08 sera)

### 6.0 La scoperta che ha alzato la posta

Prima di attuare, guardato cosa AVEVA l'indice per le 23 foto del 19/08. Non
erano senza nome: erano col nome SBAGLIATO, calcolato sulle coordinate che il
GPS si era inventato.

| ora | nel map_points si vedeva | ma nell'indice c'era scritto |
|---|---|---|
| 10:05-10:27 (16 foto) | (niente) | `Ponte di Arcola`, `Castiglione Vara (Beverino)`, `Bedizzano (Carrara)` x8, `Massa` x6, `Carrara` |
| 12:42 (pranzo) | (niente) | `Bedizzano (Carrara)` |

Cioe': al primo «Ricostruisci» il cartellino della passeggiata del mattino non
sarebbe rimasto vuoto - avrebbe scritto **«Bedizzano»**, con la faccia di chi sa.
Un nome sbagliato e' peggio di nessun nome. **Non era un difetto estetico.**

### 6.1 Esiti

| # | prova | esito |
|---|---|---|
| 1 | stato di partenza | 0 foto con `lat_mano`, 28 posizioni nei JSON |
| 2 | `ln_posizioni_fill()` | lette 28, **cambiate 26**, tolte 0, ignote 2 |
| 3 | `geocodifica_foto.php --tutto` | 26 ribattezzate in 4 posti, 8 domande a Nominatim |
| 4 | il 19/08 dopo la cura | 16 foto -> `Campocecina (Carrara)`, il pranzo -> `Colonnata (Carrara)` al parcheggio |
| 5 | **`ln_reindex_target` sulla cartella** (rilegge l'EXIF di 23 foto) | 17 posizioni a mano e 16 nomi **intatti** |
| 6 | **simulato il `DELETE FROM foto`** (azzerate tutte le `_mano` + `localita`) | `ln_posizioni_fill` ne rimette 26, `ln_localita_fill` ribattezza 26 con **0 domande alla rete** |

Le **2 ignote** sono due foto del 18/08 che il JSON nomina ancora e che non sono
piu' su disco (cestinate dal Gestore foto). La funzione lo dice e tira dritto.

### 6.2 Quel che resta da guardare a video
Premere **🔄 Ricostruisci** e controllare il cartellino della passeggiata del
mattino: deve dire `Campocecina`. Stasera non e' stato premuto - il map_points
del viaggio vero non e' stato toccato.

## 7. Cosa si sistema, oltre al cartellino

- il **tooltip del Gestore foto** smette di mostrare il posto sbagliato per le
  foto raddrizzate (e con lui il tasto 📋 con cui Elena battezza le cartelle);
- la **Ricerca foto** della piattaforma trova la foto dove sta davvero;
- una foto raddrizzata resta raddrizzata **anche fuori dal viaggio** in cui
  qualcuno l'ha corretta.

## 8. Quel che questo disegno NON fa

- Non permette di correggere una foto che **non sta in nessun viaggio**: il
  bottone 📍 vive nella pagina di un viaggio. Se un giorno servira', il posto
  naturale e' il Gestore foto, e allora servira' un elenco che non sia
  per-viaggio. Oggi non serve: non e' un buco, e' un confine.
- Non tocca `foto_a_piedi.json` / `foto_nascoste.json` / `foto_giorno.json` /
  `passeggiate.json`: quelle sono scelte sul RACCONTO di un viaggio, non fatti
  sulla foto. Stanno giuste dove stanno.
