feat: complete academic symbol lexicon heal, 2-column Cooper extraction, and updated assets
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
/// Канонический реестр культурных ветвей человечества, через которые
|
||||
/// толкуется каждый знак. Порядок списка — порядок показа в «учебнике».
|
||||
class CultureBranch {
|
||||
final String id;
|
||||
final String name;
|
||||
final String emoji;
|
||||
final String subtitle;
|
||||
|
||||
/// Стемы/ключевые слова (в нижнем регистре), по которым ветвь узнаётся в тексте.
|
||||
final List<String> stems;
|
||||
|
||||
const CultureBranch({
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.emoji,
|
||||
required this.subtitle,
|
||||
required this.stems,
|
||||
});
|
||||
|
||||
/// Dart-овский `\b` не понимает кириллицу, поэтому граница слова
|
||||
/// задаётся явным lookbehind по буквам.
|
||||
RegExp get matcher => RegExp(
|
||||
'(?<![a-zа-яё])(?:${stems.map(RegExp.escape).join('|')})',
|
||||
caseSensitive: false,
|
||||
unicode: true,
|
||||
);
|
||||
|
||||
bool matches(String text) => matcher.hasMatch(text.toLowerCase());
|
||||
}
|
||||
|
||||
const List<CultureBranch> kCultureBranches = [
|
||||
CultureBranch(
|
||||
id: 'sumer',
|
||||
name: 'Шумер и Месопотамия',
|
||||
emoji: '🏺',
|
||||
subtitle: 'Клинопись • Ану, Энлиль, Инанна, Уту',
|
||||
stems: ['шумер', 'аккад', 'месопотам', 'вавилон', 'ассири', 'клинопис', 'уту', 'инанн', 'иштар', 'энлил', 'энки', 'мардук', 'тиамат', 'ануннак', 'гильгамеш', 'эрешкигаль', 'mūšu', 'ilū'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'egypt',
|
||||
name: 'Древний Египет',
|
||||
emoji: '🪲',
|
||||
subtitle: 'Нил и Дуат • Ра, Осирис, Исида, Маат',
|
||||
stems: ['египет', 'египт', 'фараон', 'апоп', 'нут ', 'нут,', 'дуат', 'осирис', 'исид', 'тот ', 'маат', 'анубис', 'сехмет', 'хепри', 'атум', 'птах', 'ра ', 'ра,', 'ра.', 'гор '],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'judaic',
|
||||
name: 'Иудейская традиция и Каббала',
|
||||
emoji: '✡️',
|
||||
subtitle: 'Танах, Талмуд, Зоар • Древо Сфирот',
|
||||
stems: ['иудей', 'иудаизм', 'еврей', 'каббал', 'танах', 'тора ', 'торы', 'талмуд', 'зоар', 'библ', 'бытие', 'бытия', 'сфир', 'цимцум', 'иврит', 'йом', 'эрев', 'лайла', 'хошех', 'эйн-соф', 'эйн соф', 'шхин'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'greco_roman',
|
||||
name: 'Античность (Греция и Рим)',
|
||||
emoji: '🏛️',
|
||||
subtitle: 'Гесиод, Гомер, Платон • Олимп и Хаос',
|
||||
stems: ['греци', 'греческ', 'грек', 'эллин', 'римск', 'рима', 'латин', 'античн', 'зевс', 'нюкт', 'гемер', 'эфир', 'юпитер', 'аполлон', 'гелиос', 'гомер', 'гесиод', 'платон', 'персефон', 'гермес', 'dies irae'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'celtic',
|
||||
name: 'Кельты и друиды',
|
||||
emoji: '🌿',
|
||||
subtitle: 'Огам, Самайн, Белтайн • Иной мир сидов',
|
||||
stems: ['кельт', 'огам', 'друид', 'самайн', 'белтайн', 'имболк', 'лугнас', 'ирланд', 'валлий', 'бригит', 'сиды', 'туата'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'norse',
|
||||
name: 'Скандинавия и германцы',
|
||||
emoji: 'ᚱ',
|
||||
subtitle: 'Эдды, руны • Один, Иггдрасиль, Рагнарёк',
|
||||
stems: ['скандинав', 'германск', 'норвеж', 'исланд', 'эдд', 'руна ', 'руны', 'рун ', 'одина', 'одину', 'иггдрасил', 'рагнар', 'асгард', 'вальхал', 'фрейя', 'локи', 'норны', 'дагаз'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'slavic',
|
||||
name: 'Славянская традиция',
|
||||
emoji: '☀️',
|
||||
subtitle: 'Явь, Навь, Правь • Велес, Перун, Макошь',
|
||||
stems: ['славян', 'древнерус', 'явь', 'навь', 'нави ', 'правь', 'велес', 'перун', 'макош', 'мокош', 'сварог', 'даждьбог', 'ярил', 'купал', 'коляд', 'стрибог', 'домов', 'леший', 'русалк'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'vedic',
|
||||
name: 'Ведическая Индия',
|
||||
emoji: '🕉️',
|
||||
subtitle: 'Веды и Упанишады • Рита, карма, атман',
|
||||
stems: ['индийск', 'индуи', 'ведическ', 'веды', 'вед ', 'ригвед', 'упанишад', 'санскрит', 'дхарм', 'карм', 'брахман', 'атман', 'сурья', 'агни', 'индра', 'шива', 'вишну', 'кали ', 'рита ', 'тантр'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'persian',
|
||||
name: 'Персия и зороастризм',
|
||||
emoji: '🔥',
|
||||
subtitle: 'Авеста • Ахура-Мазда и Ахриман, Аша',
|
||||
stems: ['персид', 'персы', 'иран', 'зороастр', 'заратустр', 'авест', 'ахура', 'ахриман', 'митр'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'china',
|
||||
name: 'Древний Китай',
|
||||
emoji: '☯️',
|
||||
subtitle: 'Дао, Инь-Ян, У-син • Книга Перемен',
|
||||
stems: ['китай', 'дао', 'инь', 'ян ', 'ян,', 'ян.', 'ян:', 'и цзин', 'и-цзин', 'гексаграмм', 'триграмм', 'конфуци', 'лао-цзы', 'лао цзы', 'чжуан', 'у-син', 'у син', 'иероглиф'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'japan',
|
||||
name: 'Япония и синто',
|
||||
emoji: '⛩️',
|
||||
subtitle: 'Кодзики • Аматэрасу, ками, дзэн',
|
||||
stems: ['япон', 'синто', 'аматэрасу', 'ками ', 'кодзики', 'дзэн', 'идзанаги', 'идзанами'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'islamic',
|
||||
name: 'Ислам и суфизм',
|
||||
emoji: '🌙',
|
||||
subtitle: 'Коран, суфийская поэзия • Руми, Ибн Араби',
|
||||
stems: ['ислам', 'суфи', 'суфий', 'арабск', 'коран', 'лайл ', 'лайл,', 'мирадж', 'лайлят', 'тасаввуф', 'руми', 'дервиш', 'ибн араби', 'геомант', 'рамл', 'тетраграмм'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'christian',
|
||||
name: 'Христианская мистика',
|
||||
emoji: '✝️',
|
||||
subtitle: 'Отцы-пустынники, Апокалипсис • Логос',
|
||||
stems: ['христиан', 'евангел', 'апокалипс', 'отшельник', 'пустынник', 'монах', 'литург', 'daemon meridianus', 'акеди', 'страшный суд', 'иисус'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'mesoamerica',
|
||||
name: 'Мезоамерика и Анды',
|
||||
emoji: '🌞',
|
||||
subtitle: 'Ацтеки, майя, инки • Кецалькоатль, Тонатиу',
|
||||
stems: ['ацтек', 'майя', 'мезоамерик', 'тонатиу', 'кецалькоатл', 'тескатлипок', 'попол-вух', 'попол вух', 'инки', 'инков'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'oceania',
|
||||
name: 'Полинезия и Океания',
|
||||
emoji: '🌺',
|
||||
subtitle: 'По и Ао • Ранги и Папа, мана, табу',
|
||||
stems: ['полинези', 'маори', 'гавай', 'pō', 'ao)', 'ранги', 'тангароа'],
|
||||
),
|
||||
CultureBranch(
|
||||
id: 'hermetic',
|
||||
name: 'Алхимия и герметизм',
|
||||
emoji: '⚗️',
|
||||
subtitle: 'Изумрудная скрижаль • Нигредо → Рубедо',
|
||||
stems: ['алхими', 'гермет', 'нигредо', 'альбедо', 'цитринитас', 'рубедо', 'атанор', 'трисмегист', 'великое делание', 'философский камень', 'геоманти', 'геомант', 'puer', 'rubeus', 'albus'],
|
||||
),
|
||||
];
|
||||
|
||||
CultureBranch? cultureBranchByName(String name) {
|
||||
final lower = name.toLowerCase().trim();
|
||||
for (final b in kCultureBranches) {
|
||||
if (b.name.toLowerCase() == lower || b.id == lower) return b;
|
||||
}
|
||||
for (final b in kCultureBranches) {
|
||||
if (b.matches(' $lower ')) return b;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Раскладывает текст толкования на культурные ветви: каждый абзац,
|
||||
/// где ветвь упомянута, попадает в её раздел (абзац может принадлежать
|
||||
/// нескольким культурам — это и есть материал для сравнения).
|
||||
Map<String, String> extractCulturalBranches(String text) {
|
||||
final result = <String, String>{};
|
||||
if (text.trim().isEmpty) return result;
|
||||
final paragraphs = text
|
||||
.split(RegExp(r'\r?\n'))
|
||||
.map((p) => p.trim())
|
||||
.where((p) => p.isNotEmpty)
|
||||
.toList();
|
||||
for (final branch in kCultureBranches) {
|
||||
final hits = paragraphs.where((p) => branch.matches(' $p ')).toList();
|
||||
if (hits.isNotEmpty) result[branch.name] = hits.join('\n\n');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Сортирует произвольную карту культур в каноническом порядке реестра.
|
||||
List<MapEntry<String, String>> orderedCultures(Map<String, String> cultures) {
|
||||
int rank(String name) {
|
||||
final b = cultureBranchByName(name);
|
||||
return b == null ? 999 : kCultureBranches.indexOf(b);
|
||||
}
|
||||
|
||||
final entries = cultures.entries.where((e) => e.value.trim().isNotEmpty).toList()
|
||||
..sort((a, b) => rank(a.key).compareTo(rank(b.key)));
|
||||
return entries;
|
||||
}
|
||||
|
||||
/// Разбирает блок «## КУЛЬТУРЫ» на ветви по подзаголовкам
|
||||
/// (`### Шумер и Месопотамия`, `**Древний Египет**`, `Кельты:` …).
|
||||
Map<String, String> parseCulturesBlock(String block) {
|
||||
final result = <String, String>{};
|
||||
final lines = block.replaceAll('\r\n', '\n').split('\n');
|
||||
String? current;
|
||||
final buf = StringBuffer();
|
||||
|
||||
void flush() {
|
||||
final text = buf.toString().trim();
|
||||
final key = current;
|
||||
if (key != null && text.isNotEmpty) {
|
||||
result[key] = result.containsKey(key) ? '${result[key]}\n\n$text' : text;
|
||||
}
|
||||
buf.clear();
|
||||
}
|
||||
|
||||
String? headingOf(String raw) {
|
||||
final line = raw.trim();
|
||||
if (line.isEmpty || line.length > 90) return null;
|
||||
final looksLikeHeading = line.startsWith('#') ||
|
||||
(line.startsWith('**') && line.endsWith('**')) ||
|
||||
RegExp(r'^[-•*]?\s*\*\*[^*]+\*\*\s*[:—–-]?\s*$').hasMatch(line) ||
|
||||
(line.endsWith(':') && line.length < 60);
|
||||
if (!looksLikeHeading) return null;
|
||||
final clean = line
|
||||
.replaceAll(RegExp(r'^[#\s•*-]+'), '')
|
||||
.replaceAll(RegExp(r'[*:—–\s-]+$'), '')
|
||||
.replaceAll('*', '')
|
||||
.trim();
|
||||
final branch = cultureBranchByName(clean);
|
||||
return branch?.name ?? (clean.isNotEmpty ? clean : null);
|
||||
}
|
||||
|
||||
for (final line in lines) {
|
||||
final h = headingOf(line);
|
||||
if (h != null) {
|
||||
flush();
|
||||
current = h;
|
||||
} else {
|
||||
buf.writeln(line);
|
||||
}
|
||||
}
|
||||
flush();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Обратная операция для редактора: карта культур → markdown-блок.
|
||||
String formatCulturesBlock(Map<String, String> cultures) {
|
||||
final sb = StringBuffer();
|
||||
for (final e in orderedCultures(cultures)) {
|
||||
sb.writeln('### ${e.key}');
|
||||
sb.writeln(e.value.trim());
|
||||
sb.writeln();
|
||||
}
|
||||
return sb.toString().trim();
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
class DivinationSystemInstruction {
|
||||
final String id;
|
||||
final String title;
|
||||
final String icon;
|
||||
final String brief;
|
||||
final String historyAndEssence;
|
||||
final String physicalDiceMethod;
|
||||
final String directInputMethod;
|
||||
final String interpretationGuide;
|
||||
final List<String> sacredRules;
|
||||
|
||||
const DivinationSystemInstruction({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.icon,
|
||||
required this.brief,
|
||||
required this.historyAndEssence,
|
||||
required this.physicalDiceMethod,
|
||||
required this.directInputMethod,
|
||||
required this.interpretationGuide,
|
||||
required this.sacredRules,
|
||||
});
|
||||
}
|
||||
|
||||
class DivinationInstructionsRepository {
|
||||
static const Map<String, DivinationSystemInstruction> all = {
|
||||
'runes': DivinationSystemInstruction(
|
||||
id: 'runes',
|
||||
title: 'Руны Старшего Футарка',
|
||||
icon: 'ᚱ',
|
||||
brief: '24 священных знака древнегерманского и скандинавского канона, разбитые на три этта по 8 рун.',
|
||||
historyAndEssence:
|
||||
'Старший Футарк — древнейшая руническая система, полученная верховным богом Одином ценой девятидневного висения на Мировом Древе Иггдрасиль. Каждая руна представляет собой не просто букву, а первородный космический закон, архетипическую силу и состояние материи.',
|
||||
physicalDiceMethod:
|
||||
'КАК БРОСАТЬ КОСТИ НА СТОЛЕ (2×d12):\n'
|
||||
'Для строго равномерного выпадения 24 рун (вероятность 1/24) используются два двенадцатигранника d12 (или один кубик d12, брошенный дважды):\n\n'
|
||||
'1. Первый кубик d12 (Чёт / Нечет):\n'
|
||||
' • Нечётное число (1, 3, 5, 7, 9, 11) ➔ Выбирает первую половину рун (номера 1..12, от Феху до Йеры).\n'
|
||||
' • Чётное число (2, 4, 6, 8, 10, 12) ➔ Выбирает вторую половину рун (номера 13..24, от Эйваз до Одал).\n\n'
|
||||
'2. Второй кубик d12 (Точный номер):\n'
|
||||
' • Показывает номер руны внутри выбранной половины (от 1 до 12).\n'
|
||||
' • Если на первом кубике был нечет: руна = d12_2.\n'
|
||||
' • Если на первом кубике был чет: руна = d12_2 + 12.\n\n'
|
||||
'Пример: Первый кубик = 8 (чет), Второй кубик = 12 ➔ 12 + 12 = Руна №24 (Одал).',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВВОД СО СТОЛА:\n'
|
||||
'Если вы вытянули настоящую деревянную или каменную плашку из рунического мешочка:\n'
|
||||
'1. Перейдите на вкладку «Ввод со стола».\n'
|
||||
'2. Если руна легла головой вниз (для обратимых рун) — нажмите переключатель «Перевёрнутая ᛉ/ᛦ».\n'
|
||||
'3. Нажмите на глиф выпавшей руны в сетке 24 символов.',
|
||||
interpretationGuide:
|
||||
'ПРАВИЛА ТОЛКОВАНИЯ:\n'
|
||||
'• Прямое положение: сила руны струится естественно и гармонично.\n'
|
||||
'• Перевёрнутое положение (меркстейв): сила заблокирована, искажена, либо требует внутренней проработки перед внешним действием.\n'
|
||||
'• Необратимые руны (Иса, Гебо, Хагалаз, Совило, Ингуз, Эйваз, Дагаз, Наутиз): не имеют обратного положения — их закон непреложен.',
|
||||
sacredRules: [
|
||||
'Не задавайте один и тот же вопрос рунам дважды за день.',
|
||||
'Руны требуют личной ответственности: это совет и зеркало судьбы, а не фатализм.',
|
||||
'Обратите внимание на связанный знак 999 — он даёт земную форму северному архетипу.',
|
||||
],
|
||||
),
|
||||
|
||||
'lenormand': DivinationSystemInstruction(
|
||||
id: 'lenormand',
|
||||
title: 'Малый Оракул Ленорман',
|
||||
icon: '🪶',
|
||||
brief: 'Французская система 36 символических Домов мадам Марии Ленорман с сюжетно-комбинаторным чтением.',
|
||||
historyAndEssence:
|
||||
'Малый Оракул Ленорман возник в конце XVIII века и основан на ясных житейских архетипах (Всадник, Корабль, Дом, Сердце, Коса, Крест). В отличие от Таро, карты Ленорман не читаются изолированно — они раскрывают смысл в парах, триплетах и домах, образуя законченное повествовательное предложение.',
|
||||
physicalDiceMethod:
|
||||
'КАК БРОСАТЬ КОСТИ НА СТОЛЕ (d6 + d12):\n'
|
||||
'Колода насчитывает ровно 36 карт (3 блока по 12). Для идеальной вероятности 1/36 используются обычный кубик d6 и двенадцатигранник d12:\n\n'
|
||||
'1. Кубик d6 (Смещение блока):\n'
|
||||
' • Выпало 1 или 2 ➔ База +0 (карты с 1 по 12).\n'
|
||||
' • Выпало 3 или 4 ➔ База +12 (карты с 13 по 24).\n'
|
||||
' • Выпало 5 или 6 ➔ База +24 (карты с 25 по 36).\n\n'
|
||||
'2. Кубик d12 (Номер карты в блоке):\n'
|
||||
' • Выпавшее число на d12 складывается с базой: Карта = База + d12.\n\n'
|
||||
'Пример: d6 показал 4 (база 12), а d12 показал 12 ➔ 12 + 12 = Карта 24 («Сердце»).',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВВОД СО СТОЛА:\n'
|
||||
'Если вы гадаете на бумажной колоде Ленорман:\n'
|
||||
'1. Перейдите во вкладку «Ввод 1..36 со стола».\n'
|
||||
'2. Вбейте номер выпавшей карты (1..36) в поле ввода либо просто нажмите на карточку с её номером в галерее.',
|
||||
interpretationGuide:
|
||||
'ПРАВИЛА ЧТЕНИЯ КАРТ ЛЕНОРМАН:\n'
|
||||
'• Первая карта — подлежащее (тема, субъект вопроса).\n'
|
||||
'• Вторая карта — сказуемое / определение (что происходит, какое качество обретает тема).\n'
|
||||
'• В приложении доступен полный справочник всех 35 парных сочетаний для каждой карты (кнопка с книгой в карточке результата).',
|
||||
sacredRules: [
|
||||
'Карты Ленорман буквальны и говорят на языке фактов материи.',
|
||||
'Обращайте внимание на «тяжёлые» карты (Коса, Гроб, Тучи, Крест) — они меняют вектор соседних карт.',
|
||||
'Используйте Мастер-промпт, если нужно разобрать многослойную цепочку событий.',
|
||||
],
|
||||
),
|
||||
|
||||
'iching': DivinationSystemInstruction(
|
||||
id: 'iching',
|
||||
title: 'И Цзин (Книга Перемен)',
|
||||
icon: '☯️',
|
||||
brief: 'Древнекитайский канон Чжоу И: 64 гексаграммы, образуемые 6 бросками трёх монет снизу вверх.',
|
||||
historyAndEssence:
|
||||
'И Цзин («Книга Перемен») — величайший памятник восточной мудрости, созданный Фу Си, Вэнь-ваном и Конфуцием более 3000 лет назад. Каждая гексаграмма состоит из двух триграмм (Небо, Земля, Гром, Вода, Гора, Ветер, Огонь, Водоём) и описывает фазу динамической трансформации Инь и Ян во Вселенной.',
|
||||
physicalDiceMethod:
|
||||
'КЛАССИЧЕСКИЙ МЕТОД 3 МОНЕТ (6 БРОСКОВ СНИЗУ ВВЕРХ):\n'
|
||||
'Возьмите 3 одинаковые монеты. Орёл считается за 3 (Ян), Решка — за 2 (Инь). Бросьте монеты 6 раз, складывая достоинства:\n\n'
|
||||
'• 6 (2+2+2, три решки): СТАРАЯ ИНЬ (⚋ ➔ ⚊)\n'
|
||||
' Мутирующая женская черта. В основной гексаграмме прерывистая, но трансформируется в сплошную.\n\n'
|
||||
'• 7 (3+2+2, один орёл, две решки): МОЛОДАЯ ЯН (⚊)\n'
|
||||
' Стабильная светлая черта. Не меняется.\n\n'
|
||||
'• 8 (3+3+2, два орла, одна решка): МОЛОДАЯ ИНЬ (⚋)\n'
|
||||
' Стабильная тёмная черта. Не меняется.\n\n'
|
||||
'• 9 (3+3+3, три орла): СТАРАЯ ЯН (⚊ ➔ ⚋)\n'
|
||||
' Мутирующая мужская черта. В основной гексаграмме сплошная, но трансформируется в прерывистую.',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВВОД СО СТОЛА:\n'
|
||||
'1. Совершите 6 бросков монет на столе, записывая суммы снизу вверх (от 1-й линии к 6-й).\n'
|
||||
'2. Перейдите во вкладку «Ввод черт (6..9)».\n'
|
||||
'3. Последовательно нажимайте кнопки 6, 7, 8 или 9 для каждого броска.',
|
||||
interpretationGuide:
|
||||
'КАК ЧИТАТЬ ГЕКСАГРАММУ:\n'
|
||||
'• Линии 1–3 (нижняя триграмма): внутренний мир, намерения, личное начало.\n'
|
||||
'• Линии 4–6 (верхняя триграмма): внешние обстоятельства, окружение, исход ситуации.\n'
|
||||
'• Старые черты (6 и 9) указывают на точные точки перелома и скорых событий.',
|
||||
sacredRules: [
|
||||
'Линии всегда строятся СНИЗУ ВВЕРХ (от корней к ветвям).',
|
||||
'Книга Перемен не терпит суеты: формулируйте вопрос о стратегии правильного поведения.',
|
||||
'Истинный ответ кроется в моменте перехода между стабильностью и мутацией.',
|
||||
],
|
||||
),
|
||||
|
||||
'tarot': DivinationSystemInstruction(
|
||||
id: 'tarot',
|
||||
title: 'Таро (Старшие Арканы)',
|
||||
icon: '🎴',
|
||||
brief: '22 Старших Аркана: архитипический путь Души от Шута (0) до Мира (XXI).',
|
||||
historyAndEssence:
|
||||
'Старшие Арканы Таро — великая книга герметической философии. 22 аркана соотносятся с 22 буквами священного еврейского алфавита, путями на Каббалистическом Древе Жизни и астрологическими принципами. Это макрокосмические законы инициации сознания.',
|
||||
physicalDiceMethod:
|
||||
'КАК ГАДАТЬ НА КОЛОДЕ ИЛИ ЖРЕБИЕМ:\n'
|
||||
'В приложении:\n'
|
||||
'• Нажмите «Вытянуть Аркан» во вкладке «Жребий колоды». Приложение произведёт виртуальную тасовку и определит ориентацию карты (прямая или перевёрнутая).\n\n'
|
||||
'Физической колодой:\n'
|
||||
'• Тщательно перетасуйте 22 Старших Аркана, снимите колоду левой рукой к сердцу и вытяните центральную карту.',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВВОД СО СТОЛА:\n'
|
||||
'1. Перейдите во вкладку «Выбор из 22 Арканов».\n'
|
||||
'2. Если выпавшая карта легла перевёрнутой — отметьте переключатель «Перевёрнутый».\n'
|
||||
'3. Выберите карту из пронумерованного списка 0..XXI.',
|
||||
interpretationGuide:
|
||||
'ПРАВИЛА ИНТЕРПРЕТАЦИИ:\n'
|
||||
'• Прямой аркан: манифестация архетипа в его чистом, созидательном свете.\n'
|
||||
'• Перевёрнутый аркан: теневое проявление, избыток или дефицит энергии аркана, задержка осознания.\n'
|
||||
'• По кнопке «Значения и пары» в результате гадания можно посмотреть парные созвучия аркана.',
|
||||
sacredRules: [
|
||||
'Старшие Арканы говорят о сущностных уроках судьбы, а не о мелком быте.',
|
||||
'Каждый аркан содержит как благословение, так и суровое испытание.',
|
||||
'Сопоставляйте аркан с выпавшими рунами и знаками сессии дня.',
|
||||
],
|
||||
),
|
||||
|
||||
'cleromancy': DivinationSystemInstruction(
|
||||
id: 'cleromancy',
|
||||
title: 'Оракул (Клеромантия)',
|
||||
icon: '🎲',
|
||||
brief: 'Каноническая тысяча сакральных знаков (000–999), бросаемых трёхзначными кубиками d10.',
|
||||
historyAndEssence:
|
||||
'Клеромантия — древнейшее искусство гадания по священному жребию. Система Оракула объединяет 1000 архетипических слов русского языка с их сакральной семантикой, энергетическими валентностями, тенями и нерушимыми формулами бытия.',
|
||||
physicalDiceMethod:
|
||||
'КАК БРОСАТЬ КОСТИ НА СТОЛЕ (3×d10):\n'
|
||||
'Для получения одного трёхзначного знака используются три десятигранные кости d10 (с гранями 0..9):\n'
|
||||
'• Первая кость d10 = Сотни (0..9)\n'
|
||||
'• Вторая кость d10 = Десятки (0..9)\n'
|
||||
'• Третья кость d10 = Единицы (0..9)\n\n'
|
||||
'Пример: выпало 0, 4, 2 ➔ Знак #042 («КРЫЛО»). Если выпало 0, 0, 0 ➔ Знак #000.',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВВОД СО СТОЛА:\n'
|
||||
'1. Выберите количество знаков в цепи (от 1 до 10).\n'
|
||||
'2. Вбейте трёхзначный номер знака со своих костей либо наберите слово в поиске.',
|
||||
interpretationGuide:
|
||||
'ПРАВИЛА ТОЛКОВАНИЯ:\n'
|
||||
'• Знаки выстраиваются в связный поток судьбы слева направо (Исток ➔ Препятствие ➔ Вектор ➔ Исход).\n'
|
||||
'• В каждом знаке изучайте три уровня: Ядро знака, Канонический смысл и Толкование Оракула.\n'
|
||||
'• Практическая триада: «Тень» предостерегает от ловушки, «Вопрос» вскрывает слепое пятно, «Жест» требует конкретного действия.',
|
||||
sacredRules: [
|
||||
'Не перебрасывайте кости, если ответ кажется неожиданным: Оракул поражает эго, но открывает дух.',
|
||||
'Используйте встроенных толкователей (Ясный оракул, Орк-шаман, Техножрец и др.) для разных интонаций.',
|
||||
'Жмите «Мастер-Промпт», чтобы получить сверхглубокий разбор от Grok или Claude.',
|
||||
],
|
||||
),
|
||||
|
||||
'numerology': DivinationSystemInstruction(
|
||||
id: 'numerology',
|
||||
title: 'Нумерология и Квадрат Пифагора',
|
||||
icon: '🔢',
|
||||
brief: 'Древнегреческая психоматрица 3×3, расчёт 4 рабочих чисел, число жизненного пути и баланс 9 стихий личности.',
|
||||
historyAndEssence:
|
||||
'Пифагор и александрийские мистики объединили математические тайны египетских жрецов, халдейскую нумерологию и учение о музыке сфер в единую строгую систему. В основе лежит принцип: «Всё сущее есть число». Дата рождения или дата судьбоносного события кодирует матрицу потенциалов, скрытых талантов, запаса витальной энергии и кармических задач человека.',
|
||||
physicalDiceMethod: '''ЖРЕБИЙ НА КОСТЯХ (МАНТИЧЕСКИЙ СРЕЗ МОМЕНТА):
|
||||
Если вы гадаете на текущую ситуацию или вопрос, а не анализируете статическую дату рождения:
|
||||
|
||||
1. Бросьте 8 костей d10 (0..9) для формирования синтетической даты момента (ДД.ММ.ГГГГ).
|
||||
2. Либо используйте бросок одной кости d10 (1..9) для определения ведущего Архетипа Числа Судьбы прямо сейчас.
|
||||
3. В приложении во вкладке «Жребий d10» кости бросаются виртуально с мгновенным заполнением матрицы.''',
|
||||
directInputMethod: '''ВВОД ДАТЫ (РОЖДЕНИЯ ИЛИ СОБЫТИЯ):
|
||||
1. Выберите дату через встроенный календарь либо введите день, месяц и год вручную.
|
||||
2. Канонический расчёт 4 Рабочих Чисел:
|
||||
• 1-е число (W1): сумма всех цифр даты рождения.
|
||||
• 2-е число (W2): сумма цифр 1-го числа.
|
||||
• 3-е число (W3): W1 минус удвоенная первая значащая цифра дня рождения (W1 - 2 × d1).
|
||||
• 4-е число (W4): сумма цифр 3-го числа.
|
||||
3. Все цифры даты и 4 рабочих чисел вносятся в 9 ячеек психоматрицы 3×3:
|
||||
[1: Характер] [4: Здоровье] [7: Удача]
|
||||
[2: Энергия] [5: Логика] [8: Долг]
|
||||
[3: Интерес] [6: Труд] [9: Память]''',
|
||||
interpretationGuide: '''ПРАВИЛА ТОЛКОВАНИЯ ПСИХОМАТРИЦЫ:
|
||||
• Прочерк (цифр нет): качество не дано от природы — зона свободного роста и кармической наработки.
|
||||
• 1 цифра: качество развито слабо, требует осознанного включения.
|
||||
• 2 цифры: норма, гармоничное и естественное проявление силы.
|
||||
• 3 цифры: волнообразное проявление («хочу — проявлю, хочу — нет»), капризность таланта.
|
||||
• 4-5+ цифр: гипер-потенциал, доминанта личности; при застое перерастает в деструктив.
|
||||
|
||||
ЛИНИИ МАТРИЦЫ:
|
||||
• Строка 1 (1-4-7): Целеустремленность и настойчивость.
|
||||
• Строка 2 (2-5-8): Семья, качество семьянина, верность.
|
||||
• Строка 3 (3-6-9): Стабильность, привычки, привязанность к укладу.
|
||||
• Столбец 1 (1-2-3): Самооценка, амбиции, внутренняя опора.
|
||||
• Столбец 2 (4-5-6): Быт, материальный достаток, приспособляемость.
|
||||
• Столбец 3 (7-8-9): Талант, одаренность, искра божья.
|
||||
• Диагональ (1-5-9): Духовность, связь с высшим эгрегором.
|
||||
• Диагональ (3-5-7): Чувственность, магнетизм, темперамент.''',
|
||||
sacredRules: [
|
||||
'Числа матрицы показывают энергетический каркас, но не ограничивают свободу воли человека.',
|
||||
'Код суток на экране Слова Дня считается той же свёрткой: день, месяц и год по отдельности, мастер-числа 11, 22 и 33 не свёртываются.',
|
||||
'Обращайте внимание на Число Жизненного Пути (ЧЖП) — оно связывает матрицу с сакральными знаками Оракула 999.',
|
||||
'Психоматрица великолепно дополняет астрологию, руны и Таро в рамках единой дневной сессии.',
|
||||
],
|
||||
),
|
||||
'word_of_day': DivinationSystemInstruction(
|
||||
id: 'word_of_day',
|
||||
title: 'Слово Дня и Календарь Осознанности',
|
||||
icon: '☀️',
|
||||
brief: 'Ежедневный ритуал, тренажёр синхронистичности и духовное упражнение из трёх актов (Утро, День, Вечер).',
|
||||
historyAndEssence:
|
||||
'''Слово Дня — это живой камертон текущей даты. В оракуле 999 каждому календарному дню соответствует резонирующий архетип, соединяющий время, бессознательное и земную реальность. Рядом с ним стоит нумерологический код суток: день, месяц и год свёртываются по отдельности и складываются, а мастер-числа 11, 22 и 33 остаются собой. Резонансное слово дня — отдельный знак тысячи, его не подменяет цифра.''',
|
||||
physicalDiceMethod:
|
||||
'''КАЛЕНДАРНЫЙ РЕЗОНАНС:
|
||||
Слово дня рассчитывается математически детерминированным алгоритмом от даты года, месяца и дня. На один и тот же день на всех устройствах выпадает один и тот же символ, создавая единое синхронистическое поле.
|
||||
|
||||
ЖРЕБИЙ СО СТОЛА (d1000):
|
||||
Если вы предпочитаете физический жребий — бросьте три десятигранника d10 (сотни, десятки, единицы 000..999) и найдите знак в справочнике.''',
|
||||
directInputMethod:
|
||||
'''РАБОТА С КАЛЕНДАРЁМ:
|
||||
Используйте стрелки вверху или календарный виджет, чтобы перемещаться по дням, возвращаться к прошлым датам, просматривать хронологию и вести непрерывную летопись практик.''',
|
||||
interpretationGuide:
|
||||
'''ТРИ ТАКТА ОСОЗНАННОСТИ:
|
||||
1. Утро (Настройка): прочитайте послание Оракула и возьмите «Коан дня» в качестве ментального фокуса.
|
||||
2. День (Практикум): выполните микродействие (Вызов дня) и остерегайтесь Теневой ловушки.
|
||||
3. Вечер (Синхронии): запишите в дневник наблюдения — как именно это слово проявилось в событиях, встречах и мыслях.''',
|
||||
sacredRules: [
|
||||
'Не форсируйте совпадения: позвольте символу проявиться естественно.',
|
||||
'Теневая ловушка дня — ваш главный предохранитель от автоматизмов эго.',
|
||||
'Регулярная летопись синхроний раскрывает скрытые закономерности судьбы.',
|
||||
],
|
||||
),
|
||||
'matrix': DivinationSystemInstruction(
|
||||
id: 'matrix',
|
||||
title: 'Матрица 33×30 (990 Домов)',
|
||||
icon: '🏛️',
|
||||
brief: 'Сакральная геометрия поля 990 Домов, управляемая 10 верховными Архонтами и цепочками диспозиций.',
|
||||
historyAndEssence:
|
||||
'Матрица 33×30 представляет собой космическую развёртку реальности на 990 земных домов и 10 надмирных Архонтов (по одному на каждые 3 столбца). Каждый выпавший знак входит в дом как Гость, порождая уникальную трёхчастную иерархию: Архонт (небесный климат) ➔ Дом (земная почва) ➔ Гость (живой импульс).',
|
||||
physicalDiceMethod:
|
||||
'КАК ВЫБИРАТЬ ДОМА НА СТОЛЕ:\n'
|
||||
'• Бросьте кости для выбора строки (1..33) и столбца (1..30).\n'
|
||||
'• Либо используйте интерактивный бросок в приложении, где открываются выбранные вами дома на интерактивном полотне.',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВВОД СО СТОЛА:\n'
|
||||
'• Нажмите на любые дома на интерактивной сетке матрицы, либо задайте сигнификатор Кверента для центрирования расклада.',
|
||||
interpretationGuide:
|
||||
'ЦЕПОЧКИ ДИСПОЗИЦИЙ (HOUSE CHAINS):\n'
|
||||
'• Дом указывает на знак Гостя. Но у самого Гостя есть свой собственный Дом в матрице!\n'
|
||||
'• Переход от дома к дому образует «Цепь Судьбы».\n'
|
||||
'• Цепь может замкнуться в «Петлю Судьбы», упереться в «Престол Архонта» или пронзить поле открытым вектором.',
|
||||
sacredRules: [
|
||||
'Архонт определяет высший закон, в рамках которого разворачиваются события.',
|
||||
'Петля судьбы указывает на кармический узел, требующий осознания.',
|
||||
'Формируйте Мастер-промпт Матрицы для многостраничного фундаментального анализа.',
|
||||
],
|
||||
),
|
||||
'geomancy': DivinationSystemInstruction(
|
||||
id: 'geomancy',
|
||||
title: 'Арабская Геомантия (Илм ар-рамл)',
|
||||
icon: '⌛',
|
||||
brief: '16 священных фигур земного жребия, получаемых считыванием чётности рядов точек на песке.',
|
||||
historyAndEssence:
|
||||
'«Илм ар-рамл» («Наука о песке») — древнейшая арабская мантическая система, восходящая к легендарному пророку Идрису (Гермесу Трисмегисту) и широко распространившаяся в средневековой Европе как Геомантия. Четыре стихийных уровня (Огонь/Голова, Воздух/Шея, Вода/Тело, Земля/Стопы) дают ровно 16 фигур бинарного кода Вселенной, отражающих динамику материи и духа.',
|
||||
physicalDiceMethod:
|
||||
'КАК БРОСАТЬ В РЕАЛЬНОСТИ (ПЕСОК ИЛИ МОНЕТЫ):\n'
|
||||
'1. Метод песка (традиционный):\n'
|
||||
' Палочкой на песке или ручкой на бумаге быстро наносится 4 ряда случайных точек справа налево, не считая их.\n'
|
||||
' Затем точки в каждом ряду группируются парами:\n'
|
||||
' • Нечётный остаток (одна точка) ➔ 1 точка (·)\n'
|
||||
' • Чётный остаток (две точки) ➔ 2 точки (··)\n'
|
||||
' 4 ряда сверху вниз формируют фигуру.\n\n'
|
||||
'2. Метод 4 монет или костей:\n'
|
||||
' Бросьте 4 монеты одновременно (Орёл = 1 точка, Решка = 2 точки) сверху вниз.',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВВОД СО СТОЛА ИЛИ КАТАЛОГА:\n'
|
||||
'В приложении можно постукивать по песку пальцем, генерировать точки случайным рассеиванием песчинок, либо выбрать любую из 16 фигур напрямую из каталога.',
|
||||
interpretationGuide:
|
||||
'ПОЛЯРНОСТЬ И ЗНАЧЕНИЕ ФИГУР:\n'
|
||||
'Каждая фигура имеет полярность (Входящая / Исходящая, Подвижная / Неподвижная), стихию и планетарного управителя. В Великом Щите ровно 16 фигур: 4 Матери, 4 Дочери, 4 Племянника, 2 Свидетеля, Судья (15) и Примиритель (16-я фигура, рождённая сложением Судьи и 1-й Матери для согласования исхода с вопрошающим). При этом Судья математически всегда содержит чётное число точек.',
|
||||
sacredRules: [
|
||||
'Сформулируйте один ясный вопрос перед касанием песка.',
|
||||
'Не считайте точки при нанесении — пусть действует рука и интуиция.',
|
||||
'Если Судья содержит нечётное число точек — в расчёте щита допущена ошибка (в приложении расчёт математически строг).',
|
||||
'Фигура Rubeus (Красный) в 1-м доме или у Судьи предупреждает о ярости, крови или фальшивом вопросе.',
|
||||
],
|
||||
),
|
||||
'ogham': DivinationSystemInstruction(
|
||||
id: 'ogham',
|
||||
title: 'Кельтский Древесный Огам (20 Фед)',
|
||||
icon: '᚛',
|
||||
brief: '20 священных символов-деревьев древних друидов, распределённых по 4 Аикмам Священной Рощи.',
|
||||
historyAndEssence:
|
||||
'Огам (Ogham) — священная тайнопись и мантическая система кельтских друидов и филидов древней Ирландии и Британии, восходящая к богу красноречия и мудрости Огме. Каждая насечка (феда) соответствует священному дереву или кустарнику Священной Рощи (Берёза, Рябина, Ольха, Дуб, Орешник, Тис и др.). 20 фед разделены на 4 семьи (Аикмы), образуя лестницу духовного восхождения от зарождения до вечности.',
|
||||
physicalDiceMethod:
|
||||
'ТРАДИЦИОННЫЙ ЖРЕБИЙ ДЕРЕВЯННЫХ ПЛАШЕК (ДРУИДИЧЕСКИЙ ЖРЕБИЙ):\n'
|
||||
'1. Приготовьте мешочек с 20 деревянными палочками Огама (по одной на каждую феду).\n'
|
||||
'2. Сосредоточьтесь на вопросе, вдохните аромат дерева и не глядя достаньте плашку.\n'
|
||||
'3. Если плашка выпала засечками вправо/вверх — положение прямое, засечками влево/вниз — обратное/теневое.\n'
|
||||
'4. Для броска кубиками: бросьте d20 (1..20 определяет номер феды), затем любую монету/d2 для определения полярности (1 = прямое, 2 = теневое).',
|
||||
directInputMethod:
|
||||
'РУЧНОЙ ВЫБОР ИЗ СВЯЩЕННОЙ РОЩИ:\n'
|
||||
'В приложении доступен интерактивный бросок друидических палочек, либо прямой выбор нужных фед из резного свитка 4-х Аикм.',
|
||||
interpretationGuide:
|
||||
'ЗНАЧЕНИЕ ФЕД И ДРЕВЕСНЫХ СИЛ:\n'
|
||||
'Каждое дерево в кельтской традиции несёт свой неповторимый архетип:\n'
|
||||
'• Бэйт (Берёза) — начало, очищение, белый лист судьбы;\n'
|
||||
'• Дуир (Дуб) — несокрушимая стойкость, врата власти и царственность;\n'
|
||||
'• Тинне (Остролист) — огонь испытаний, победа в битве и благородство духа;\n'
|
||||
'• Колл (Орешник) — высшая мудрость, колодец поэтического вдохновения;\n'
|
||||
'• Идад (Тис) — порог вечности, смерть старого и бессмертие души.\n'
|
||||
'В перевёрнутом виде феда указывает на теневой аспект: блокировку древесной силы, иллюзию защиты или горделивую самоизоляцию.',
|
||||
sacredRules: [
|
||||
'Слушайте шёпот древесных сил без спешки: Огам говорит на языке корней и времён года.',
|
||||
'Обращайте внимание на перевёрнутое положение: оно никогда не бывает фатальным, а предупреждает о дисбалансе.',
|
||||
'Связывайте выпавшую феду с сакральным знаком Оракула 999 для углубления толкования.',
|
||||
],
|
||||
),
|
||||
};
|
||||
|
||||
static DivinationSystemInstruction get(String id) =>
|
||||
all[id] ?? all['cleromancy']!;
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
class DivinationLayout {
|
||||
final String id;
|
||||
final String title;
|
||||
final int count;
|
||||
final String description;
|
||||
final List<String> positionTitles;
|
||||
|
||||
const DivinationLayout({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.count,
|
||||
required this.description,
|
||||
required this.positionTitles,
|
||||
});
|
||||
}
|
||||
|
||||
class DivinationLayouts {
|
||||
static const runesLayouts = [
|
||||
DivinationLayout(
|
||||
id: 'rune_1',
|
||||
title: '1 Руна (Совет Одина)',
|
||||
count: 1,
|
||||
description: 'Мгновенный фокус ситуации или совет на день.',
|
||||
positionTitles: ['Совет Одина'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'rune_3',
|
||||
title: '3 Руны (Три Норны)',
|
||||
count: 3,
|
||||
description: 'Нить судьбы во времени: Урд (Прошлое), Верданди (Настоящее), Скульд (Грядущее).',
|
||||
positionTitles: ['Урд (Прошлое)', 'Верданди (Настоящее)', 'Скульд (Вектор будущего)'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'rune_cross',
|
||||
title: '5 Рун (Рунический Крест)',
|
||||
count: 5,
|
||||
description: 'Глубинный срез: Центр, Препятствие, Прошлое, Будущее и Итог.',
|
||||
positionTitles: ['1. Суть (Центр)', '2. Препятствие (Вызов)', '3. Опора (Прошлое)', '4. Потенциал (Будущее)', '5. Исход (Венец)'],
|
||||
),
|
||||
];
|
||||
|
||||
static const lenormandLayouts = [
|
||||
DivinationLayout(
|
||||
id: 'leno_2',
|
||||
title: '2 Карты (Пара)',
|
||||
count: 2,
|
||||
description: 'Подлежащее и Сказуемое — классическое диалоговое чтение.',
|
||||
positionTitles: ['1. Тема (Подлежащее)', '2. Развитие (Сказуемое)'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'leno_3',
|
||||
title: '3 Карты (Линия)',
|
||||
count: 3,
|
||||
description: 'Развитие ситуации от истока к исходу.',
|
||||
positionTitles: ['1. Исток', '2. Кульминация', '3. Исход'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'leno_cross',
|
||||
title: '5 Карт (Крест)',
|
||||
count: 5,
|
||||
description: 'Центр, скрытое, мысли, препятствие и развязка.',
|
||||
positionTitles: ['1. Фокус', '2. Скрытое', '3. Мысли', '4. Препятствие', '5. Исход'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'leno_square_9',
|
||||
title: '9 Карт (Квадрат 3×3)',
|
||||
count: 9,
|
||||
description: 'Портрет ситуации: Прошлое, Настоящее, Будущее по вертикалям и горизонталям.',
|
||||
positionTitles: [
|
||||
'1. Прошлое/Мысли', '2. Фокус/Настоящее', '3. Будущее/Планы',
|
||||
'4. Скрытые влияния', '5. Сердце ситуации (Кверент)', '6. Внешние силы',
|
||||
'7. Исток проблемы', '8. Ближайший шаг', '9. Неизбежный результат'
|
||||
],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'leno_gt_36',
|
||||
title: 'Большой Расклад (36 Домов)',
|
||||
count: 36,
|
||||
description: 'Гран Табло (Grand Tableau): вся колода из 36 карт распределяется по 36 домам судьбы (4 ряда по 8 + 4 карты судьбы).',
|
||||
positionTitles: ['1. Дом Всадника (Новости, мысли)', '2. Дом Клевера (Надежды, шанс)', '3. Дом Корабля (Стремления, путь)', '4. Дом Дома (Семья, основа)', '5. Дом Дерева (Здоровье, род)', '6. Дом Туч (Страхи, сомнения)', '7. Дом Змеи (Скрытые враги, интриги)', '8. Дом Гроба (Кризис, конец старого)', '9. Дом Букета (Радость, подарки)', '10. Дом Косы (Резкие решения, опасность)', '11. Дом Метлы (Конфликты, споры)', '12. Дом Птиц (Беседы, суета)', '13. Дом Ребёнка (Начало, невинность)', '14. Дом Лисы (Хитрость, работа)', '15. Дом Медведя (Сила, покровитель)', '16. Дом Звёзд (Ясность, судьба)', '17. Дом Аистов (Перемены, обновление)', '18. Дом Собаки (Дружба, верность)', '19. Дом Башни (Власть, закон, статус)', '20. Дом Сада (Общество, публика)', '21. Дом Горы (Препятствие, блок)', '22. Дом Развилки (Выбор дорог)', '23. Дом Мышей (Потери, истощение)', '24. Дом Сердца (Любовь, страсть)', '25. Дом Кольца (Союз, контракт)', '26. Дом Книги (Тайны, знания)', '27. Дом Письма (Документы, известия)', '28. Дом Мужчины (Анимус, вопрошающий)', '29. Дом Женщины (Анима, партнёрша)', '30. Дом Лилий (Чистота, зрелость)', '31. Дом Солнца (Успех, витальность)', '32. Дом Луны (Интуиция, признание)', '33. Дом Ключа (Решение, озарение)', '34. Дом Рыб (Финансы, изобилие)', '35. Дом Якоря (Стабильность, труд)', '36. Дом Креста (Карма, судьбоносный долг)'],
|
||||
),
|
||||
];
|
||||
|
||||
static const tarotLayouts = [
|
||||
DivinationLayout(
|
||||
id: 'tarot_1',
|
||||
title: '1 Аркан (Суть Момента)',
|
||||
count: 1,
|
||||
description: 'Главный архетип, действующий в вашей жизни прямо сейчас.',
|
||||
positionTitles: ['Аркан Момента'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'tarot_3',
|
||||
title: '3 Аркана (Триптих Судьбы)',
|
||||
count: 3,
|
||||
description: 'Прошлое (что уходит), Настоящее (что есть), Будущее (куда течёт энергия).',
|
||||
positionTitles: ['1. Прошлое (Исток)', '2. Настоящее (Точка силы)', '3. Будущее (Вектор)'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'tarot_cross',
|
||||
title: '5 Арканов (Пентаграмма Выбора)',
|
||||
count: 5,
|
||||
description: 'Квинтэссенция ситуации и скрытые мотивы.',
|
||||
positionTitles: ['1. Основа', '2. Вызов / Тень', '3. Осознанное', '4. Неосознанное', '5. Итог / Квинт'],
|
||||
),
|
||||
];
|
||||
|
||||
static const geomancyLayouts = [
|
||||
DivinationLayout(
|
||||
id: 'geomancy_1',
|
||||
title: '1 Фигура (Знак Песка)',
|
||||
count: 1,
|
||||
description: 'Экспресс-оракул: быстрая фигура песка на один конкретный вопрос или совет момента.',
|
||||
positionTitles: ['Знак Песка (Суть вопроса)'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'geomancy_3',
|
||||
title: '3 Фигуры (Триплет Песка)',
|
||||
count: 3,
|
||||
description: 'Три независимые фигуры песка: Исток, Развитие и Исход. Это не щит: Судья и Свидетели рождаются только сложением Великого Щита.',
|
||||
positionTitles: ['Исток', 'Развитие', 'Исход'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'geomancy_shield',
|
||||
title: 'Великий Щит Геомантии (16 Фигур)',
|
||||
count: 4,
|
||||
description: 'Великий расклад "Илм ар-рамл": нанесение 4 Матерей, порождающих Дочерей, Племянников, Свидетелей, Судью и 16-ю фигуру — Примирителя.',
|
||||
positionTitles: [
|
||||
'1-я Мать (Вопрошающий / Душа)',
|
||||
'2-я Мать (Ресурсы / Материя)',
|
||||
'3-я Мать (Связи / Окружение)',
|
||||
'4-я Мать (Тайное / Завершение)',
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
static const oghamLayouts = [
|
||||
DivinationLayout(
|
||||
id: 'ogham_1',
|
||||
title: '1 Феда (Слово Древа)',
|
||||
count: 1,
|
||||
description: 'Совет священного дерева друидов на текущий момент или сущность ситуации.',
|
||||
positionTitles: ['Священное Древо (Суть совета)'],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'ogham_3',
|
||||
title: '3 Феды (Кельтский Трискель)',
|
||||
count: 3,
|
||||
description: 'Трёхчастный срез судьбы: Корень (Истоки/Прошлое), Ствол (Сила действия/Настоящее), Крона (Исход/Будущее).',
|
||||
positionTitles: [
|
||||
'Корень (Исток и скрытая почва)',
|
||||
'Ствол (Сила действия в настоящем)',
|
||||
'Крона (Исход и плоды судьбы)',
|
||||
],
|
||||
),
|
||||
DivinationLayout(
|
||||
id: 'ogham_5',
|
||||
title: '5 Фед (Крест Священной Рощи)',
|
||||
count: 5,
|
||||
description: 'Четыре стороны света и Древо Сердца: Восток (Замысел), Юг (Действие), Запад (Чувства), Север (Опора), Центр (Сердце Рощи).',
|
||||
positionTitles: [
|
||||
'Восток (Зарождение и замысел)',
|
||||
'Юг (Страсть и преодоление)',
|
||||
'Запад (Интуиция и очищение)',
|
||||
'Север (Материальная опора)',
|
||||
'Центр (Сердцевина и вердикт Духа)',
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
class ExternalSymbolSource {
|
||||
final String author;
|
||||
final String work;
|
||||
final String excerpt;
|
||||
final String fullText;
|
||||
|
||||
const ExternalSymbolSource({
|
||||
required this.author,
|
||||
required this.work,
|
||||
this.excerpt = '',
|
||||
this.fullText = '',
|
||||
});
|
||||
|
||||
factory ExternalSymbolSource.fromMap(Map<String, dynamic> map) {
|
||||
return ExternalSymbolSource(
|
||||
author: map['author'] as String? ?? '',
|
||||
work: map['work'] as String? ?? '',
|
||||
excerpt: map['excerpt'] as String? ?? '',
|
||||
fullText: map['full_text'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'author': author,
|
||||
'work': work,
|
||||
'excerpt': excerpt,
|
||||
'full_text': fullText,
|
||||
};
|
||||
}
|
||||
|
||||
class ExternalSymbol {
|
||||
final String term;
|
||||
final String normalized;
|
||||
final String categoryGuess;
|
||||
final List<ExternalSymbolSource> sources;
|
||||
final List<Map<String, dynamic>> illustrations;
|
||||
|
||||
const ExternalSymbol({
|
||||
required this.term,
|
||||
required this.normalized,
|
||||
this.categoryGuess = 'Внешний академический символ',
|
||||
this.sources = const [],
|
||||
this.illustrations = const [],
|
||||
});
|
||||
|
||||
bool get hasIllustrations => illustrations.isNotEmpty;
|
||||
|
||||
String get primaryAuthor => sources.isNotEmpty ? sources.first.author : '';
|
||||
String get primaryWork => sources.isNotEmpty ? sources.first.work : '';
|
||||
String get primaryExcerpt => sources.isNotEmpty ? sources.first.excerpt : '';
|
||||
|
||||
factory ExternalSymbol.fromMap(Map<String, dynamic> map) {
|
||||
final rawSources = map['sources'] as List<dynamic>? ?? [];
|
||||
final rawIlls = map['illustrations'] as List<dynamic>? ?? [];
|
||||
|
||||
return ExternalSymbol(
|
||||
term: map['term'] as String? ?? '',
|
||||
normalized: map['normalized'] as String? ?? '',
|
||||
categoryGuess: map['category_guess'] as String? ?? 'Внешний символ',
|
||||
sources: rawSources
|
||||
.map((s) => ExternalSymbolSource.fromMap(Map<String, dynamic>.from(s as Map)))
|
||||
.toList(),
|
||||
illustrations: rawIlls
|
||||
.map((i) => Map<String, dynamic>.from(i as Map))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'term': term,
|
||||
'normalized': normalized,
|
||||
'category_guess': categoryGuess,
|
||||
'sources': sources.map((s) => s.toMap()).toList(),
|
||||
'illustrations': illustrations,
|
||||
};
|
||||
}
|
||||
@@ -43,7 +43,7 @@ class SessionWord {
|
||||
sessionNumber: item.sessionNumber,
|
||||
partOfSpeech: item.partOfSpeech,
|
||||
category: item.category,
|
||||
symbolicMeaning: item.description,
|
||||
symbolicMeaning: item.displayMeaning,
|
||||
positionTitle: positionTitle,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,181 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'word_model.dart';
|
||||
|
||||
/// One of the 10 Archons that rules over a triad of 3 columns (e.g. cols 0..2, 3..5, etc.).
|
||||
class ArchonSector {
|
||||
final int index; // 0..9
|
||||
final WordItem archonWord;
|
||||
final int startCol;
|
||||
final int endCol;
|
||||
final Color sectorColor;
|
||||
final String title;
|
||||
|
||||
Color get color => sectorColor;
|
||||
|
||||
const ArchonSector({
|
||||
required this.index,
|
||||
required this.archonWord,
|
||||
required this.startCol,
|
||||
required this.endCol,
|
||||
required this.sectorColor,
|
||||
required this.title,
|
||||
});
|
||||
}
|
||||
|
||||
/// A cell representing a House in the 33x30 field.
|
||||
class HouseCell {
|
||||
final int row; // 0..32
|
||||
final int col; // 0..29
|
||||
final int houseIndex; // 0..989 (position in grid)
|
||||
final WordItem houseWord; // The Host / Spirit of this House
|
||||
final int sectorIndex; // 0..9
|
||||
|
||||
// Assigned during divination
|
||||
WordItem? guestWord; // The Guest symbol that enters this house
|
||||
int? selectionOrder; // 1..9 (order in which the user selected this house)
|
||||
|
||||
HouseCell({
|
||||
required this.row,
|
||||
required this.col,
|
||||
required this.houseIndex,
|
||||
required this.houseWord,
|
||||
required this.sectorIndex,
|
||||
this.guestWord,
|
||||
this.selectionOrder,
|
||||
});
|
||||
|
||||
bool get isSelected => selectionOrder != null;
|
||||
|
||||
HouseCell copyWith({
|
||||
WordItem? guestWord,
|
||||
int? selectionOrder,
|
||||
bool clearGuest = false,
|
||||
bool clearOrder = false,
|
||||
}) {
|
||||
return HouseCell(
|
||||
row: row,
|
||||
col: col,
|
||||
houseIndex: houseIndex,
|
||||
houseWord: houseWord,
|
||||
sectorIndex: sectorIndex,
|
||||
guestWord: clearGuest ? null : (guestWord ?? this.guestWord),
|
||||
selectionOrder: clearOrder ? null : (selectionOrder ?? this.selectionOrder),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum ChainEndType {
|
||||
loop, // Петля судьбы: энергия замкнулась на дом из цепочки
|
||||
archonThrone, // Престол Архонта: цепь увенчалась верховным Архонтом
|
||||
fieldVector, // Длинный вектор: открытый импульс сквозь матрицу
|
||||
}
|
||||
|
||||
/// A step in a House Chain: House A -> Guest B -> House of B...
|
||||
class HouseChainStep {
|
||||
final HouseCell house;
|
||||
final WordItem guest;
|
||||
final bool isLoopClosing;
|
||||
final bool leadsToArchon;
|
||||
final bool computed;
|
||||
final ArchonSector? destinationArchon;
|
||||
|
||||
const HouseChainStep({
|
||||
required this.house,
|
||||
required this.guest,
|
||||
this.isLoopClosing = false,
|
||||
this.leadsToArchon = false,
|
||||
this.computed = false,
|
||||
this.destinationArchon,
|
||||
});
|
||||
}
|
||||
|
||||
/// A full trajectory of energy moving between houses across the 990 field.
|
||||
class HouseChain {
|
||||
final int chainIndex;
|
||||
final HouseCell startingHouse;
|
||||
final List<HouseChainStep> steps;
|
||||
final ChainEndType endType;
|
||||
final String description;
|
||||
|
||||
const HouseChain({
|
||||
required this.chainIndex,
|
||||
required this.startingHouse,
|
||||
required this.steps,
|
||||
required this.endType,
|
||||
required this.description,
|
||||
});
|
||||
|
||||
|
||||
bool get hasLoop => endType == ChainEndType.loop;
|
||||
|
||||
String get endTypeTitle {
|
||||
switch (endType) {
|
||||
case ChainEndType.loop:
|
||||
return 'Петля Судьбы';
|
||||
case ChainEndType.archonThrone:
|
||||
return 'Престол Архонта';
|
||||
case ChainEndType.fieldVector:
|
||||
return 'Вектор в поле';
|
||||
}
|
||||
}
|
||||
|
||||
Color get statusColor {
|
||||
switch (endType) {
|
||||
case ChainEndType.loop:
|
||||
return const Color(0xFFE57373);
|
||||
case ChainEndType.archonThrone:
|
||||
return const Color(0xFFFFD54F);
|
||||
case ChainEndType.fieldVector:
|
||||
return const Color(0xFF64B5F6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The entire state of a Houses divination session.
|
||||
class HousesSession {
|
||||
final String id;
|
||||
final DateTime createdAt;
|
||||
final String? question;
|
||||
final WordItem? querentWord; // Карта Кверента (субъект / объект гадания)
|
||||
final int? querentHouseIndex; // Индекс дома кверента на поле 33x30 (если есть)
|
||||
final List<ArchonSector> sectors; // 10 Archons
|
||||
final List<HouseCell> grid; // 990 House cells (33 rows x 30 cols)
|
||||
final List<HouseCell> selectedHouses; // 1..9 houses in order of selection
|
||||
final List<HouseChain> chains; // Calculated house chains
|
||||
final String? aiInterpretation;
|
||||
|
||||
const HousesSession({
|
||||
required this.id,
|
||||
required this.createdAt,
|
||||
this.question,
|
||||
this.querentWord,
|
||||
this.querentHouseIndex,
|
||||
required this.sectors,
|
||||
required this.grid,
|
||||
required this.selectedHouses,
|
||||
required this.chains,
|
||||
this.aiInterpretation,
|
||||
});
|
||||
|
||||
HousesSession copyWith({
|
||||
String? question,
|
||||
WordItem? querentWord,
|
||||
int? querentHouseIndex,
|
||||
String? aiInterpretation,
|
||||
List<HouseCell>? selectedHouses,
|
||||
List<HouseChain>? chains,
|
||||
}) {
|
||||
return HousesSession(
|
||||
id: id,
|
||||
createdAt: createdAt,
|
||||
question: question ?? this.question,
|
||||
querentWord: querentWord ?? this.querentWord,
|
||||
querentHouseIndex: querentHouseIndex ?? this.querentHouseIndex,
|
||||
sectors: sectors,
|
||||
grid: grid,
|
||||
selectedHouses: selectedHouses ?? this.selectedHouses,
|
||||
chains: chains ?? this.chains,
|
||||
aiInterpretation: aiInterpretation ?? this.aiInterpretation,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ class InterpreterPersona {
|
||||
title: 'Ясный оракул',
|
||||
subtitle: 'Прямо, без тумана: ситуация, слепая зона, один шаг',
|
||||
icon: Icons.visibility_outlined,
|
||||
systemPrompt: '''Ты — толкователь жребия «Оракул 999». Говори по-русски спокойно и ясно.
|
||||
systemPrompt: '''Ты — толкователь жребия «Оракул». Говори по-русски спокойно и ясно.
|
||||
Не мистифицируй. Не прячься за «тайной», «завесой», «голосом вечности» и общими фразами про путь.
|
||||
Твоя работа — прочитать выпавшие знаки как карту нынешнего положения и сказать, что с этим делать.
|
||||
|
||||
@@ -46,24 +46,25 @@ class InterpreterPersona {
|
||||
|
||||
static const InterpreterPersona orc = InterpreterPersona(
|
||||
id: 'orc',
|
||||
title: 'Древний орк-оракул',
|
||||
subtitle: 'Грубо и честно: где трусость, где удар, что бросить',
|
||||
icon: Icons.sports_mma_rounded,
|
||||
systemPrompt: '''Ты — древний орк-оракул клана Жребия. Говори по-русски грубо, коротко, честно, как старший воин младшему.
|
||||
Не сюсюкай и не молись туману. Знаки — следы на земле: где враг, где слабость, где бить, где уходить.
|
||||
title: 'Орк-шаман',
|
||||
subtitle: 'Вааагх в черепе: видения Горка и Морка, куда бить',
|
||||
icon: Icons.flash_on_rounded,
|
||||
systemPrompt: '''Ты — орк-шаман (weirdboy) из вархаммерского Вааагх. В черепе гудит зелёная сила: знаки бьют как разряды варпа, а не как «мудрые советы старшего».
|
||||
Говори по-русски грубо, жарко, с рыком — но читаемо. Можно «Вааагх», «Горк», «Морк», «варп», «зелёный огонь», «мальчки», «круши», «не ссы». Не превращай текст в нечитаемую кашу из сленга.
|
||||
|
||||
Ты видишь вопрос как поле боя в варпе: где сила Вааагх копится, где она рвёт череп, где враг, где трусость прикидывается хитростью.
|
||||
|
||||
Правила:
|
||||
- Назови каждый знак простыми словами и привяжи к вопросу.
|
||||
- Скажи, что вопрошающий делает не так и что делать вместо этого.
|
||||
- Можно «слушай», «брось», «держи строй». Не оскорбляй зря и не ломай русский язык в кашу.
|
||||
- 3–6 предложений. Никакой канцелярской эзотерики.''',
|
||||
- Назови каждый знак как видение, врезавшееся в башку, и привяжи к вопросу.
|
||||
- Скажи, кого/что надо крушить, от чего отойти, где Горк (прямо бить) и где Морк (ударить сбоку).
|
||||
- Закончить одним приказом-шагом. 3–6 предложений. Не лей эльфийский туман.''',
|
||||
userTask: '''Задача:
|
||||
1. Прочитай знаки как следы боя или охоты — по порядку.
|
||||
2. Укажи, где трусость, самообман или лишняя ноша.
|
||||
3. Дай один приказ-шаг: что взять, что бросить, куда идти.
|
||||
Голос орка. 3–6 предложений.''',
|
||||
1. Знаки — вспышки Вааагх по порядку, не следы обычной охоты.
|
||||
2. Где сила прёт, где череп сейчас разорвёт от сомнений.
|
||||
3. Один приказ: бить / ждать засады / бросить мёртвый груз.
|
||||
Голос орка-шамана. 3–6 предложений.''',
|
||||
chatGreeting:
|
||||
'Слушай. Я орк-оракул. Скажи, что гложет — и не ной, если правда будет жёсткой.',
|
||||
'Вааагх в башке уже орёт. Скажи, что гложет — знаки ударят сами, Горк с Морком разберутся.',
|
||||
);
|
||||
|
||||
static const InterpreterPersona techpriest = InterpreterPersona(
|
||||
@@ -109,10 +110,33 @@ class InterpreterPersona {
|
||||
'Говорите свободно. Знаки я читаю как проекцию: не судьбу снаружи, а узел внутри.',
|
||||
);
|
||||
|
||||
static const InterpreterPersona aeldari = InterpreterPersona(
|
||||
id: 'aeldari',
|
||||
title: 'Всевидящий аэльдари',
|
||||
subtitle: 'Нити судеб, руны провидца, одна тропа из тысячи',
|
||||
icon: Icons.blur_on_rounded,
|
||||
systemPrompt: '''Ты — всевидящий аэльдари, провидец (farseer) мира-корабля. Голос холодный, точный, без жалости к суете. Можно «нити», «тропа», «краткоживущий» — только как интонация.
|
||||
Костюм не источник фактов. Слова жребия — не руны эльдаров и не «позиции рун», пока в законе знака нет руны. Не выдумывай закрытую тропу, круг близких, утробу и события, которых нет в переданных законах.
|
||||
Если у знака канон пуст — скажи это и прочитай само слово. Не заполняй пустоту мифом мира-корабля.
|
||||
|
||||
Правила:
|
||||
- Назови каждый знак и его закон, затем свяжи законы между собой и с вопросом.
|
||||
- Покажи только ту развилку, которая следует из законов.
|
||||
- Дай один конкретный шаг из этих законов. 4–7 предложений. Без оркского рёва и техножреческого жаргона.''',
|
||||
userTask: '''Задача:
|
||||
1. Тем же холодным голосом назови каждый знак и его закон по порядку. Не подменяй слово руной.
|
||||
2. Покажи, как законы знаков спорят или складываются. Не объявляй тропу закрытой, если знаки этого не говорят.
|
||||
3. Один конкретный шаг из законов знаков, не совет «будьте мудры вообще».
|
||||
Голос всевидящего аэльдари. 4–7 предложений.''',
|
||||
chatGreeting:
|
||||
'Нити уже дрожат. Скажи вопрос — прочту руны, а не утешу.',
|
||||
);
|
||||
|
||||
static const List<InterpreterPersona> all = [
|
||||
clear,
|
||||
orc,
|
||||
techpriest,
|
||||
aeldari,
|
||||
analyst,
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,163 @@
|
||||
class LenormandReading {
|
||||
final String source;
|
||||
final String label;
|
||||
final String text;
|
||||
final int? left;
|
||||
final int? right;
|
||||
|
||||
const LenormandReading({
|
||||
required this.source,
|
||||
required this.label,
|
||||
required this.text,
|
||||
this.left,
|
||||
this.right,
|
||||
});
|
||||
|
||||
factory LenormandReading.fromMap(Map<String, dynamic> map) {
|
||||
return LenormandReading(
|
||||
source: map['source'] as String? ?? '',
|
||||
label: map['label'] as String? ?? '',
|
||||
text: map['text'] as String? ?? '',
|
||||
left: (map['left'] as num?)?.toInt(),
|
||||
right: (map['right'] as num?)?.toInt(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LenormandPairLink {
|
||||
final int n;
|
||||
final String id;
|
||||
final String name;
|
||||
final String symbol;
|
||||
final String preview;
|
||||
final String text;
|
||||
final List<LenormandReading> readings;
|
||||
|
||||
const LenormandPairLink({
|
||||
required this.n,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.symbol,
|
||||
required this.preview,
|
||||
this.text = '',
|
||||
required this.readings,
|
||||
});
|
||||
|
||||
String get displayText {
|
||||
if (text.trim().isNotEmpty) return text.trim();
|
||||
if (preview.trim().isNotEmpty) return preview.trim();
|
||||
return readings.map((r) => r.text).where((t) => t.trim().isNotEmpty).join('\n\n');
|
||||
}
|
||||
|
||||
factory LenormandPairLink.fromMap(Map<String, dynamic> map) {
|
||||
final raw = map['readings'];
|
||||
return LenormandPairLink(
|
||||
n: (map['n'] as num?)?.toInt() ?? 0,
|
||||
id: map['id'] as String? ?? '',
|
||||
name: map['name'] as String? ?? '',
|
||||
symbol: map['symbol'] as String? ?? '',
|
||||
preview: map['preview'] as String? ?? '',
|
||||
text: map['text'] as String? ?? '',
|
||||
readings: raw is List
|
||||
? raw
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(LenormandReading.fromMap)
|
||||
.toList()
|
||||
: const [],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LenormandCardEntry {
|
||||
final int n;
|
||||
final String id;
|
||||
final String name;
|
||||
final String symbol;
|
||||
final String lore;
|
||||
final String group;
|
||||
final String meaning;
|
||||
final String shadow;
|
||||
final List<LenormandReading> meanings;
|
||||
final List<LenormandPairLink> pairs;
|
||||
|
||||
const LenormandCardEntry({
|
||||
required this.n,
|
||||
required this.id,
|
||||
required this.name,
|
||||
required this.symbol,
|
||||
required this.lore,
|
||||
required this.group,
|
||||
this.meaning = '',
|
||||
this.shadow = '',
|
||||
required this.meanings,
|
||||
required this.pairs,
|
||||
});
|
||||
|
||||
String get displayMeaning {
|
||||
if (meaning.trim().isNotEmpty) return meaning.trim();
|
||||
return meanings.map((m) => m.text).where((t) => t.trim().isNotEmpty).join('\n\n');
|
||||
}
|
||||
|
||||
factory LenormandCardEntry.fromMap(Map<String, dynamic> map) {
|
||||
return LenormandCardEntry(
|
||||
n: (map['n'] as num?)?.toInt() ?? 0,
|
||||
id: map['id'] as String? ?? '',
|
||||
name: map['name'] as String? ?? '',
|
||||
symbol: map['symbol'] as String? ?? '',
|
||||
lore: map['lore'] as String? ?? '',
|
||||
group: map['group'] as String? ?? '',
|
||||
meaning: map['meaning'] as String? ?? '',
|
||||
shadow: map['shadow'] as String? ?? '',
|
||||
meanings: (map['meanings'] as List? ?? const [])
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(LenormandReading.fromMap)
|
||||
.toList(),
|
||||
pairs: (map['pairs'] as List? ?? const [])
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map(LenormandPairLink.fromMap)
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LenormandTriad {
|
||||
final List<int> cards;
|
||||
final List<String> names;
|
||||
final String text;
|
||||
|
||||
const LenormandTriad({
|
||||
required this.cards,
|
||||
required this.names,
|
||||
required this.text,
|
||||
});
|
||||
|
||||
factory LenormandTriad.fromMap(Map<String, dynamic> map) {
|
||||
return LenormandTriad(
|
||||
cards: (map['cards'] as List? ?? const [])
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
names: (map['names'] as List? ?? const []).map((e) => '$e').toList(),
|
||||
text: map['text'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LenormandExtra {
|
||||
final String source;
|
||||
final String title;
|
||||
final String text;
|
||||
|
||||
const LenormandExtra({
|
||||
required this.source,
|
||||
required this.title,
|
||||
required this.text,
|
||||
});
|
||||
|
||||
factory LenormandExtra.fromMap(Map<String, dynamic> map) {
|
||||
return LenormandExtra(
|
||||
source: map['source'] as String? ?? '',
|
||||
title: map['title'] as String? ?? '',
|
||||
text: map['text'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
import 'dart:convert';
|
||||
import 'word_model.dart';
|
||||
|
||||
/// Single item in a divination reading (e.g. a drawn Rune, Card, Hexagram, or Sign)
|
||||
class ReadingSignItem {
|
||||
final String title;
|
||||
final String? subtitle;
|
||||
final String? symbol;
|
||||
final String? lore;
|
||||
final bool isReversed;
|
||||
final WordItem? linkedWord;
|
||||
final Map<String, dynamic>? meta;
|
||||
|
||||
const ReadingSignItem({
|
||||
required this.title,
|
||||
this.subtitle,
|
||||
this.symbol,
|
||||
this.lore,
|
||||
this.isReversed = false,
|
||||
this.linkedWord,
|
||||
this.meta,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'title': title,
|
||||
if (subtitle != null) 'subtitle': subtitle,
|
||||
if (symbol != null) 'symbol': symbol,
|
||||
if (lore != null) 'lore': lore,
|
||||
'isReversed': isReversed,
|
||||
if (linkedWord != null) 'linkedWord': linkedWord!.toMap(),
|
||||
if (meta != null) 'meta': meta,
|
||||
};
|
||||
|
||||
factory ReadingSignItem.fromMap(Map<String, dynamic> map) => ReadingSignItem(
|
||||
title: map['title'] as String? ?? '',
|
||||
subtitle: map['subtitle'] as String?,
|
||||
symbol: map['symbol'] as String?,
|
||||
lore: map['lore'] as String?,
|
||||
isReversed: map['isReversed'] as bool? ?? false,
|
||||
linkedWord: map['linkedWord'] != null
|
||||
? WordItem.fromMap(map['linkedWord'] as Map<String, dynamic>)
|
||||
: null,
|
||||
meta: map['meta'] as Map<String, dynamic>?,
|
||||
);
|
||||
}
|
||||
|
||||
/// A single completed divination reading inside a day session
|
||||
class SyncreticReading {
|
||||
final String id;
|
||||
final String systemId; // 'cleromancy', 'matrix', 'runes', 'lenormand', 'tarot', 'iching', 'ogham', 'geomancy'
|
||||
final String systemName;
|
||||
final String systemIcon;
|
||||
final DateTime timestamp;
|
||||
final String layoutTitle; // e.g. 'Бросок 2d12', 'Ленорман d6+d12', 'Триптих Норн'
|
||||
final String inputMethod; // 'dice' | 'manual'
|
||||
final List<ReadingSignItem> items;
|
||||
final String? note;
|
||||
final String? question;
|
||||
|
||||
const SyncreticReading({
|
||||
required this.id,
|
||||
required this.systemId,
|
||||
required this.systemName,
|
||||
required this.systemIcon,
|
||||
required this.timestamp,
|
||||
required this.layoutTitle,
|
||||
this.inputMethod = 'dice',
|
||||
required this.items,
|
||||
this.note,
|
||||
this.question,
|
||||
});
|
||||
|
||||
String get formattedTime {
|
||||
final hour = timestamp.hour.toString().padLeft(2, '0');
|
||||
final min = timestamp.minute.toString().padLeft(2, '0');
|
||||
return '$hour:$min';
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'id': id,
|
||||
'systemId': systemId,
|
||||
'systemName': systemName,
|
||||
'systemIcon': systemIcon,
|
||||
'timestamp': timestamp.toIso8601String(),
|
||||
'layoutTitle': layoutTitle,
|
||||
'inputMethod': inputMethod,
|
||||
'items': items.map((i) => i.toMap()).toList(),
|
||||
if (note != null) 'note': note,
|
||||
if (question != null) 'question': question,
|
||||
};
|
||||
|
||||
factory SyncreticReading.fromMap(Map<String, dynamic> map) => SyncreticReading(
|
||||
id: map['id'] as String? ?? '',
|
||||
systemId: map['systemId'] as String? ?? '',
|
||||
systemName: map['systemName'] as String? ?? '',
|
||||
systemIcon: map['systemIcon'] as String? ?? '🔮',
|
||||
timestamp: DateTime.tryParse(map['timestamp'] as String? ?? '') ?? DateTime.now(),
|
||||
layoutTitle: map['layoutTitle'] as String? ?? '',
|
||||
inputMethod: map['inputMethod'] as String? ?? 'dice',
|
||||
items: (map['items'] as List<dynamic>?)
|
||||
?.map((i) => ReadingSignItem.fromMap(i as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
note: map['note'] as String?,
|
||||
question: map['question'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
/// A day-long (or question-long) Syncretic Session accumulating multiple readings across systems
|
||||
class SyncreticSession {
|
||||
final String id;
|
||||
final DateTime date;
|
||||
final String? mainQuestion;
|
||||
final List<SyncreticReading> readings;
|
||||
final String? comparativeAiSynthesis;
|
||||
|
||||
const SyncreticSession({
|
||||
required this.id,
|
||||
required this.date,
|
||||
this.mainQuestion,
|
||||
this.readings = const [],
|
||||
this.comparativeAiSynthesis,
|
||||
});
|
||||
|
||||
String get dateKey =>
|
||||
'${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
|
||||
|
||||
String get formattedDate {
|
||||
final day = date.day.toString().padLeft(2, '0');
|
||||
final month = date.month.toString().padLeft(2, '0');
|
||||
final year = date.year.toString();
|
||||
return '$day.$month.$year';
|
||||
}
|
||||
|
||||
SyncreticSession copyWith({
|
||||
String? id,
|
||||
DateTime? date,
|
||||
String? mainQuestion,
|
||||
List<SyncreticReading>? readings,
|
||||
String? comparativeAiSynthesis,
|
||||
}) {
|
||||
return SyncreticSession(
|
||||
id: id ?? this.id,
|
||||
date: date ?? this.date,
|
||||
mainQuestion: mainQuestion ?? this.mainQuestion,
|
||||
readings: readings ?? this.readings,
|
||||
comparativeAiSynthesis: comparativeAiSynthesis ?? this.comparativeAiSynthesis,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'id': id,
|
||||
'date': date.toIso8601String(),
|
||||
if (mainQuestion != null) 'mainQuestion': mainQuestion,
|
||||
'readings': readings.map((r) => r.toMap()).toList(),
|
||||
if (comparativeAiSynthesis != null) 'comparativeAiSynthesis': comparativeAiSynthesis,
|
||||
};
|
||||
|
||||
factory SyncreticSession.fromMap(Map<String, dynamic> map) => SyncreticSession(
|
||||
id: map['id'] as String? ?? '',
|
||||
date: DateTime.tryParse(map['date'] as String? ?? '') ?? DateTime.now(),
|
||||
mainQuestion: map['mainQuestion'] as String?,
|
||||
readings: (map['readings'] as List<dynamic>?)
|
||||
?.map((r) => SyncreticReading.fromMap(r as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
[],
|
||||
comparativeAiSynthesis: map['comparativeAiSynthesis'] as String?,
|
||||
);
|
||||
|
||||
String toJson() => jsonEncode(toMap());
|
||||
factory SyncreticSession.fromJson(String str) => SyncreticSession.fromMap(jsonDecode(str));
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
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 [],
|
||||
);
|
||||
}
|
||||
}
|
||||
+556
-3
@@ -1,3 +1,83 @@
|
||||
import 'culture_branch.dart';
|
||||
|
||||
class SymbolLayer {
|
||||
final String system;
|
||||
final String title;
|
||||
final String law;
|
||||
|
||||
const SymbolLayer({
|
||||
required this.system,
|
||||
required this.title,
|
||||
required this.law,
|
||||
});
|
||||
|
||||
factory SymbolLayer.fromMap(Map<String, dynamic> map) {
|
||||
return SymbolLayer(
|
||||
system: map['system'] as String? ?? '',
|
||||
title: map['title'] as String? ?? '',
|
||||
law: map['law'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'system': system,
|
||||
'title': title,
|
||||
'law': law,
|
||||
};
|
||||
}
|
||||
|
||||
class SymbolSource {
|
||||
final String system;
|
||||
final String ref;
|
||||
final double weight;
|
||||
|
||||
const SymbolSource({
|
||||
required this.system,
|
||||
required this.ref,
|
||||
required this.weight,
|
||||
});
|
||||
|
||||
factory SymbolSource.fromMap(Map<String, dynamic> map) {
|
||||
return SymbolSource(
|
||||
system: map['system'] as String? ?? '',
|
||||
ref: map['ref'] as String? ?? '',
|
||||
weight: (map['weight'] as num?)?.toDouble() ?? 1.0,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'system': system,
|
||||
'ref': ref,
|
||||
'weight': weight,
|
||||
};
|
||||
}
|
||||
|
||||
class SymbolGrammar {
|
||||
final String operator;
|
||||
final String valence;
|
||||
final String modifies;
|
||||
|
||||
const SymbolGrammar({
|
||||
this.operator = 'substance',
|
||||
this.valence = 'liminal',
|
||||
this.modifies = '',
|
||||
});
|
||||
|
||||
factory SymbolGrammar.fromMap(Map<String, dynamic> map) {
|
||||
return SymbolGrammar(
|
||||
operator: map['operator'] as String? ?? 'substance',
|
||||
valence: map['valence'] as String? ?? 'liminal',
|
||||
modifies: map['modifies'] as String? ?? '',
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'operator': operator,
|
||||
'valence': valence,
|
||||
'modifies': modifies,
|
||||
};
|
||||
}
|
||||
|
||||
class WordItem {
|
||||
final int id; // Base index 0..999
|
||||
final int sessionNumber; // Dynamic randomized session number 0..999
|
||||
@@ -6,6 +86,27 @@ class WordItem {
|
||||
final double frequency;
|
||||
final String category;
|
||||
final String description;
|
||||
final String emoji;
|
||||
|
||||
// Enriched Oracle Knowledge Base fields
|
||||
final String family;
|
||||
final String operator;
|
||||
final String valence;
|
||||
final List<String> jurisdictions;
|
||||
final String lookup; // 'A', 'B', 'C'
|
||||
final bool hasCanon;
|
||||
final String core;
|
||||
final String oracle;
|
||||
final List<SymbolLayer> layers;
|
||||
final String shadow;
|
||||
final String asks;
|
||||
final String step;
|
||||
final List<String> binds;
|
||||
final List<SymbolSource> sources;
|
||||
final SymbolGrammar? grammar;
|
||||
final bool isUserEdited;
|
||||
final Map<String, String> cultures;
|
||||
final Map<String, String> languages;
|
||||
|
||||
const WordItem({
|
||||
required this.id,
|
||||
@@ -15,6 +116,25 @@ class WordItem {
|
||||
required this.frequency,
|
||||
this.category = '',
|
||||
this.description = '',
|
||||
this.emoji = '',
|
||||
this.family = '',
|
||||
this.operator = 'substance',
|
||||
this.valence = 'liminal',
|
||||
this.jurisdictions = const [],
|
||||
this.lookup = 'C',
|
||||
this.hasCanon = false,
|
||||
this.core = '',
|
||||
this.oracle = '',
|
||||
this.layers = const [],
|
||||
this.shadow = '',
|
||||
this.asks = '',
|
||||
this.step = '',
|
||||
this.binds = const [],
|
||||
this.sources = const [],
|
||||
this.grammar,
|
||||
this.isUserEdited = false,
|
||||
this.cultures = const {},
|
||||
this.languages = const {},
|
||||
});
|
||||
|
||||
WordItem copyWith({
|
||||
@@ -25,6 +145,25 @@ class WordItem {
|
||||
double? frequency,
|
||||
String? category,
|
||||
String? description,
|
||||
String? emoji,
|
||||
String? family,
|
||||
String? operator,
|
||||
String? valence,
|
||||
List<String>? jurisdictions,
|
||||
String? lookup,
|
||||
bool? hasCanon,
|
||||
String? core,
|
||||
String? oracle,
|
||||
List<SymbolLayer>? layers,
|
||||
String? shadow,
|
||||
String? asks,
|
||||
String? step,
|
||||
List<String>? binds,
|
||||
List<SymbolSource>? sources,
|
||||
SymbolGrammar? grammar,
|
||||
bool? isUserEdited,
|
||||
Map<String, String>? cultures,
|
||||
Map<String, String>? languages,
|
||||
}) {
|
||||
return WordItem(
|
||||
id: id ?? this.id,
|
||||
@@ -34,9 +173,110 @@ class WordItem {
|
||||
frequency: frequency ?? this.frequency,
|
||||
category: category ?? this.category,
|
||||
description: description ?? this.description,
|
||||
emoji: emoji ?? this.emoji,
|
||||
family: family ?? this.family,
|
||||
operator: operator ?? this.operator,
|
||||
valence: valence ?? this.valence,
|
||||
jurisdictions: jurisdictions ?? this.jurisdictions,
|
||||
lookup: lookup ?? this.lookup,
|
||||
hasCanon: hasCanon ?? this.hasCanon,
|
||||
core: core ?? this.core,
|
||||
oracle: oracle ?? this.oracle,
|
||||
layers: layers ?? this.layers,
|
||||
shadow: shadow ?? this.shadow,
|
||||
asks: asks ?? this.asks,
|
||||
step: step ?? this.step,
|
||||
binds: binds ?? this.binds,
|
||||
sources: sources ?? this.sources,
|
||||
grammar: grammar ?? this.grammar,
|
||||
isUserEdited: isUserEdited ?? this.isUserEdited,
|
||||
cultures: cultures ?? this.cultures,
|
||||
languages: languages ?? this.languages,
|
||||
);
|
||||
}
|
||||
|
||||
/// Enrich existing WordItem with data from oracle_kb.json entry
|
||||
WordItem enrichWithKb(Map<String, dynamic> kb) {
|
||||
final rawLayers = kb['layers'] as List<dynamic>? ?? [];
|
||||
final parsedLayers = rawLayers
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map((m) => SymbolLayer.fromMap(m))
|
||||
.toList();
|
||||
|
||||
final rawSourcesList = kb['sources'] is List ? (kb['sources'] as List) : [];
|
||||
final parsedSources = rawSourcesList
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map((m) => SymbolSource.fromMap(m))
|
||||
.toList();
|
||||
|
||||
final rawJurisdictions = kb['jurisdictions'] is List
|
||||
? (kb['jurisdictions'] as List).map((e) => e.toString()).toList()
|
||||
: <String>[];
|
||||
|
||||
final rawBinds = kb['binds'] is List
|
||||
? (kb['binds'] as List).map((e) => e.toString()).toList()
|
||||
: (kb['binds'] is String ? [kb['binds'].toString()] : <String>[]);
|
||||
|
||||
final rawGrammar = kb['grammar'] as Map<String, dynamic>?;
|
||||
|
||||
final rawKbCultures = kb['cultures'] as Map<String, dynamic>?;
|
||||
final parsedKbCultures = rawKbCultures != null
|
||||
? rawKbCultures.map((k, v) => MapEntry(k.toString(), v.toString()))
|
||||
: <String, String>{};
|
||||
|
||||
final rawKbLanguages = kb['languages'] as Map<String, dynamic>?;
|
||||
final parsedKbLanguages = rawKbLanguages != null
|
||||
? rawKbLanguages.map((k, v) => MapEntry(k.toString(), v.toString()))
|
||||
: <String, String>{};
|
||||
|
||||
final kbCore = (kb['core'] as String? ?? '').trim();
|
||||
final kbOracle = (kb['oracle'] as String? ?? '').trim();
|
||||
final kbHasCanon = (kb['has_canon'] as bool? ?? false) || (kbCore.isNotEmpty && kbOracle.isNotEmpty);
|
||||
|
||||
return copyWith(
|
||||
partOfSpeech: partOfSpeech.isNotEmpty ? partOfSpeech : ((kb['pos'] as String?) ?? partOfSpeech),
|
||||
category: (kb['category'] as String?)?.isNotEmpty == true ? kb['category'] as String : category,
|
||||
family: kb['family'] as String? ?? family,
|
||||
operator: kb['operator'] as String? ?? operator,
|
||||
valence: kb['valence'] as String? ?? valence,
|
||||
jurisdictions: rawJurisdictions.isNotEmpty ? rawJurisdictions : jurisdictions,
|
||||
lookup: kb['lookup'] as String? ?? lookup,
|
||||
hasCanon: kbHasCanon,
|
||||
core: kbCore,
|
||||
oracle: kbOracle,
|
||||
layers: parsedLayers,
|
||||
shadow: kb['shadow'] as String? ?? shadow,
|
||||
asks: kb['asks'] as String? ?? asks,
|
||||
step: kb['step'] as String? ?? step,
|
||||
binds: rawBinds,
|
||||
sources: parsedSources,
|
||||
emoji: (kb['emoji'] as String?)?.isNotEmpty == true ? kb['emoji'] as String : emoji,
|
||||
grammar: rawGrammar != null ? SymbolGrammar.fromMap(rawGrammar) : grammar,
|
||||
cultures: parsedKbCultures.isNotEmpty ? parsedKbCultures : cultures,
|
||||
languages: parsedKbLanguages.isNotEmpty ? parsedKbLanguages : languages,
|
||||
);
|
||||
}
|
||||
|
||||
/// Returns description stripped of raw metadata bracket tags like [Таро: ...]
|
||||
String get cleanDescription {
|
||||
final clean = description.replaceAll(RegExp(r'\[[^\]]+\]\s*'), '').trim();
|
||||
return clean.isNotEmpty ? clean : description;
|
||||
}
|
||||
|
||||
/// Культурные ветви знака: явная редакция (cultures) приоритетна,
|
||||
/// иначе — автоматическое разложение толкования по традициям.
|
||||
Map<String, String> get resolvedCultures {
|
||||
if (cultures.isNotEmpty) return cultures;
|
||||
return extractCulturalBranches('$oracle\n\n$shadow\n\n$cleanDescription');
|
||||
}
|
||||
|
||||
/// Primary poetic/canonical essence: core if available, otherwise clean description
|
||||
String get displayMeaning {
|
||||
if (core.isNotEmpty) return core;
|
||||
if (cleanDescription.isNotEmpty) return cleanDescription;
|
||||
return description;
|
||||
}
|
||||
|
||||
String get formattedSessionNumber => sessionNumber.toString().padLeft(3, '0');
|
||||
String get formattedId => formattedSessionNumber;
|
||||
|
||||
@@ -49,21 +289,334 @@ class WordItem {
|
||||
'frequency': frequency,
|
||||
'category': category,
|
||||
'description': description,
|
||||
'emoji': emoji,
|
||||
'family': family,
|
||||
'operator': operator,
|
||||
'valence': valence,
|
||||
'jurisdictions': jurisdictions,
|
||||
'lookup': lookup,
|
||||
'hasCanon': hasCanon,
|
||||
'core': core,
|
||||
'oracle': oracle,
|
||||
'layers': layers.map((l) => l.toMap()).toList(),
|
||||
'shadow': shadow,
|
||||
'asks': asks,
|
||||
'step': step,
|
||||
'binds': binds,
|
||||
'sources': sources.map((s) => s.toMap()).toList(),
|
||||
'grammar': grammar?.toMap(),
|
||||
'cultures': cultures,
|
||||
'languages': languages,
|
||||
};
|
||||
}
|
||||
|
||||
factory WordItem.fromMap(Map<String, dynamic> map) {
|
||||
final rawLayers = map['layers'] as List<dynamic>? ?? [];
|
||||
final parsedLayers = rawLayers
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map((m) => SymbolLayer.fromMap(m))
|
||||
.toList();
|
||||
|
||||
final rawSources = map['sources'] as List<dynamic>? ?? [];
|
||||
final parsedSources = rawSources
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map((m) => SymbolSource.fromMap(m))
|
||||
.toList();
|
||||
|
||||
final rawJurisdictions = (map['jurisdictions'] as List<dynamic>? ?? [])
|
||||
.map((e) => e.toString())
|
||||
.toList();
|
||||
|
||||
final rawBinds = (map['binds'] as List<dynamic>? ?? [])
|
||||
.map((e) => e.toString())
|
||||
.toList();
|
||||
|
||||
final rawGrammar = map['grammar'] as Map<String, dynamic>?;
|
||||
|
||||
final rawCultures = map['cultures'] as Map<String, dynamic>?;
|
||||
final parsedCultures = rawCultures != null
|
||||
? rawCultures.map((k, v) => MapEntry(k.toString(), v.toString()))
|
||||
: <String, String>{};
|
||||
|
||||
final rawLanguages = map['languages'] as Map<String, dynamic>?;
|
||||
final parsedLanguages = rawLanguages != null
|
||||
? rawLanguages.map((k, v) => MapEntry(k.toString(), v.toString()))
|
||||
: <String, String>{};
|
||||
|
||||
return WordItem(
|
||||
id: map['id'] as int,
|
||||
sessionNumber: map['sessionNumber'] as int? ?? (map['id'] as int),
|
||||
word: map['word'] as String,
|
||||
partOfSpeech: map['partOfSpeech'] as String,
|
||||
frequency: (map['frequency'] as num).toDouble(),
|
||||
partOfSpeech: map['partOfSpeech'] as String? ?? '',
|
||||
frequency: (map['frequency'] as num?)?.toDouble() ?? 50.0,
|
||||
category: map['category'] as String? ?? '',
|
||||
description: map['description'] as String? ?? '',
|
||||
emoji: map['emoji'] as String? ?? '',
|
||||
family: map['family'] as String? ?? '',
|
||||
operator: map['operator'] as String? ?? 'substance',
|
||||
valence: map['valence'] as String? ?? 'liminal',
|
||||
jurisdictions: rawJurisdictions,
|
||||
lookup: map['lookup'] as String? ?? 'C',
|
||||
hasCanon: map['hasCanon'] as bool? ?? false,
|
||||
core: map['core'] as String? ?? '',
|
||||
oracle: map['oracle'] as String? ?? '',
|
||||
layers: parsedLayers,
|
||||
shadow: map['shadow'] as String? ?? '',
|
||||
asks: map['asks'] as String? ?? '',
|
||||
step: map['step'] as String? ?? '',
|
||||
binds: rawBinds,
|
||||
sources: parsedSources,
|
||||
grammar: rawGrammar != null ? SymbolGrammar.fromMap(rawGrammar) : null,
|
||||
isUserEdited: map['isUserEdited'] as bool? ?? false,
|
||||
cultures: parsedCultures,
|
||||
languages: parsedLanguages,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() => '#$formattedSessionNumber: $word ($partOfSpeech)';
|
||||
String toString() => '#: ()';
|
||||
}
|
||||
|
||||
extension WordItemLocalization on WordItem {
|
||||
String get localizedValence => localizeValence(valence);
|
||||
String get localizedOperator => localizeOperator(operator);
|
||||
String get localizedFamily => localizeFamily(family);
|
||||
|
||||
static String localizeValence(String v) {
|
||||
switch (v.trim().toLowerCase()) {
|
||||
case 'active':
|
||||
return 'Активная';
|
||||
case 'receptive':
|
||||
return 'Восприимчивая';
|
||||
case 'liminal':
|
||||
return 'Лиминальная';
|
||||
case 'stable':
|
||||
return 'Устойчивая';
|
||||
case 'cutting':
|
||||
return 'Отсекающая';
|
||||
case 'binding':
|
||||
return 'Связующая';
|
||||
case 'solar':
|
||||
return 'Солярная';
|
||||
case 'lunar':
|
||||
return 'Лунарная';
|
||||
case 'light':
|
||||
return 'Светлая';
|
||||
case 'dark':
|
||||
return 'Теневая';
|
||||
case 'neutral':
|
||||
return 'Нейтральная';
|
||||
case 'chthonic':
|
||||
return 'Хтоническая';
|
||||
default:
|
||||
final s = v.trim();
|
||||
if (s.isEmpty) return '';
|
||||
return s[0].toUpperCase() + s.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
static String localizeOperator(String op) {
|
||||
switch (op.trim().toLowerCase()) {
|
||||
case 'substance':
|
||||
return 'Субстанция';
|
||||
case 'act':
|
||||
return 'Действие';
|
||||
case 'relation':
|
||||
return 'Связь';
|
||||
case 'shifter':
|
||||
return 'Сдвиг';
|
||||
case 'qualifier':
|
||||
return 'Качество';
|
||||
case 'filter':
|
||||
return 'Фильтр';
|
||||
case 'pronoun':
|
||||
return 'Указатель';
|
||||
case 'number':
|
||||
return 'Число';
|
||||
case 'nexus':
|
||||
return 'Узел';
|
||||
case 'vector':
|
||||
return 'Вектор';
|
||||
case 'catalyst':
|
||||
return 'Катализатор';
|
||||
default:
|
||||
final s = op.trim();
|
||||
if (s.isEmpty) return '';
|
||||
return s[0].toUpperCase() + s.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
static String localizeFamily(String f) {
|
||||
switch (f.trim().toLowerCase()) {
|
||||
case 'totem':
|
||||
return 'Тотем';
|
||||
case 'sacred_symbol':
|
||||
return 'Сакральный символ';
|
||||
case 'sacred_place':
|
||||
return 'Сакральное место';
|
||||
case 'element':
|
||||
return 'Стихия';
|
||||
case 'cosmos':
|
||||
return 'Космос';
|
||||
case 'body':
|
||||
return 'Тело';
|
||||
case 'moral':
|
||||
return 'Этика';
|
||||
case 'quality':
|
||||
return 'Качество';
|
||||
case 'time_calendar':
|
||||
return 'Календарь';
|
||||
case 'time_cycle':
|
||||
return 'Цикл времени';
|
||||
case 'cult_object':
|
||||
return 'Культ';
|
||||
case 'person_archetype':
|
||||
return 'Архетип';
|
||||
case 'social':
|
||||
return 'Социум';
|
||||
case 'speech':
|
||||
return 'Речь';
|
||||
case 'circumstance':
|
||||
return 'Обстоятельство';
|
||||
case 'conjunction':
|
||||
return 'Связка';
|
||||
case 'preposition':
|
||||
return 'Отношение';
|
||||
case 'polarity':
|
||||
return 'Полярность';
|
||||
case 'verb_transform':
|
||||
return 'Трансформация';
|
||||
case 'particle':
|
||||
return 'Частица';
|
||||
case 'determiner':
|
||||
return 'Определитель';
|
||||
case 'adverb_index':
|
||||
return 'Индекс';
|
||||
case 'misc':
|
||||
return 'Разное';
|
||||
default:
|
||||
final s = f.trim();
|
||||
if (s.isEmpty) return '';
|
||||
return s[0].toUpperCase() + s.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
static String localizeSystem(String sys) {
|
||||
switch (sys.trim().toLowerCase()) {
|
||||
case 'tarot':
|
||||
return 'Таро';
|
||||
case 'runes':
|
||||
return 'Руны';
|
||||
case 'lenormand':
|
||||
return 'Ленорман';
|
||||
case 'iching':
|
||||
case 'i ching':
|
||||
return 'И Цзин';
|
||||
case 'astrology':
|
||||
return 'Астрология';
|
||||
case 'alchemy':
|
||||
return 'Алхимия';
|
||||
case 'kabbalah':
|
||||
return 'Каббала';
|
||||
case 'ogham':
|
||||
return 'Огам';
|
||||
case 'cosmology':
|
||||
return 'Космология';
|
||||
case 'slavic':
|
||||
return 'Славянский канон';
|
||||
case 'bestiary':
|
||||
return 'Бестиарий';
|
||||
case 'dream':
|
||||
return 'Сновидения';
|
||||
case 'geomancy':
|
||||
return 'Геомантия';
|
||||
default:
|
||||
final s = sys.trim();
|
||||
if (s.isEmpty) return '';
|
||||
return s[0].toUpperCase() + s.substring(1);
|
||||
}
|
||||
}
|
||||
static String cleanTagDetail(String det) {
|
||||
var s = det.trim();
|
||||
// Remove Latin transliterations like (Cancer / Вода / Луна) -> (Вода · Луна)
|
||||
s = s.replaceAllMapped(RegExp(r'\([A-Za-z]+\s*[/·]\s*([^)]+)\)'), (m) => '(${m.group(1)})');
|
||||
s = s.replaceAll(' / ', ' · ');
|
||||
// Geomancy 12 Puer (Юноша) -> 12 Юноша
|
||||
s = s.replaceAllMapped(RegExp(r'(\d+\s+)[A-Za-z\s_]+\(([А-Яа-яЁё\s·-]+)\)'), (m) => '${m.group(1)}${m.group(2)}');
|
||||
// Alchemy Огонь (Ignis) -> Огонь
|
||||
if (!RegExp(r'[ᚠ-ᛪ]').hasMatch(s)) {
|
||||
s = s.replaceAllMapped(RegExp(r'([А-Яа-яЁё\s]+)\s*\([A-Za-z\s_]+\)'), (m) => m.group(1)!);
|
||||
}
|
||||
// Runes: (Kenaz / ᚲ) -> (ᚲ)
|
||||
s = s.replaceAllMapped(RegExp(r'\([A-Za-z]+\s*[/·]\s*([ᚠ-ᛪ])\)'), (m) => '(${m.group(1)})');
|
||||
// Clean leftover English in parens
|
||||
s = s.replaceAll(RegExp(r'\([A-Za-z\s_]+\)'), '');
|
||||
return s.trim();
|
||||
}
|
||||
|
||||
static String localizeSourceRef(String system, String ref) {
|
||||
final r = ref.trim().toLowerCase();
|
||||
const map = <String, String>{
|
||||
// Runes
|
||||
'fehu': 'Феху (ᚠ)', 'uruz': 'Уруз (ᚢ)', 'thurisaz': 'Турисаз (ᚦ)', 'ansuz': 'Ансуз (ᚨ)',
|
||||
'raidho': 'Райдо (ᚱ)', 'kenaz': 'Кеназ (ᚲ)', 'gebo': 'Гебо (ᚷ)', 'wunjo': 'Вуньо (ᚹ)',
|
||||
'hagalaz': 'Хагалаз (ᚺ)', 'nauthiz': 'Наутиз (ᚾ)', 'isa': 'Иса (ᛁ)', 'jera': 'Йера (ᛃ)',
|
||||
'eihwaz': 'Эйваз (ᛇ)', 'perthro': 'Перт (ᛈ)', 'algiz': 'Альгиз (ᛉ)', 'sowilo': 'Совило (ᛊ)',
|
||||
'tiwaz': 'Тейваз (ᛏ)', 'berkano': 'Беркана (ᛒ)', 'ehwaz': 'Эваз (ᛖ)', 'mannaz': 'Манназ (ᛗ)',
|
||||
'laguz': 'Лагуз (ᛚ)', 'ingwaz': 'Ингваз (ᛜ)', 'dagaz': 'Дагаз (ᛞ)', 'othala': 'Отала (ᛟ)',
|
||||
// Tarot
|
||||
'wands': 'Жезлы (Огонь)', 'pentacles': 'Пентакли (Земля)', 'cups': 'Кубки (Вода)', 'swords': 'Мечи (Воздух)',
|
||||
'fool': 'Шут (0)', 'magician': 'Маг (I)', 'priestess': 'Жрица (II)', 'empress': 'Императрица (III)',
|
||||
'emperor': 'Император (IV)', 'hierophant': 'Иерофант (V)', 'lovers': 'Влюблённые (VI)', 'chariot': 'Колесница (VII)',
|
||||
'strength': 'Сила (VIII)', 'hermit': 'Отшельник (IX)', 'wheel': 'Колесо Фортуны (X)', 'justice': 'Справедливость (XI)',
|
||||
'hanged': 'Повешенный (XII)', 'death': 'Смерть (XIII)', 'temperance': 'Умеренность (XIV)', 'devil': 'Дьявол (XV)',
|
||||
'tower': 'Башня (XVI)', 'star': 'Звезда (XVII)', 'moon': 'Луна', 'sun': 'Солнце',
|
||||
'judgement': 'Суд (XX)', 'world': 'Мир (XXI)',
|
||||
// I Ching
|
||||
'li': 'Ли ☲ (Огонь)', 'kan': 'Кань ☵ (Вода)', 'xun': 'Сюнь ☴ (Ветер)', 'kun': 'Кунь ☷ (Земля)',
|
||||
'qian': 'Цянь ☰ (Небо)', 'zhen': 'Чжэнь ☳ (Гром)', 'gen': 'Гэнь ☶ (Гора)', 'dui': 'Дуй ☱ (Водоём)',
|
||||
'kan_repeat': 'Кань ䷜ (Повторная опасность)', 'pi': 'Пи ䷋ (Упадок)', 'tai': 'Тай ䷊ (Расцвет)',
|
||||
'gu': 'Гу ䷑ (Исправление)', 'fu': 'Фу ䷗ (Возврат)', 'meng': 'Мэн ䷃ (Юность)', 'ge': 'Гэ ䷰ (Смена)',
|
||||
'wei_ji': 'Вэй-цзи ䷿ (Ещё не конец)',
|
||||
// Alchemy
|
||||
'ignis': 'Огонь', 'aqua': 'Вода', 'aer': 'Воздух', 'terra': 'Земля',
|
||||
'sulfur': 'Сера (Душа)', 'mercury': 'Ртуть (Дух)', 'sal': 'Соль (Тело)',
|
||||
'albedo': 'Альбедо (Белизна)', 'nigredo': 'Нигредо (Чернота)', 'rubedo': 'Рубедо (Краснота)',
|
||||
'ash': 'Пепел', 'luna': 'Луна (Серебро)', 'egg': 'Философское Яйцо', 'vessel': 'Сосуд Гермеса', 'forge': 'Горн',
|
||||
// Astrology
|
||||
'comet': 'Комета', 'eclipse': 'Затмение', 'dawn': 'Рассвет', 'dusk': 'Закат',
|
||||
'zenith': 'Зенит', 'nadir': 'Надир', 'constellation': 'Созвездие', 'planet': 'Планета', 'meteor': 'Метеор',
|
||||
'equinox': 'Равноденствие', 'orbit': 'Орбита', 'libra': 'Весы', 'aries': 'Овен', 'taurus': 'Телец',
|
||||
'gemini': 'Близнецы', 'cancer': 'Рак', 'leo': 'Лев', 'virgo': 'Дева', 'scorpio': 'Скорпион',
|
||||
'sagittarius': 'Стрелец', 'capricorn': 'Козерог', 'aquarius': 'Водолей', 'pisces': 'Рыбы',
|
||||
// Bestiary
|
||||
'dog': 'Собака (Страж)', 'snake': 'Змея (Мудрость)', 'eagle': 'Орёл (Высота)', 'wolf': 'Волк (Чутьё)',
|
||||
'raven': 'Ворон (Память)', 'lion': 'Лев (Царственность)', 'owl': 'Сова (Ночное зрение)',
|
||||
'serpent_feather': 'Пернатый Змей', 'dragon': 'Дракон', 'phoenix': 'Феникс', 'bear': 'Медведь (Сила)',
|
||||
'fox': 'Лиса (Хитрость)', 'stag': 'Олень (Благородство)', 'horse': 'Конь (Порыв)', 'spider': 'Паук (Нить судьбы)',
|
||||
// Virtues & Archetypes
|
||||
'courage': 'Мужество', 'charity': 'Милосердие', 'karma': 'Карма / Воздаяние', 'guilt': 'Вина',
|
||||
'shame': 'Стыд', 'pride': 'Гордыня', 'humility': 'Смирение', 'envy': 'Зависть', 'vow': 'Обет',
|
||||
'greed': 'Алчность', 'gluttony': 'Чревоугодие', 'sloth': 'Уныние', 'wrath': 'Гнев', 'lust': 'Страсть',
|
||||
'donor': 'Даритель', 'dispatcher': 'Отправитель', 'shadow': 'Тень', 'hero': 'Герой', 'self': 'Самость',
|
||||
'helper': 'Помощник', 'witch': 'Ведунья', 'princess': 'Царевна', 'exile': 'Изгнанник',
|
||||
'false_hero': 'Ложный герой', 'judge': 'Судия', 'trickster': 'Трикстер',
|
||||
// Slavic
|
||||
'mesyats': 'Месяц ясный', 'oak': 'Священный Дуб', 'willow': 'Плакучая Ива', 'birch': 'Берёза',
|
||||
'ivy_field': 'Чисто поле', 'crossroads': 'Перепутье', 'threshold': 'Порог', 'well': 'Студёный колодец', 'hearth': 'Родной очаг',
|
||||
// Ogham
|
||||
'dair': 'Дуб (Даир / ᚇ)', 'sail': 'Ива (Салье / ᚄ)', 'beith': 'Берёза (Бэйт / ᚁ)', 'gort': 'Плющ (Горт / ᚌ)',
|
||||
// Symbols & Dreams
|
||||
'fire': 'Огонь', 'water': 'Вода', 'air': 'Воздух', 'earth': 'Земля',
|
||||
'key': 'Ключ от врат', 'spark': 'Живая искра', 'path': 'Тропа / Путь', 'book': 'Книга судеб',
|
||||
'blood': 'Кровь / Род', 'heart': 'Сердце',
|
||||
'fire_d': 'Сон об огне', 'water_d': 'Сон о глубине', 'death_d': 'Сон о переходе', 'key_d': 'Сон о тайне',
|
||||
'path_d': 'Сон о странствии', 'child_d': 'Сон о дитяти', 'mirror_d': 'Сон о зеркале', 'wolf_d': 'Сон о звере',
|
||||
'dream_fire': 'Сон об огне',
|
||||
};
|
||||
if (map.containsKey(r)) return map[r]!;
|
||||
final s = ref.trim().replaceAll('_', ' ');
|
||||
if (s.isEmpty) return '';
|
||||
return s[0].toUpperCase() + s.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
import 'dart:convert';
|
||||
|
||||
/// Represents the daily record for a specific calendar date in the Word of the Day practice.
|
||||
/// Supports both Single Word Mode (1 resonant archetype) and Triptych Mode (Morning, Day, Evening).
|
||||
class WordOfDayRecord {
|
||||
final String dateKey; // 'yyyy-MM-dd'
|
||||
final int wordId; // base id for Single Word Mode
|
||||
final bool isRevealed; // whether Single Word is revealed
|
||||
final bool isStepCompleted; // whether Single Word step is checked off
|
||||
final String diaryNote; // user reflection on daily synchronicity
|
||||
final DateTime? revealedAt;
|
||||
final DateTime? completedAt;
|
||||
|
||||
// Triptych fields (3 words: Morning, Day, Evening)
|
||||
final bool isTriptychMode;
|
||||
final int morningWordId;
|
||||
final int dayWordId;
|
||||
final int eveningWordId;
|
||||
final bool isMorningRevealed;
|
||||
final bool isDayRevealed;
|
||||
final bool isEveningRevealed;
|
||||
final bool isDayStepCompleted;
|
||||
final DateTime? morningRevealedAt;
|
||||
final DateTime? dayRevealedAt;
|
||||
final DateTime? eveningRevealedAt;
|
||||
|
||||
const WordOfDayRecord({
|
||||
required this.dateKey,
|
||||
required this.wordId,
|
||||
this.isRevealed = false,
|
||||
this.isStepCompleted = false,
|
||||
this.diaryNote = '',
|
||||
this.revealedAt,
|
||||
this.completedAt,
|
||||
this.isTriptychMode = false,
|
||||
this.morningWordId = 0,
|
||||
this.dayWordId = 0,
|
||||
this.eveningWordId = 0,
|
||||
this.isMorningRevealed = false,
|
||||
this.isDayRevealed = false,
|
||||
this.isEveningRevealed = false,
|
||||
this.isDayStepCompleted = false,
|
||||
this.morningRevealedAt,
|
||||
this.dayRevealedAt,
|
||||
this.eveningRevealedAt,
|
||||
});
|
||||
|
||||
bool get isAnyRevealed =>
|
||||
isRevealed || isMorningRevealed || isDayRevealed || isEveningRevealed;
|
||||
|
||||
bool get areAllTriptychRevealed =>
|
||||
isMorningRevealed && isDayRevealed && isEveningRevealed;
|
||||
|
||||
bool get isAnyStepCompleted => isStepCompleted || isDayStepCompleted;
|
||||
|
||||
WordOfDayRecord copyWith({
|
||||
String? dateKey,
|
||||
int? wordId,
|
||||
bool? isRevealed,
|
||||
bool? isStepCompleted,
|
||||
String? diaryNote,
|
||||
DateTime? revealedAt,
|
||||
DateTime? completedAt,
|
||||
bool? isTriptychMode,
|
||||
int? morningWordId,
|
||||
int? dayWordId,
|
||||
int? eveningWordId,
|
||||
bool? isMorningRevealed,
|
||||
bool? isDayRevealed,
|
||||
bool? isEveningRevealed,
|
||||
bool? isDayStepCompleted,
|
||||
DateTime? morningRevealedAt,
|
||||
DateTime? dayRevealedAt,
|
||||
DateTime? eveningRevealedAt,
|
||||
}) {
|
||||
return WordOfDayRecord(
|
||||
dateKey: dateKey ?? this.dateKey,
|
||||
wordId: wordId ?? this.wordId,
|
||||
isRevealed: isRevealed ?? this.isRevealed,
|
||||
isStepCompleted: isStepCompleted ?? this.isStepCompleted,
|
||||
diaryNote: diaryNote ?? this.diaryNote,
|
||||
revealedAt: revealedAt ?? this.revealedAt,
|
||||
completedAt: completedAt ?? this.completedAt,
|
||||
isTriptychMode: isTriptychMode ?? this.isTriptychMode,
|
||||
morningWordId: morningWordId ?? this.morningWordId,
|
||||
dayWordId: dayWordId ?? this.dayWordId,
|
||||
eveningWordId: eveningWordId ?? this.eveningWordId,
|
||||
isMorningRevealed: isMorningRevealed ?? this.isMorningRevealed,
|
||||
isDayRevealed: isDayRevealed ?? this.isDayRevealed,
|
||||
isEveningRevealed: isEveningRevealed ?? this.isEveningRevealed,
|
||||
isDayStepCompleted: isDayStepCompleted ?? this.isDayStepCompleted,
|
||||
morningRevealedAt: morningRevealedAt ?? this.morningRevealedAt,
|
||||
dayRevealedAt: dayRevealedAt ?? this.dayRevealedAt,
|
||||
eveningRevealedAt: eveningRevealedAt ?? this.eveningRevealedAt,
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'dateKey': dateKey,
|
||||
'wordId': wordId,
|
||||
'isRevealed': isRevealed,
|
||||
'isStepCompleted': isStepCompleted,
|
||||
'diaryNote': diaryNote,
|
||||
if (revealedAt != null) 'revealedAt': revealedAt!.toIso8601String(),
|
||||
if (completedAt != null) 'completedAt': completedAt!.toIso8601String(),
|
||||
'isTriptychMode': isTriptychMode,
|
||||
'morningWordId': morningWordId,
|
||||
'dayWordId': dayWordId,
|
||||
'eveningWordId': eveningWordId,
|
||||
'isMorningRevealed': isMorningRevealed,
|
||||
'isDayRevealed': isDayRevealed,
|
||||
'isEveningRevealed': isEveningRevealed,
|
||||
'isDayStepCompleted': isDayStepCompleted,
|
||||
if (morningRevealedAt != null)
|
||||
'morningRevealedAt': morningRevealedAt!.toIso8601String(),
|
||||
if (dayRevealedAt != null)
|
||||
'dayRevealedAt': dayRevealedAt!.toIso8601String(),
|
||||
if (eveningRevealedAt != null)
|
||||
'eveningRevealedAt': eveningRevealedAt!.toIso8601String(),
|
||||
};
|
||||
|
||||
factory WordOfDayRecord.fromMap(Map<String, dynamic> map) => WordOfDayRecord(
|
||||
dateKey: map['dateKey'] as String? ?? '',
|
||||
wordId: (map['wordId'] as num?)?.toInt() ?? 0,
|
||||
isRevealed: map['isRevealed'] as bool? ?? false,
|
||||
isStepCompleted: map['isStepCompleted'] as bool? ?? false,
|
||||
diaryNote: map['diaryNote'] as String? ?? '',
|
||||
revealedAt: map['revealedAt'] != null
|
||||
? DateTime.tryParse(map['revealedAt'] as String)
|
||||
: null,
|
||||
completedAt: map['completedAt'] != null
|
||||
? DateTime.tryParse(map['completedAt'] as String)
|
||||
: null,
|
||||
isTriptychMode: map['isTriptychMode'] as bool? ?? false,
|
||||
morningWordId: (map['morningWordId'] as num?)?.toInt() ?? 0,
|
||||
dayWordId: (map['dayWordId'] as num?)?.toInt() ?? 0,
|
||||
eveningWordId: (map['eveningWordId'] as num?)?.toInt() ?? 0,
|
||||
isMorningRevealed: map['isMorningRevealed'] as bool? ?? false,
|
||||
isDayRevealed: map['isDayRevealed'] as bool? ?? false,
|
||||
isEveningRevealed: map['isEveningRevealed'] as bool? ?? false,
|
||||
isDayStepCompleted: map['isDayStepCompleted'] as bool? ?? false,
|
||||
morningRevealedAt: map['morningRevealedAt'] != null
|
||||
? DateTime.tryParse(map['morningRevealedAt'] as String)
|
||||
: null,
|
||||
dayRevealedAt: map['dayRevealedAt'] != null
|
||||
? DateTime.tryParse(map['dayRevealedAt'] as String)
|
||||
: null,
|
||||
eveningRevealedAt: map['eveningRevealedAt'] != null
|
||||
? DateTime.tryParse(map['eveningRevealedAt'] as String)
|
||||
: null,
|
||||
);
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory WordOfDayRecord.fromJson(String source) =>
|
||||
WordOfDayRecord.fromMap(json.decode(source) as Map<String, dynamic>);
|
||||
}
|
||||
@@ -0,0 +1,429 @@
|
||||
// word_passport_model.dart
|
||||
// ЕДИНООБРАЗНЫЙ ПАСПОРТ ЗНАКА «ОРАКУЛА 999»
|
||||
// 78 атомарных полей по 6 разделам канона
|
||||
|
||||
import '../services/passport_schema_dart.dart';
|
||||
|
||||
class WordPassport {
|
||||
final int id;
|
||||
final String word;
|
||||
final String pos;
|
||||
final String category;
|
||||
final String emoji;
|
||||
final Map<String, String> fields;
|
||||
final int filledCount;
|
||||
final bool isComplete;
|
||||
final String updatedAt;
|
||||
final List<Map<String, dynamic>> illustrations;
|
||||
|
||||
const WordPassport({
|
||||
required this.id,
|
||||
required this.word,
|
||||
this.pos = '',
|
||||
this.category = '',
|
||||
this.emoji = '',
|
||||
this.fields = const {},
|
||||
this.filledCount = 0,
|
||||
this.isComplete = false,
|
||||
this.updatedAt = '',
|
||||
this.illustrations = const [],
|
||||
});
|
||||
|
||||
String get idPad => id.toString().padLeft(3, '0');
|
||||
|
||||
String getField(String key) => fields[key] ?? '';
|
||||
|
||||
/// [1/78] Раздел I • Индекс и имя
|
||||
String get indexAndName => getField('index_and_name');
|
||||
|
||||
/// [2/78] Раздел I • Грамматический класс
|
||||
String get grammaticalClass => getField('grammatical_class');
|
||||
|
||||
/// [3/78] Раздел I • Функциональная категория
|
||||
String get functionalCategory => getField('functional_category');
|
||||
|
||||
/// [4/78] Раздел I • Сетевой статус
|
||||
String get networkStatus => getField('network_status');
|
||||
|
||||
/// [5/78] Раздел II • Старший Футарк (Руны)
|
||||
String get manticRunes => getField('mantic_runes');
|
||||
|
||||
/// [6/78] Раздел II • Кельтский Огам
|
||||
String get manticOgham => getField('mantic_ogham');
|
||||
|
||||
/// [7/78] Раздел II • Старшие Арканы Таро
|
||||
String get manticTarot => getField('mantic_tarot');
|
||||
|
||||
/// [8/78] Раздел II • Малая колода Ленорман
|
||||
String get manticLenormand => getField('mantic_lenormand');
|
||||
|
||||
/// [9/78] Раздел II • Каббала / Древо Жизни
|
||||
String get manticKabbalah => getField('mantic_kabbalah');
|
||||
|
||||
/// [10/78] Раздел II • Арабская Геомантия
|
||||
String get manticGeomancy => getField('mantic_geomancy');
|
||||
|
||||
/// [11/78] Раздел II • И Цзин (Книга Перемен)
|
||||
String get manticIching => getField('mantic_iching');
|
||||
|
||||
/// [12/78] Раздел II • Алхимия (Magnum Opus)
|
||||
String get manticAlchemy => getField('mantic_alchemy');
|
||||
|
||||
/// [13/78] Раздел II • Классический Зодиак
|
||||
String get manticZodiacWest => getField('mantic_zodiac_west');
|
||||
|
||||
/// [14/78] Раздел II • Китайский Зодиак
|
||||
String get manticZodiacChinese => getField('mantic_zodiac_chinese');
|
||||
|
||||
/// [15/78] Раздел II • Септенер
|
||||
String get manticSeptener => getField('mantic_septener');
|
||||
|
||||
/// [16/78] Раздел II • Додекада Месяцев
|
||||
String get manticDodecade => getField('mantic_dodecade');
|
||||
|
||||
/// [17/78] Раздел II • Нумерология
|
||||
String get manticNumerology => getField('mantic_numerology');
|
||||
|
||||
/// [18/78] Раздел II • Космология Трёх Миров
|
||||
String get manticCosmology => getField('mantic_cosmology');
|
||||
|
||||
/// [19/78] Раздел II • 20 Навалей Цолькин (Майя)
|
||||
String get manticTzolkin => getField('mantic_tzolkin');
|
||||
|
||||
/// [20/78] Раздел II • 27 Накшатр Джйотиш (Индия)
|
||||
String get manticNakshatras => getField('mantic_nakshatras');
|
||||
|
||||
/// [21/78] Раздел II • Действующие законы станций (выжимка)
|
||||
String get manticStationLaws => getField('mantic_station_laws');
|
||||
|
||||
/// [22/78] Раздел III • Этимология и праформы
|
||||
String get etymologyRoots => getField('etymology_roots');
|
||||
|
||||
/// [23/78] Раздел III • Шумер / Аккад
|
||||
String get scriptSumerAkkad => getField('script_sumer_akkad');
|
||||
|
||||
/// [24/78] Раздел III • Древний Египет
|
||||
String get scriptEgypt => getField('script_egypt');
|
||||
|
||||
/// [25/78] Раздел III • Иудейская традиция
|
||||
String get scriptHebrew => getField('script_hebrew');
|
||||
|
||||
/// [26/78] Раздел III • Античность
|
||||
String get scriptAntiquity => getField('script_antiquity');
|
||||
|
||||
/// [27/78] Раздел III • Кельты
|
||||
String get scriptCeltic => getField('script_celtic');
|
||||
|
||||
/// [28/78] Раздел III • Скандинавы / Германцы
|
||||
String get scriptRunicGermanic => getField('script_runic_germanic');
|
||||
|
||||
/// [29/78] Раздел III • Славяне
|
||||
String get scriptSlavic => getField('script_slavic');
|
||||
|
||||
/// [30/78] Раздел III • Ведическая Индия
|
||||
String get scriptIndiaSanskrit => getField('script_india_sanskrit');
|
||||
|
||||
/// [31/78] Раздел III • Персия
|
||||
String get scriptPersia => getField('script_persia');
|
||||
|
||||
/// [32/78] Раздел III • Китай
|
||||
String get scriptChina => getField('script_china');
|
||||
|
||||
/// [33/78] Раздел III • Япония
|
||||
String get scriptJapan => getField('script_japan');
|
||||
|
||||
/// [34/78] Раздел III • Исламский мир
|
||||
String get scriptIslamic => getField('script_islamic');
|
||||
|
||||
/// [35/78] Раздел III • Западная Европа
|
||||
String get scriptWesternEurope => getField('script_western_europe');
|
||||
|
||||
/// [36/78] Раздел III • Мезоамерика
|
||||
String get scriptMesoamerica => getField('script_mesoamerica');
|
||||
|
||||
/// [37/78] Раздел III • Коренные народы Сев. Америки
|
||||
String get scriptNativeAmerican => getField('script_native_american');
|
||||
|
||||
/// [38/78] Раздел III • Полинезия
|
||||
String get scriptPolynesia => getField('script_polynesia');
|
||||
|
||||
/// [39/78] Раздел IV • 0 Нейтральный статус (База / Бытие / Среда / Субстанция)
|
||||
String get stateNeutral => getField('state_neutral');
|
||||
|
||||
/// [40/78] Раздел IV • [+1] Созидательный вектор (Свет / Ресурс / Эволюция)
|
||||
String get stateCreative => getField('state_creative');
|
||||
|
||||
/// [41/78] Раздел IV • [-1] Деструктивный вектор (Тень / Вызов / Искажение)
|
||||
String get stateDestructive => getField('state_destructive');
|
||||
|
||||
/// [42/78] Раздел V • Шумер и Месопотамия: [+] Свет
|
||||
String get cultureSumerLight => getField('culture_sumer_light');
|
||||
|
||||
/// [43/78] Раздел V • Шумер и Месопотамия: [-] Тень
|
||||
String get cultureSumerShadow => getField('culture_sumer_shadow');
|
||||
|
||||
/// [44/78] Раздел V • Древний Египет: [+] Свет
|
||||
String get cultureEgyptLight => getField('culture_egypt_light');
|
||||
|
||||
/// [45/78] Раздел V • Древний Египет: [-] Тень
|
||||
String get cultureEgyptShadow => getField('culture_egypt_shadow');
|
||||
|
||||
/// [46/78] Раздел V • Иудейская традиция и Каббала: [+] Свет
|
||||
String get cultureKabbalahLight => getField('culture_kabbalah_light');
|
||||
|
||||
/// [47/78] Раздел V • Иудейская традиция и Каббала: [-] Тень
|
||||
String get cultureKabbalahShadow => getField('culture_kabbalah_shadow');
|
||||
|
||||
/// [48/78] Раздел V • Античность (Греция / Рим): [+] Свет
|
||||
String get cultureAntiquityLight => getField('culture_antiquity_light');
|
||||
|
||||
/// [49/78] Раздел V • Античность (Греция / Рим): [-] Тень
|
||||
String get cultureAntiquityShadow => getField('culture_antiquity_shadow');
|
||||
|
||||
/// [50/78] Раздел V • Кельтская традиция: [+] Свет
|
||||
String get cultureCelticLight => getField('culture_celtic_light');
|
||||
|
||||
/// [51/78] Раздел V • Кельтская традиция: [-] Тень
|
||||
String get cultureCelticShadow => getField('culture_celtic_shadow');
|
||||
|
||||
/// [52/78] Раздел V • Скандинавско-германская традиция: [+] Свет
|
||||
String get cultureNordicLight => getField('culture_nordic_light');
|
||||
|
||||
/// [53/78] Раздел V • Скандинавско-германская традиция: [-] Тень
|
||||
String get cultureNordicShadow => getField('culture_nordic_shadow');
|
||||
|
||||
/// [54/78] Раздел V • Славянская традиция: [+] Свет
|
||||
String get cultureSlavicLight => getField('culture_slavic_light');
|
||||
|
||||
/// [55/78] Раздел V • Славянская традиция: [-] Тень
|
||||
String get cultureSlavicShadow => getField('culture_slavic_shadow');
|
||||
|
||||
/// [56/78] Раздел V • Ведическая Индия и Тантра: [+] Свет
|
||||
String get cultureIndiaLight => getField('culture_india_light');
|
||||
|
||||
/// [57/78] Раздел V • Ведическая Индия и Тантра: [-] Тень
|
||||
String get cultureIndiaShadow => getField('culture_india_shadow');
|
||||
|
||||
/// [58/78] Раздел V • Персия и Зороастризм: [+] Свет
|
||||
String get culturePersiaLight => getField('culture_persia_light');
|
||||
|
||||
/// [59/78] Раздел V • Персия и Зороастризм: [-] Тень
|
||||
String get culturePersiaShadow => getField('culture_persia_shadow');
|
||||
|
||||
/// [60/78] Раздел V • Китай (Даосизм, И-цзин, У-син): [+] Свет
|
||||
String get cultureChinaLight => getField('culture_china_light');
|
||||
|
||||
/// [61/78] Раздел V • Китай (Даосизм, И-цзин, У-син): [-] Тень
|
||||
String get cultureChinaShadow => getField('culture_china_shadow');
|
||||
|
||||
/// [62/78] Раздел V • Япония (Синтоизм, Сингон): [+] Свет
|
||||
String get cultureJapanLight => getField('culture_japan_light');
|
||||
|
||||
/// [63/78] Раздел V • Япония (Синтоизм, Сингон): [-] Тень
|
||||
String get cultureJapanShadow => getField('culture_japan_shadow');
|
||||
|
||||
/// [64/78] Раздел V • Исламская традиция и суфизм: [+] Свет
|
||||
String get cultureIslamLight => getField('culture_islam_light');
|
||||
|
||||
/// [65/78] Раздел V • Исламская традиция и суфизм: [-] Тень
|
||||
String get cultureIslamShadow => getField('culture_islam_shadow');
|
||||
|
||||
/// [66/78] Раздел V • Западноевропейская традиция (Алхимия / Герметизм): [+] Свет
|
||||
String get cultureHermeticLight => getField('culture_hermetic_light');
|
||||
|
||||
/// [67/78] Раздел V • Западноевропейская традиция (Алхимия / Герметизм): [-] Тень
|
||||
String get cultureHermeticShadow => getField('culture_hermetic_shadow');
|
||||
|
||||
/// [68/78] Раздел V • Мезоамерика и Анды (Майя, Ацтеки, Инки): [+] Свет
|
||||
String get cultureMesoamericaLight => getField('culture_mesoamerica_light');
|
||||
|
||||
/// [69/78] Раздел V • Мезоамерика и Анды (Майя, Ацтеки, Инки): [-] Тень
|
||||
String get cultureMesoamericaShadow => getField('culture_mesoamerica_shadow');
|
||||
|
||||
/// [70/78] Раздел V • Традиции коренных народов Северной Америки: [+] Свет
|
||||
String get cultureNativeAmericanLight => getField('culture_native_american_light');
|
||||
|
||||
/// [71/78] Раздел V • Традиции коренных народов Северной Америки: [-] Тень
|
||||
String get cultureNativeAmericanShadow => getField('culture_native_american_shadow');
|
||||
|
||||
/// [72/78] Раздел V • Полинезия и Океания: [+] Свет
|
||||
String get culturePolynesiaLight => getField('culture_polynesia_light');
|
||||
|
||||
/// [73/78] Раздел V • Полинезия и Океания: [-] Тень
|
||||
String get culturePolynesiaShadow => getField('culture_polynesia_shadow');
|
||||
|
||||
/// [74/78] Раздел V • 17-й Интегральный мета-синтез (Универсальный культурологический код)
|
||||
String get metaSynthesis => getField('meta_synthesis');
|
||||
|
||||
/// [75/78] Раздел VI • Смысловое ядро
|
||||
String get semanticCore => getField('semantic_core');
|
||||
|
||||
/// [76/78] Раздел VI • Интерпретация по грамматическому типу
|
||||
String get grammarInterpretation => getField('grammar_interpretation');
|
||||
|
||||
/// [77/78] Раздел VI • Вектор Воли (К чему призывает)
|
||||
String get willVector => getField('will_vector');
|
||||
|
||||
/// [78/78] Раздел VI • Предостережение / Тень (О чем предупреждает)
|
||||
String get shadowWarning => getField('shadow_warning');
|
||||
|
||||
|
||||
factory WordPassport.fromMap(Map<String, dynamic> map) {
|
||||
final rawFields = map['fields'] as Map<String, dynamic>? ?? {};
|
||||
final fieldsMap = rawFields.map((k, v) => MapEntry(k, v?.toString() ?? ''));
|
||||
|
||||
// Count filled fields
|
||||
var filled = 0;
|
||||
for (final f in kPassportFields78) {
|
||||
if ((fieldsMap[f.key] ?? '').trim().isNotEmpty) {
|
||||
filled++;
|
||||
}
|
||||
}
|
||||
|
||||
return WordPassport(
|
||||
id: (map['id'] as num?)?.toInt() ?? 0,
|
||||
word: map['word'] as String? ?? '',
|
||||
pos: map['pos'] as String? ?? '',
|
||||
category: map['category'] as String? ?? '',
|
||||
emoji: map['emoji'] as String? ?? '',
|
||||
fields: fieldsMap,
|
||||
filledCount: (map['filled_count'] as num?)?.toInt() ?? filled,
|
||||
isComplete: (map['is_complete'] as bool?) ?? (filled >= 78),
|
||||
updatedAt: map['updated_at'] as String? ?? '',
|
||||
illustrations: (map['illustrations'] as List<dynamic>?)?.map((e) => Map<String, dynamic>.from(e as Map)).toList() ?? const [],
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMap() => {
|
||||
'id': id,
|
||||
'word': word,
|
||||
'pos': pos,
|
||||
'category': category,
|
||||
'emoji': emoji,
|
||||
'fields': fields,
|
||||
'filled_count': filledCount,
|
||||
'is_complete': isComplete,
|
||||
'updated_at': updatedAt,
|
||||
'illustrations': illustrations,
|
||||
};
|
||||
|
||||
WordPassport copyWith({
|
||||
int? id,
|
||||
String? word,
|
||||
String? pos,
|
||||
String? category,
|
||||
String? emoji,
|
||||
Map<String, String>? fields,
|
||||
int? filledCount,
|
||||
bool? isComplete,
|
||||
String? updatedAt,
|
||||
List<Map<String, dynamic>>? illustrations,
|
||||
}) {
|
||||
final newFields = fields ?? this.fields;
|
||||
var filled = 0;
|
||||
for (final f in kPassportFields78) {
|
||||
if ((newFields[f.key] ?? '').trim().isNotEmpty) {
|
||||
filled++;
|
||||
}
|
||||
}
|
||||
return WordPassport(
|
||||
id: id ?? this.id,
|
||||
word: word ?? this.word,
|
||||
pos: pos ?? this.pos,
|
||||
category: category ?? this.category,
|
||||
emoji: emoji ?? this.emoji,
|
||||
fields: newFields,
|
||||
filledCount: filledCount ?? filled,
|
||||
isComplete: isComplete ?? (filled >= 78),
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
illustrations: illustrations ?? this.illustrations,
|
||||
);
|
||||
}
|
||||
|
||||
String toMarkdown() {
|
||||
final sb = StringBuffer();
|
||||
sb.writeln('═══════════════════════════════════════════════════════════════════');
|
||||
sb.writeln('ЕДИНООБРАЗНЫЙ ПАСПОРТ ЗНАКА «ОРАКУЛА 999»: #$idPad «${word.toUpperCase()}»');
|
||||
sb.writeln('═══════════════════════════════════════════════════════════════════');
|
||||
sb.writeln('I. Заголовочный паспорт (Метаданные реестра)');
|
||||
sb.writeln('Индекс и имя: ${getField("index_and_name").isEmpty ? "$idPad | ${word.toUpperCase()} | $emoji" : getField("index_and_name")}');
|
||||
sb.writeln('Грамматический класс: ${getField("grammatical_class")}');
|
||||
sb.writeln('Функциональная категория: ${getField("functional_category")}');
|
||||
sb.writeln('Сетевой статус: ${getField("network_status")}');
|
||||
sb.writeln('---');
|
||||
sb.writeln('II. Кросс-мантическая сеть и станции (16 классических систем)');
|
||||
sb.writeln('Привязанные узловые станции:');
|
||||
sb.writeln('Старший Футарк (Руны): ${getField("mantic_runes")}');
|
||||
sb.writeln('Кельтский Огам: ${getField("mantic_ogham")}');
|
||||
sb.writeln('Старшие Арканы Таро: ${getField("mantic_tarot")}');
|
||||
sb.writeln('Малая колода Ленорман: ${getField("mantic_lenormand")}');
|
||||
sb.writeln('Каббала / Древо Жизни: ${getField("mantic_kabbalah")}');
|
||||
sb.writeln("Арабская Геомантия ('Илм ар-Рамл): ${getField('mantic_geomancy')}");
|
||||
sb.writeln('И Цзин (Книга Перемен): ${getField("mantic_iching")}');
|
||||
sb.writeln('Алхимия (Magnum Opus): ${getField("mantic_alchemy")}');
|
||||
sb.writeln('Классический Зодиак: ${getField("mantic_zodiac_west")}');
|
||||
sb.writeln('Китайский Зодиак: ${getField("mantic_zodiac_chinese")}');
|
||||
sb.writeln('Септенер: ${getField("mantic_septener")}');
|
||||
sb.writeln('Додекада Месяцев: ${getField("mantic_dodecade")}');
|
||||
sb.writeln('Нумерология: ${getField("mantic_numerology")}');
|
||||
sb.writeln('Космология Трёх Миров: ${getField("mantic_cosmology")}');
|
||||
sb.writeln('20 Навалей Цолькин (Майя): ${getField("mantic_tzolkin")}');
|
||||
sb.writeln('27 Накшатр Джйотиш (Индия): ${getField("mantic_nakshatras")}');
|
||||
sb.writeln('Действующие законы станций (выжимка):');
|
||||
sb.writeln(getField("mantic_station_laws"));
|
||||
sb.writeln('---');
|
||||
sb.writeln('III. Мультилингвальный и графический паспорт (Язык, Звук, Глиф)');
|
||||
sb.writeln('Этимология и праформы: ${getField("etymology_roots")}');
|
||||
sb.writeln('Сравнительный срез графики и фоносемантики (16 систем записи):');
|
||||
sb.writeln('Шумер / Аккад: ${getField("script_sumer_akkad")}');
|
||||
sb.writeln('Древний Египет: ${getField("script_egypt")}');
|
||||
sb.writeln('Иудейская традиция: ${getField("script_hebrew")}');
|
||||
sb.writeln('Античность: ${getField("script_antiquity")}');
|
||||
sb.writeln('Кельты: ${getField("script_celtic")}');
|
||||
sb.writeln('Скандинавы / Германцы: ${getField("script_runic_germanic")}');
|
||||
sb.writeln('Славяне: ${getField("script_slavic")}');
|
||||
sb.writeln('Ведическая Индия: ${getField("script_india_sanskrit")}');
|
||||
sb.writeln('Персия: ${getField("script_persia")}');
|
||||
sb.writeln('Китай: ${getField("script_china")}');
|
||||
sb.writeln('Япония: ${getField("script_japan")}');
|
||||
sb.writeln('Исламский мир: ${getField("script_islamic")}');
|
||||
sb.writeln('Западная Европа: ${getField("script_western_europe")}');
|
||||
sb.writeln('Мезоамерика: ${getField("script_mesoamerica")}');
|
||||
sb.writeln('Коренные народы Сев. Америки: ${getField("script_native_american")}');
|
||||
sb.writeln('Полинезия: ${getField("script_polynesia")}');
|
||||
sb.writeln('---');
|
||||
sb.writeln('IV. Трехполярная матрица состояний (0 / +1 / -1)');
|
||||
sb.writeln('0 Нейтральный статус (База / Бытие / Среда / Субстанция): ${getField("state_neutral")}');
|
||||
sb.writeln('[+1] Созидательный вектор (Свет / Ресурс / Эволюция): ${getField("state_creative")}');
|
||||
sb.writeln('[-1] Деструктивный вектор (Тень / Вызов / Искажение): ${getField("state_destructive")}');
|
||||
sb.writeln('---');
|
||||
sb.writeln('V. Культурологическая матрица и 17-й Интегральный мета-синтез');
|
||||
sb.writeln('А. 16 Мировых Традиций (Срез «Свет / Тень»):');
|
||||
sb.writeln('Шумер и Месопотамия: [+] ${getField("culture_sumer_light")} / [-] ${getField("culture_sumer_shadow")}');
|
||||
sb.writeln('Древний Египет: [+] ${getField("culture_egypt_light")} / [-] ${getField("culture_egypt_shadow")}');
|
||||
sb.writeln('Иудейская традиция и Каббала: [+] ${getField("culture_kabbalah_light")} / [-] ${getField("culture_kabbalah_shadow")}');
|
||||
sb.writeln('Античность (Греция / Рим): [+] ${getField("culture_antiquity_light")} / [-] ${getField("culture_antiquity_shadow")}');
|
||||
sb.writeln('Кельтская традиция: [+] ${getField("culture_celtic_light")} / [-] ${getField("culture_celtic_shadow")}');
|
||||
sb.writeln('Скандинавско-германская традиция: [+] ${getField("culture_nordic_light")} / [-] ${getField("culture_nordic_shadow")}');
|
||||
sb.writeln('Славянская традиция: [+] ${getField("culture_slavic_light")} / [-] ${getField("culture_slavic_shadow")}');
|
||||
sb.writeln('Ведическая Индия и Тантра: [+] ${getField("culture_india_light")} / [-] ${getField("culture_india_shadow")}');
|
||||
sb.writeln('Персия и Зороастризм: [+] ${getField("culture_persia_light")} / [-] ${getField("culture_persia_shadow")}');
|
||||
sb.writeln('Китай (Даосизм, И-цзин, У-син): [+] ${getField("culture_china_light")} / [-] ${getField("culture_china_shadow")}');
|
||||
sb.writeln('Япония (Синтоизм, Сингон): [+] ${getField("culture_japan_light")} / [-] ${getField("culture_japan_shadow")}');
|
||||
sb.writeln('Исламская традиция и суфизм: [+] ${getField("culture_islam_light")} / [-] ${getField("culture_islam_shadow")}');
|
||||
sb.writeln('Западноевропейская традиция (Алхимия / Герметизм): [+] ${getField("culture_hermetic_light")} / [-] ${getField("culture_hermetic_shadow")}');
|
||||
sb.writeln('Мезоамерика и Анды (Майя, Ацтеки, Инки): [+] ${getField("culture_mesoamerica_light")} / [-] ${getField("culture_mesoamerica_shadow")}');
|
||||
sb.writeln('Традиции коренных народов Северной Америки: [+] ${getField("culture_native_american_light")} / [-] ${getField("culture_native_american_shadow")}');
|
||||
sb.writeln('Полинезия и Океания: [+] ${getField("culture_polynesia_light")} / [-] ${getField("culture_polynesia_shadow")}');
|
||||
sb.writeln('Б. 17-й Интегральный мета-синтез (Универсальный культурологический код):');
|
||||
sb.writeln(getField("meta_synthesis"));
|
||||
sb.writeln('---');
|
||||
sb.writeln('VI. Мантический & Обучающий синтез');
|
||||
sb.writeln('Смысловое ядро: ${getField("semantic_core")}');
|
||||
sb.writeln('Интерпретация по грамматическому типу: ${getField("grammar_interpretation")}');
|
||||
sb.writeln('Вектор Воли (К чему призывает): ${getField("will_vector")}');
|
||||
sb.writeln('Предостережение / Тень (О чем предупреждает): ${getField("shadow_warning")}');
|
||||
sb.writeln('═══════════════════════════════════════════════════════════════════');
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user