Backend per il gioco mobile multiplayer asincrono "Contrabbandieri". Tutte le regole di gioco vivono sul server: il client non è mai considerato affidabile.
cp .env.example .env # poi cambia JWT_SECRET e POSTGRES_PASSWORD
mkdir -p data/postgres data/redis data/backups
docker compose up -d --build
```
Al primo avvio il container `api` applica automaticamente le migrazioni (`prisma migrate deploy`). Poi esegui il seed (città, item, listini):
```bash
docker compose exec api npx prisma db seed
```
Il server è su `http://localhost:3000` (health check: `GET /healthz`).
### Dati persistenti
Tutti i dati vivono in bind-mount locali dentro `data/` (`postgres/`, `redis/`, `backups/`): copiare la cartella del progetto su un altro server trasferisce tutto. Per il backup vedi §Backup.
**Bilanciamento**: ogni costante di gioco (costi viaggio, formule mercato, probabilità di successo missioni, eventi, XP) sta in [src/config/gameBalance.ts](src/config/gameBalance.ts), commentata. Nessun numero "magico" altrove.
## API REST (`/api/v1`)
Tutte le route tranne register/login richiedono `Authorization: Bearer <jwt>`.
- **Missioni**: `successo = 0.95 − risk×0.6 + livello×0.01 + reputazione×0.0005 − (pressione polizia−1)×0.05`, limitato a [5%, 95%]; la stessa stima è esposta al client in `/missions/available`. Ogni tipo ha un carattere (`typeConfig`): Consegna trasporta merce, Furto paga meno ma dà bottino in merce, Contrabbando paga molto e rischia di più, Informazioni dà XP e reputazione doppia. Difficoltà alte richiedono un livello minimo. Successo: denaro + XP + reputazione + eventuale bottino. Fallimento: −3 reputazione e multa (30% del premio × pressione polizia, mai oltre il denaro posseduto). Una missione attiva può essere abbandonata (`POST /missions/:id/abandon`, −1 reputazione, merce consumata persa). Massimo 3 missioni attive per giocatore.
- **XP**: per passare dal livello L a L+1 servono `100 × L^1.5` XP.
- **Eventi**: ogni 15 min possibile evento locale (25%), ogni ora possibile evento globale (20%); modificano prezzi e pressione di polizia finché attivi.
- **Ogni 15 minuti**: possibile evento locale, refresh classifiche Redis.
- **Ogni ora**: possibile evento globale, notifica eventi terminati.
## Sviluppo senza Docker
Servono PostgreSQL e Redis raggiungibili (puoi usare solo i container `db` e `redis`):
```bash
npm install
# in .env usa localhost al posto di db/redis
npx prisma migrate dev
npx prisma db seed
npm run dev
```
## Backup
```bash
# dump (a caldo, sicuro)
docker compose exec db pg_dump -U gameuser game > ./data/backups/game_$(date +%Y%m%d_%H%M).sql
# restore
cat ./data/backups/game_XXX.sql | docker compose exec -T db psql -U gameuser game
# migrazione completa su altro host: stop, archivio, riavvio
docker compose down
tar -czf contrabbandieri-data.tar.gz data .env docker-compose.yml
```
## Produzione
Il `Dockerfile` ha uno stage `production` (build TypeScript, solo dipendenze runtime, `node dist/server.js`). Prima del deploy: cambia `JWT_SECRET` e `POSTGRES_PASSWORD`, non esporre le porte 5432/6379, metti un reverse proxy HTTPS (es. Nginx) davanti alla porta 3000.