import 'dart:convert'; import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart' show rootBundle; import '../models/lenormand_pairs.dart'; class LenormandPairsRepository { static final LenormandPairsRepository _instance = LenormandPairsRepository._internal(); factory LenormandPairsRepository() => _instance; LenormandPairsRepository._internal(); final Map _byN = {}; List _triads = const []; List _extras = const []; bool _loaded = false; bool get isLoaded => _loaded; List get cards => List.unmodifiable(_byN.values.toList()..sort((a, b) => a.n.compareTo(b.n))); List get triads => List.unmodifiable(_triads); List get extras => List.unmodifiable(_extras); LenormandCardEntry? byNumber(int n) => _byN[n]; LenormandCardEntry? byStationId(String id) { if (id.startsWith('card_')) { final n = int.tryParse(id.substring(5)); if (n != null) return _byN[n]; } return null; } Future init() async { if (_loaded && _byN.isNotEmpty) return; Map? decoded; final cwd = Directory.current.path; final candidates = { 'assets/data/lenormand_pairs.json', '../assets/data/lenormand_pairs.json', '$cwd/assets/data/lenormand_pairs.json', '$cwd/../assets/data/lenormand_pairs.json', }; for (final path in candidates) { try { final file = File(path); if (file.existsSync()) { decoded = json.decode(file.readAsStringSync()) as Map; break; } } catch (e) { debugPrint('lenormand_pairs.json skip $path: $e'); } } if (decoded == null) { try { final jsonStr = await rootBundle.loadString('assets/data/lenormand_pairs.json'); decoded = json.decode(jsonStr) as Map; } catch (e) { debugPrint('Could not load lenormand_pairs.json: $e'); } } if (decoded == null) { _loaded = true; return; } _byN.clear(); for (final raw in (decoded['cards'] as List? ?? const [])) { if (raw is! Map) continue; final card = LenormandCardEntry.fromMap(raw); _byN[card.n] = card; } _triads = (decoded['triads'] as List? ?? const []) .whereType>() .map(LenormandTriad.fromMap) .toList(); _extras = (decoded['extras'] as List? ?? const []) .whereType>() .map(LenormandExtra.fromMap) .toList(); _loaded = true; } }