# Simulador de Contaminació Marina

Visor web de trajectòries lagrangianes de **~10.000 partícules contaminants** al Mediterrani occidental. Les partícules surten de punts de la costa catalana i es dispersen amb els corrents marins durant 72 hores. Quan arriben a la costa, s’encallen i s’acumulen, mostrant zones d’impacte.

**Stack:** Python · FastAPI · Next.js · Deck.gl · MapLibre (sense claus d’API)

---

## Arquitectura

```
trajectories/
├── backend/                 # API i dades
│   ├── main.py              # FastAPI: metadata, blocs JSON/Arrow, CORS, gzip
│   ├── data/                # Dades servides per l’API
│   │   ├── metadata.json    # (opcional) simulació "default" a la arrel
│   │   └── simulations/     # Una carpeta per simulació
│   │       └── <sim_id>/   # metadata.json, block_0.arrow, block_1.arrow, ...
│   ├── etl/                 # Pipeline NetCDF → blocs Arrow + metadata
│   │   ├── nc_reader.py     # Lectura NetCDF (lon, lat, u, v, beached, temps)
│   │   ├── pipeline.py      # Orquestració: load_nc → subsample horari → write_blocks_arrow
│   │   └── to_blocks.py     # Escriptura Arrow IPC + metadata.json
│   └── scripts/
│       └── run_etl.py      # CLI: python -m scripts.run_etl fitxer.nc [--sim-id ...]
│
└── frontend/                # App Next.js (App Router)
    ├── src/
    │   ├── app/page.tsx     # Pàgina principal → TrajectoryMap
    │   ├── components/      # MapView, MapHeader, TimePlayer, TrajectoryMap, IntroDialog, …
    │   ├── hooks/           # useBlocks (càrrega Arrow/JSON), useSimulation, useMapLayers, useMetadata
    │   ├── lib/              # constants, trajectoryData (buildTrails, buildTripsWithTime)
    │   └── types/            # trajectory (Meta, Block, PointDatum, TripDatum, …)
```

- **Backend:** Servir `metadata.json` i blocs de frames (JSON o **Arrow IPC**). Les dades viuen a `backend/data/` o `backend/data/simulations/<sim_id>/`. L’API accepta `?sim=default` (o qualsevol `sim_id`) per triar simulació.
- **Frontend:** Demana metadata a `/api/metadata?sim=...`, després els blocs a `/api/block/{id}` o `/api/block/{id}/arrow`. Construeix trails i trips a memòria (TripsLayer amb timestamps, PathLayer per selecció). Deck.gl + MapLibre renderitzen el mapa; el reproductor temporal avança el `currentTime` i es visualitzen les trajectòries amb color per origen, bloom/glow i partícules actives/beached.

---

## Com arrencar el projecte

### Requisits

- **Backend:** Python 3.10+, Node 18+ (només si no tens les dependències del backend instal·lades)
- **Frontend:** Node 18+

### 1. Backend

```bash
cd backend

# Entorn virtual i dependències
python3 -m venv venv
source venv/bin/activate   # Windows: venv\Scripts\activate
pip install -r requirements.txt

# Dades (una de les dues opcions)
# Opció A: Dades de prova (sense NetCDF)
python generate_dummy_data.py

# Opció B: ETL des d’un NetCDF (genera block_*.arrow + metadata a data/simulations/<sim_id>/)
python -m scripts.run_etl path/to/trajectories.nc
python -m scripts.run_etl path/to/file.nc --sim-id my_run --write-json   # opcional JSON

# Servidor API (port 8000)
uvicorn main:app --reload
```

L’API queda disponible a **http://localhost:8000**.

### 2. Frontend

```bash
cd frontend

npm install
npm run dev
```

Obre **http://localhost:3000**. Per defecte el frontend crida l’API a `http://localhost:8000` (configurable amb `NEXT_PUBLIC_API_URL` si cal).

### 3. Ús bàsic

1. Backend en marxa (terminal 1), frontend en marxa (terminal 2).
2. Obrir http://localhost:3000.
3. Tancar/acceptar el popup d’introducció i esperar que carreguin els blocs (barra de progrés).
4. Play / slider / velocitat (×0.5 … ×8). Zoom a les partícules (botó crosshair), Filters (basemap, capes), Info.

---

## API (resum)

| Endpoint | Descripció |
|----------|------------|
| `GET /api/simulations` | Llista d’IDs de simulació disponibles |
| `GET /api/metadata?sim=default` | Metadata (num_particles, num_steps, num_blocks, seed_names, origins, time_start, time_end, …) |
| `GET /api/block/{id}?sim=default` | Bloc en JSON (frames + step_start, step_end, accumulation) |
| `GET /api/block/{id}/arrow?sim=default` | Bloc en Apache Arrow IPC (columnes: step, particle_id, lon, lat, u, v, beached) |

---

## Característiques

- **Partícules i temps:** milers de partícules, 72 h (1 pas/hora), blocs de 24 h per càrrega progressiva.
- **Trajectòries:** TripsLayer amb cap arrodonit, color per origen (paleta), bloom/glow; partícules actives vs beached (vermell).
- **Mapa:** MapLibre (basemaps Carto), zoom/fit a partícules, tooltip amb origen i velocitat.
- **Dades:** ETL des de NetCDF (subsample horari, beached persistent) o dades de prova amb `generate_dummy_data.py`.
