178 lines
5.0 KiB
Dart
178 lines
5.0 KiB
Dart
class StationWord {
|
|
final int id;
|
|
final String word;
|
|
final String emoji;
|
|
final String pos;
|
|
final String category;
|
|
final String desc;
|
|
|
|
const StationWord({
|
|
required this.id,
|
|
required this.word,
|
|
this.emoji = '',
|
|
this.pos = '',
|
|
this.category = '',
|
|
this.desc = '',
|
|
});
|
|
|
|
factory StationWord.fromMap(Map<String, dynamic> map) {
|
|
return StationWord(
|
|
id: (map['id'] as num?)?.toInt() ?? 0,
|
|
word: map['word'] as String? ?? '',
|
|
emoji: map['emoji'] as String? ?? '',
|
|
pos: map['pos'] as String? ?? '',
|
|
category: map['category'] as String? ?? '',
|
|
desc: map['desc'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
class TraditionStation {
|
|
final String id;
|
|
final String name;
|
|
final String symbol;
|
|
final String group;
|
|
final String lore;
|
|
final String? hebrew;
|
|
final String? hanzi;
|
|
final String? arabic;
|
|
final String? arcanum;
|
|
final StationWord? primary;
|
|
final List<StationWord> cluster;
|
|
final List<Map<String, String>> parallels;
|
|
final List<int> dots;
|
|
|
|
const TraditionStation({
|
|
required this.id,
|
|
required this.name,
|
|
required this.symbol,
|
|
required this.group,
|
|
required this.lore,
|
|
this.hebrew,
|
|
this.hanzi,
|
|
this.arabic,
|
|
this.arcanum,
|
|
this.primary,
|
|
this.cluster = const [],
|
|
this.parallels = const [],
|
|
this.dots = const [],
|
|
});
|
|
|
|
/// Four geomantic rows (1 or 2 dots each), head → feet. Empty if not a figure.
|
|
List<int> get geomancyRows {
|
|
if (dots.length == 4 && dots.every((n) => n == 1 || n == 2)) return dots;
|
|
final lines = symbol
|
|
.split('\n')
|
|
.map((s) => s.trim())
|
|
.where((s) => s.isNotEmpty)
|
|
.toList();
|
|
if (lines.length != 4) return const [];
|
|
final rows = <int>[];
|
|
for (final line in lines) {
|
|
final n = '·'.allMatches(line).length;
|
|
if (n != 1 && n != 2) return const [];
|
|
rows.add(n);
|
|
}
|
|
return rows;
|
|
}
|
|
|
|
String get groupKey {
|
|
final sep = group.indexOf(' · ');
|
|
if (sep <= 0) return group;
|
|
return group.substring(0, sep);
|
|
}
|
|
|
|
String get groupSub {
|
|
final sep = group.indexOf(' · ');
|
|
if (sep < 0) return '';
|
|
return group.substring(sep + 3);
|
|
}
|
|
|
|
factory TraditionStation.fromMap(Map<String, dynamic> map) {
|
|
final primaryMap = map['primary'];
|
|
final clusterRaw = map['cluster'];
|
|
return TraditionStation(
|
|
id: map['id'] as String? ?? '',
|
|
name: map['name'] as String? ?? '',
|
|
symbol: map['symbol'] as String? ?? '',
|
|
group: map['group'] as String? ?? '',
|
|
lore: map['lore'] as String? ?? '',
|
|
hebrew: map['hebrew'] as String?,
|
|
hanzi: map['hanzi'] as String?,
|
|
arabic: map['arabic'] as String?,
|
|
arcanum: map['arcanum'] as String?,
|
|
primary: primaryMap is Map<String, dynamic>
|
|
? StationWord.fromMap(primaryMap)
|
|
: null,
|
|
cluster: clusterRaw is List
|
|
? clusterRaw
|
|
.whereType<Map<String, dynamic>>()
|
|
.map(StationWord.fromMap)
|
|
.toList()
|
|
: const [],
|
|
dots: (map['dots'] as List? ?? const [])
|
|
.whereType<num>()
|
|
.map((n) => n.toInt())
|
|
.toList(),
|
|
parallels: (map['parallels'] as List? ?? const [])
|
|
.whereType<Map>()
|
|
.map((p) => {
|
|
'system': '${p['system'] ?? ''}',
|
|
'system_name': '${p['system_name'] ?? ''}',
|
|
'id': '${p['id'] ?? ''}',
|
|
'name': '${p['name'] ?? ''}',
|
|
'symbol': '${p['symbol'] ?? ''}',
|
|
})
|
|
.toList(),
|
|
);
|
|
}
|
|
|
|
bool matchesQuery(String query) {
|
|
if (query.isEmpty) return true;
|
|
final q = query.toLowerCase();
|
|
if (name.toLowerCase().contains(q)) return true;
|
|
if (lore.toLowerCase().contains(q)) return true;
|
|
if (symbol.contains(query)) return true;
|
|
if (hebrew != null && hebrew!.contains(query)) return true;
|
|
if (hanzi != null && hanzi!.contains(query)) return true;
|
|
if (arabic != null && arabic!.contains(query)) return true;
|
|
if (primary != null && primary!.word.toLowerCase().contains(q)) return true;
|
|
return cluster.any((c) => c.word.toLowerCase().contains(q));
|
|
}
|
|
}
|
|
|
|
class TraditionCanon {
|
|
final String id;
|
|
final String name;
|
|
final String icon;
|
|
final int count;
|
|
final String description;
|
|
final List<TraditionStation> stations;
|
|
|
|
const TraditionCanon({
|
|
required this.id,
|
|
required this.name,
|
|
required this.icon,
|
|
required this.count,
|
|
required this.description,
|
|
required this.stations,
|
|
});
|
|
|
|
factory TraditionCanon.fromMap(Map<String, dynamic> map) {
|
|
final raw = map['stations'];
|
|
return TraditionCanon(
|
|
id: map['id'] as String? ?? '',
|
|
name: map['name'] as String? ?? '',
|
|
icon: map['icon'] as String? ?? '',
|
|
count: (map['count'] as num?)?.toInt() ?? 0,
|
|
description: map['description'] as String? ?? '',
|
|
stations: raw is List
|
|
? raw
|
|
.whereType<Map<String, dynamic>>()
|
|
.map(TraditionStation.fromMap)
|
|
.toList()
|
|
: const [],
|
|
);
|
|
}
|
|
}
|