111 lines
3.5 KiB
Dart
111 lines
3.5 KiB
Dart
import 'dart:convert';
|
|
import 'dart:io';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/services.dart' show rootBundle;
|
|
|
|
import '../models/tradition_model.dart';
|
|
|
|
class TraditionsRepository {
|
|
static final TraditionsRepository _instance = TraditionsRepository._internal();
|
|
factory TraditionsRepository() => _instance;
|
|
TraditionsRepository._internal();
|
|
|
|
List<TraditionCanon> _traditions = const [];
|
|
bool _loaded = false;
|
|
|
|
List<TraditionCanon> get traditions => List.unmodifiable(_traditions);
|
|
bool get isLoaded => _loaded;
|
|
|
|
static const Map<String, String> filterToCanonId = {
|
|
'ᚱ Руны': 'runes',
|
|
'᚛ Огам': 'ogham',
|
|
'✡️ Каббала': 'kabbalah',
|
|
'⚗️ Алхимия': 'alchemy',
|
|
'🎴 Таро': 'tarot',
|
|
'🪶 Ленорман': 'lenormand',
|
|
'☯️ И Цзин': 'iching',
|
|
'⌛ Геомантия': 'geomancy',
|
|
'♈ Гороскоп': 'western_zodiac',
|
|
'🐉 Китайский зодиак': 'zodiac',
|
|
'🌌 Космология': 'cosmology',
|
|
'📅 Дни недели': 'days_of_week',
|
|
'🗓️ Месяцы года': 'months_of_year',
|
|
'🔢 Нумерология': 'numerology',
|
|
};
|
|
|
|
TraditionCanon? byId(String id) {
|
|
for (final t in _traditions) {
|
|
if (t.id == id) return t;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// Finds all stations across traditions that relate to this word (either as primary station or in cluster)
|
|
List<({TraditionCanon tradition, TraditionStation station, bool isPrimary})> findMatchesForWord(String word, {int? wordId}) {
|
|
final cleanWord = word.trim().toLowerCase();
|
|
final results = <({TraditionCanon tradition, TraditionStation station, bool isPrimary})>[];
|
|
|
|
for (final tradition in _traditions) {
|
|
for (final station in tradition.stations) {
|
|
if (station.primary != null &&
|
|
(station.primary!.word.trim().toLowerCase() == cleanWord ||
|
|
(wordId != null && station.primary!.id == wordId))) {
|
|
results.add((tradition: tradition, station: station, isPrimary: true));
|
|
} else if (station.cluster.any((cw) =>
|
|
cw.word.trim().toLowerCase() == cleanWord ||
|
|
(wordId != null && cw.id == wordId))) {
|
|
results.add((tradition: tradition, station: station, isPrimary: false));
|
|
}
|
|
}
|
|
}
|
|
return results;
|
|
}
|
|
|
|
Future<void> init() async {
|
|
if (_loaded && _traditions.isNotEmpty) return;
|
|
Map<String, dynamic>? decoded;
|
|
|
|
final cwd = Directory.current.path;
|
|
final candidates = <String>{
|
|
'assets/data/traditions_canon.json',
|
|
'../assets/data/traditions_canon.json',
|
|
'$cwd/assets/data/traditions_canon.json',
|
|
'$cwd/../assets/data/traditions_canon.json',
|
|
};
|
|
|
|
for (final path in candidates) {
|
|
try {
|
|
final file = File(path);
|
|
if (file.existsSync()) {
|
|
decoded = json.decode(file.readAsStringSync()) as Map<String, dynamic>;
|
|
break;
|
|
}
|
|
} catch (e) {
|
|
debugPrint('traditions_canon.json skip $path: $e');
|
|
}
|
|
}
|
|
|
|
if (decoded == null) {
|
|
try {
|
|
final jsonStr = await rootBundle.loadString('assets/data/traditions_canon.json');
|
|
decoded = json.decode(jsonStr) as Map<String, dynamic>;
|
|
} catch (e) {
|
|
debugPrint('Could not load traditions_canon.json: $e');
|
|
}
|
|
}
|
|
|
|
if (decoded == null) {
|
|
_traditions = const [];
|
|
_loaded = true;
|
|
return;
|
|
}
|
|
|
|
_traditions = decoded.values
|
|
.whereType<Map<String, dynamic>>()
|
|
.map(TraditionCanon.fromMap)
|
|
.toList();
|
|
_loaded = true;
|
|
}
|
|
}
|