# Coaster World DATA — v1.0.0

Version du 1er octobre 2026, construite sur v0.20.2 et l’ensemble des mises à jour DATA antérieures. Application Laravel 13 / PHP 8.3+, séparée du site principal et de l’application mobile.

## Installation sous Laragon

1. Activer PHP 8.3 ou plus et MySQL/MariaDB. Extensions : PDO MySQL, mbstring, XML/DOM, ctype, fileinfo, curl, OpenSSL et zip.
2. Extraire l’archive complète dans `C:/laragon/www/coaster-world-data`. Configurer la racine web du domaine sur le sous-dossier `public/`.
3. Créer une base MySQL vide `coaster_world_data`. Copier `.env.example` vers `.env`, puis renseigner `DB_*` et `APP_URL`.
4. Depuis le terminal Laragon, lancer `INSTALL_DATA.bat`. L’archive contient le code et les dépendances, sans secrets ni base personnelle. Le dossier `vendor/` est fourni ; Composer est nécessaire seulement pour réinstaller les dépendances.
5. Ouvrir `http://coaster-world-data.test/setup` depuis le même ordinateur et créer le premier administrateur. Aucun compte administrateur ni mot de passe par défaut n’est fourni.
6. Lancer `START_DATA.bat`. Il démarre le scheduler, un worker Live et un worker de collecte. Vérifier les trois indicateurs dans **Système**.
7. Créer une clé dans **Accès API et utilisateurs** pour le serveur qui consommera l’API.

Commandes équivalentes, après création et configuration de `.env` :

```bash
php artisan config:clear
php artisan cw:data:install --generate-key
php artisan optimize:clear
php artisan schedule:work
```

Dans deux autres terminaux :

```bash
php artisan queue:work --queue=live --sleep=1 --tries=3 --timeout=60
php artisan queue:work --queue=default --sleep=2 --tries=2 --timeout=360
```

`STOP_DATA.bat` arrête les processus lancés par le script. `STATUS_DATA.bat` affiche leur état. En production, superviser les deux workers et exécuter `php artisan schedule:run` chaque minute. Aucun build npm n’est nécessaire pour l’administration : ses fichiers CSS et JavaScript sont servis directement.

## Mise à jour depuis v0.20.2

Conserver son `.env`, son `APP_KEY`, sa base et son dossier `storage/`. Arrêter les workers avec `STOP_DATA.bat`, puis superposer les fichiers de l’archive `_update.zip`. Renseigner `CW_DATA_VERSION=1.0.0` et `DB_QUEUE_RETRY_AFTER=480` dans `.env` ; définir `CW_DATA_API_REQUIRE_KEY=true` si l’API doit être privée.

Lancer `UPDATE_DATA.bat` depuis le terminal Laragon : il crée et vérifie une sauvegarde avant les migrations, puis lance l’installation additive. Relancer `START_DATA.bat`. Les choix des fournisseurs existants, les corrections, les identifiants et les données métier sont conservés. L’installeur du catalogue historique conserve son comportement de restauration d’un fournisseur supprimé ; aucune désactivation existante n’est remplacée.

L’archive complète convient à une installation dans un nouveau dossier. Pour une installation existante, employer la mise à jour. Ne pas employer `migrate:fresh` ou régénérer une clé existante.

## Parcours de collecte

- **Collecte et exploitation** : rechercher un parc, une attraction, un coaster ou un POI par nom. Une attraction, un coaster ou un POI doit avoir un parc de rattachement.
- Examiner les candidats dans **Ingestion**, puis associer une fiche existante ou créer une fiche explicitement.
- Dans une fiche, ouvrir **Sources et données** : contrôler les identifiants, lancer l’enrichissement, consulter les observations et l’historique, ajouter des organisations ou des médias avec leurs droits.
- Valider les propositions dans **À vérifier**. Les collectes statiques et l’IA ne modifient pas silencieusement les valeurs canoniques.
- Programmer les collectes statiques avec un intervalle d’au moins 24 heures. Les propositions restent soumises à la revue.

Les collectes et analyses longues utilisent la file `default`. Leur page affiche l’état et se rafraîchit automatiquement. Un échec peut être relancé. Les fiches de coaster peuvent recevoir des informations Wikidata à partir d’un identifiant vérifié ; les quantités sans unité reconnue sont ignorées.

## Fournisseurs et Live

L’installation enregistre les fournisseurs manquants : ThemeParks.wiki, Queue-Times, Wikidata, Wikipedia et OpenStreetMap/Overpass. Les fournisseurs, capacités, sources, périmètres et priorités restent configurables.

ThemeParks.wiki et Queue-Times disposent de connecteurs Live effectifs. Chaque parc est traité dans un job indépendant. Les correspondances reposent sur les identifiants externes du fournisseur ; une ressemblance de nom ne suffit pas. Les données inconnues ne créent pas automatiquement de nouvelles attractions.

Une source HTTP JSON personnalisée peut déclarer `live_endpoint_template` et `live_mapping` dans ses métadonnées. Exemple :

```json
{
  "live_endpoint_template": "https://api.example.com/parks/{park_id}/live",
  "live_mapping": {
    "items": "rides", "id": "id", "status": "status", "wait": "wait_minutes",
    "timestamp": "updated_at", "status_map": {"OPEN": "open", "CLOSED": "closed"}
  }
}
```

Le fournisseur doit être actif, sa capacité `wait_times` activée et les fiches reliées à ses identifiants `default`. Les désactivations par parc ou par source sont respectées. Les appels HTTP ont des délais limités, les redirections automatiques sont désactivées et les adresses privées sont bloquées par défaut.

L’API lit les tables locales et n’appelle aucun fournisseur. Une attente expirée devient `null`, avec `freshness=expired` et un état courant inconnu. Une fermeture connue du parc masque l’attente ; un horaire manquant reste inconnu. ThemeParks.wiki utilise une date de dernier changement : le moteur conserve cette date et évalue sa fraîcheur à partir de la dernière collecte réussie. Les horaires gardent le fuseau local et couvrent les ouvertures qui passent minuit.

Les réponses Live indiquent l’attribution. Afficher **Powered by Queue-Times.com** avec un lien vers Queue-Times lorsque ses données sont utilisées, ainsi que l’attribution ThemeParks.wiki applicable. Vérifier les conditions des sources avant une diffusion externe de leurs données.

## API

Base : `/api/v1`. Avec `.env.example`, les données nécessitent `Authorization: Bearer <clé>` ou `X-API-Key`. La clé est stockée sous forme de hash, peut être révoquée et doit rester côté serveur. `/api/v1/health` reste accessible pour la supervision. L’API retourne des réponses JSON, avec pagination, limites de débit et en-têtes de cache.

```bash
curl -H "Authorization: Bearer VOTRE_CLE" "http://coaster-world-data.test/api/v1/parks?locale=fr"
```

Principales routes :

| Route GET | Contenu |
| --- | --- |
| `/parks`, `/parks/{id}` | Catalogue et fiche parc |
| `/parks/{id}/attractions`, `/parks/{id}/coasters`, `/parks/{id}/pois` | Contenu d’un parc |
| `/attractions/{id}`, `/coasters/{id}`, `/pois/{id}` | Fiches et données canoniques |
| `/search?q=...` | Recherche transversale |
| `/parks/{id}/live`, `/attractions/{id}/live` | État Live local |
| `/attractions/{id}/live/history` | Mesures historiques paginées |
| `/parks/{id}/schedule` | Horaires, fuseau et état du parc |
| `/entities/{type}/{id}/media` | Médias dont les droits et la diffusion sont confirmés |
| `/entities/{type}/{id}/organizations` | Constructeurs, propriétaires, exploitants et périodes |

Les fiches exposent la confiance, la vérification, les dates et la source des valeurs canoniques. Langues : `fr`, `en`, `de`, `es`, `it`, via `locale` ou `Accept-Language`. Le fichier `docs/openapi.json` décrit les routes GET disponibles.

## IA facultative

Renseigner `OPENAI_API_KEY` et un modèle compatible avec Responses et la recherche web dans `CW_DATA_AI_MODEL`, puis activer `CW_DATA_AI_ENABLED=true`. L’IA est désactivée par défaut. Elle ne soumet que des observations dont l’URL figure dans les citations ou les sources retournées par la recherche ; la confiance est plafonnée à 70. Une validation humaine reste nécessaire. Aucun appel payant réel n’a été effectué pour la validation de cette livraison.

## Sauvegarde et contrôle de restauration

Une sauvegarde quotidienne est programmée à 03:00 UTC, avec rétention de 20 archives. La base est sauvegardée par `mysqldump` ou `mariadb-dump` ; son exécutable est détecté dans une installation Laragon standard. Les chemins peuvent être précisés dans `CW_DATA_MYSQLDUMP_BINARY` et `CW_DATA_MYSQL_BINARY`.

```bash
php artisan cw:data:backup
php artisan cw:data:backup --verify=cwdata-YYYYMMDD-HHMMSS-xxxxxx.zip
php artisan cw:data:restore-check cwdata-YYYYMMDD-HHMMSS-xxxxxx.zip --database=coaster_world_data_restore_test
```

La restauration de contrôle exige un **nouveau nom de base** et n’écrit pas dans la base courante. Elle contrôle les empreintes et les nombres de lignes des tables métier. Le compte utilisé doit pouvoir créer la base de contrôle. Les tables de jobs, cache et sessions sont exclues de cette comparaison car elles évoluent continuellement.

Les sauvegardes contiennent la base, un manifeste et, lorsque `.env` existe, sa copie chiffrée. Conserver `APP_KEY` séparément pour relire cette copie. `storage/app/private/data-backups` doit être copié régulièrement vers un autre disque ou une destination de sauvegarde. Les médias externes sont sauvegardés comme références, pas comme fichiers téléchargés.

## Vérifications et références

```bash
php artisan test
php artisan route:list --path=api
php artisan cw:system:status
```

Voir `docs/VALIDATION_v1.0.0.md`, `CHANGELOG_v1.0.0.md` et `docs/RELEASE_MANIFEST_v1.0.0.json`. Les notes des versions antérieures sont conservées dans `docs/README_REFERENCE_v0.20.2.md` et dans les documents historiques.

Les paramètres réels de la base Laragon et les éventuelles clés de services restent à renseigner sur l’ordinateur cible. Les tests des fournisseurs utilisent des réponses contrôlées ; leurs disponibilités et leurs conditions peuvent évoluer. La base encyclopédique réelle se remplit ensuite avec les importations et validations de l’administration.
