# Application Architecture ## Overview L'application suit une **Clean Architecture allégée** en trois couches, avec une règle de dépendance stricte : les dépendances pointent vers l'intérieur. Le state management est assuré par Riverpod (providers manuels). ## Couches ### core (transversal) - **`AppConstants`** : toutes les constantes métier en un seul endroit (vies, points, shiny odds, plages de générations, clés SharedPreferences, URL API). - **`logger`** : wrapper minimal autour de `dart:developer`. ### domain (Dart pur) - **Entités** : `Pokemon`, immuable, sans dépendance Flutter/DB/API. - **Repository (interface)** : `PokemonRepository` définit le contrat d'accès aux données. - **Jeu** : `GameState` (état immuable) et `GameEngine` (règles pures, testables). - `GameEngine` gère : soumission de réponse, vies, hints, skips, score, Shiny, bonus périodiques. - `GameStatus` : `loading | playing | roundWon | gameOver`. - `GuessResult` : `correct | wrong | gameOver | invalid`. ### data - **DTO** : `PokemonDto` centralise tout le parsing JSON (API Tyradex + SQLite). - `fromTyradexJson()`, `fromDb()`, `toDb()`. - **Datasources** : - `PokemonLocalDataSource` — SQLite via sqflite ; absent (`null`) sur le web. - `PokemonRemoteDataSource` — HTTP vers Tyradex + PokéAPI (genus anglais). - **Repository (impl)** : `PokemonRepositoryImpl` applique « DB locale d'abord, sinon API + cache ». ### l10n Internationalisation complète **FR / EN** via `flutter_localizations` + `intl`. Fichiers générés : `app_localizations.dart`, `app_localizations_fr.dart`, `app_localizations_en.dart`. La langue active est persistée dans SharedPreferences (`AppConstants.prefsLocale`). ### presentation #### Providers (Riverpod) | Provider | Type | Rôle | | --- | --- | --- | | `pokemonRepositoryProvider` | `Provider` | DI du repository | | `pokedexProvider` | `AsyncNotifier>` | Chargement + cache du Pokédex | | `gameProvider` | `Notifier` | État de la partie en cours | | `selectedTabProvider` | `StateProvider` | Onglet de navigation courant | | `localeProvider` | `Notifier` | Langue active (FR/EN) + persistance | | `themeProvider` | `Notifier` | Palette de couleurs active (5 thèmes) + persistance | | `genFilterProvider` | `Notifier>` | Générations sélectionnées pour le jeu + persistance | | `caughtCountProvider` | `Provider` | Nombre de Pokémon capturés (dérivé de pokedexProvider) | #### Pages | Fichier | Rôle | | --- | --- | | `main_page.dart` | Hub de navigation par onglets (Jeu / Pokédex / Système) | | `guess_page.dart` | Écran principal du jeu (silhouette, input, lives, score) | | `game_over_page.dart` | Écran de fin de partie avec stats de session | | `pokemon_list.dart` | Pokédex : liste filtrée + recherche par nom | | `pokemon_detail.dart` | Fiche détaillée : stats, type, genus, toggle normal/shiny | | `system_page.dart` | Paramètres (langue, palette) et statistiques globales | #### Widgets notables - **Réutilisables** : `PokemonImage`, `PokemonTile`, `PokemonTypeWidget`, `ScanlineOverlay`. - **guess/** : `GuessSilhouette`, `GuessInputSection`, `LivesRow`, `ScoreBoard`, `GenFilterSection`. - **detail/** : `PokemonDetailTop`, `PokemonStatsPanel`. - **game_over/** : `GameOverHeader`, `GameOverStats`, `GameOverActions`, `HingeDivider`. - **list/** : `PokedexListHeader`, `PokedexCountBar`. - **system/** : `LanguagePicker`, `PalettePicker`, `SectionTitle`, `SystemHeader`, `SystemStats`. #### Thème `type_colors.dart` : couleur et libellé localisé par type Pokémon. ## Flux de données ``` UI (Consumer) → Notifier → GameEngine (règles) + Repository (données) → DataSource (SQLite / HTTP) → DTO → Entity ``` Riverpod re-render automatiquement les consommateurs concernés. Plus de bus d'événements global ni d'accès inter-pages via l'arbre de widgets. ## Mécaniques de jeu (résumé) - **Vies** : 3 au départ ; une vie perdue par mauvaise réponse ; game over à 0. - **Hints** : 3 au départ ; révèle partiellement le nom ; +1 tous les 5 bonnes réponses consécutives. - **Skips** : 3 au départ ; passe au Pokémon suivant sans pénalité ; +1 tous les 10 bonnes réponses. - **Score** : +10 pts normal, +20 pts shiny ; meilleur score persisté via SharedPreferences. - **Shiny** : 1 chance sur 10 (`AppConstants.shinyOdds`). - **Filtre de génération** : le joueur choisit parmi Gen I–IX ; persisté entre les sessions. - **Acceptation bilingue** : le nom FR *ou* EN est accepté quelle que soit la langue de l'UI. ## Tests - `test/domain/game_engine_test.dart` : règles du jeu. - `test/data/pokemon_dto_test.dart` : parsing JSON ↔ DB. - `test/data/pokemon_repository_test.dart` : logique du repository (datasources factices). - `test/widget_test.dart` : smoke test de démarrage de l'app.