import 'dart:math'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../../core/config/app_constants.dart'; import '../../domain/game/game_engine.dart'; import '../../domain/game/game_state.dart'; import '../../core/logger.dart'; import 'pokedex_provider.dart'; import 'repository_provider.dart'; /// Orchestration de la partie : relie GameEngine (règles), le repository (données) /// et SharedPreferences (best score). class GameNotifier extends Notifier { static const _engine = GameEngine(); final _random = Random(); @override GameState build() => const GameState(); Future startNewGame() async { state = _engine.newGame(state); await _loadBestScore(); await loadNextPokemon(); } Future _loadBestScore() async { final prefs = await SharedPreferences.getInstance(); state = state.copyWith(bestScore: prefs.getInt(AppConstants.prefsBestScore) ?? 0); } Future loadNextPokemon() async { state = state.copyWith(status: GameStatus.loading); final repo = ref.read(pokemonRepositoryProvider); final isShiny = _random.nextInt(AppConstants.shinyOdds) == 0; final id = _random.nextInt(AppConstants.totalPokemon) + 1; try { final pokemon = await repo.getById(id); if (pokemon == null) { state = state.copyWith(status: GameStatus.error); return; } state = _engine.startRound(state, pokemon, isShiny: isShiny); } catch (e, st) { AppLogger.error('loadNextPokemon a échoué', e, st); state = state.copyWith(status: GameStatus.error); } } Future submitGuess(String guess) async { final outcome = _engine.submitGuess(state, guess); state = outcome.state; if (outcome.result == GuessResult.correct) { final repo = ref.read(pokemonRepositoryProvider); final caught = state.currentPokemon; if (caught != null) await repo.update(caught); await _persistBestScore(); if (!kIsWeb) ref.invalidate(pokedexProvider); // rafraîchit la liste (pas de persistance sur web) } return outcome.result; } Future _persistBestScore() async { final prefs = await SharedPreferences.getInstance(); final stored = prefs.getInt(AppConstants.prefsBestScore) ?? 0; if (state.bestScore > stored) { await prefs.setInt(AppConstants.prefsBestScore, state.bestScore); } } void useHint() => state = _engine.useHint(state); Future useSkip() async { final updated = _engine.useSkip(state); if (updated.skips == state.skips) return; // pas de skip dispo state = updated; await loadNextPokemon(); } } final gameProvider = NotifierProvider(GameNotifier.new);