feat: complete academic symbol lexicon heal, 2-column Cooper extraction, and updated assets

This commit is contained in:
2026-10-09 15:26:58 +05:00
parent 7f91366201
commit 0b12e4583b
244 changed files with 611461 additions and 1617 deletions
+120
View File
@@ -0,0 +1,120 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:words999/models/word_model.dart';
import 'package:words999/services/manual_dive.dart';
import 'package:words999/services/words_repository.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
const snake = WordItem(
id: 12,
word: 'змей',
partOfSpeech: 'существительное',
frequency: 1,
category: 'Образ',
core: 'Сброс кожи оставляет старый покров на тропе.',
);
test('role prompts name the sign and stay inside their closed menus', () {
final cultures = cultureRoutePrompt(snake);
expect(cultures, contains('«змей»'));
expect(cultures, contains('Шумер и Месопотамия'));
expect(cultures, contains('Алхимия и герметизм'));
expect(cultures, contains('три названия через запятую'));
final languages = languageRoutePrompt(snake);
expect(languages, contains('санскрит'));
expect(languages, contains('церковнославянский'));
expect(mysticPrompt(snake), contains('Не занимай чужую карту'));
expect(psychoPrompt(snake), contains('не архетип'));
expect(cultureSlicePrompt(snake, 'Древний Китай'), contains('следа нет'));
expect(languageSlicePrompt(snake, 'санскрит'), contains('прямого корня нет'));
expect(traditionSlicePrompt(snake, 'Руны'), contains('Руны'));
});
test('route answers map onto the closed registries', () {
expect(
matchCultureNames('Китай, Египет, выдуманная страна'),
['Древний Китай', 'Древний Египет'],
);
expect(matchLanguageNames('греческий, китайский'), ['древнегреческий', 'древнекитайский']);
});
test('synthesizer JSON fills cultures, a tradition and the core', () {
const raw = '''
```json
{"word":"змей","core":"Кожа сходит кольцом.","oracle":"Старый покров остаётся.","shadow":"Яд в той же коже.","asks":"Какое кольцо уже снято?","step":"Положи кольцо за порог.","binds":["кожа","порог"],"cultures":{"Китай":"Лун отпустил чешую и не стал драконом воды."},"languages":{"санскрит":"прямого корня нет"},"layers":[{"system":"alchemy","title":"Алхимия","law":"Чернота снимает цвет, новое тело его ещё не держит."}]}
```
''';
final draft = parseDiveCanon(raw);
expect(draft, isNotNull);
expect(draft!.core, 'Кожа сходит кольцом.');
expect(draft.cultures, {'Древний Китай': 'Лун отпустил чешую и не стал драконом воды.'});
expect(draft.languages, {'санскрит': 'прямого корня нет'});
expect(draft.layers!.single.system, 'alchemy');
expect(draft.binds, ['кожа', 'порог']);
final prompt = synthesizerPrompt(
word: snake,
reports: const {'mystic': 'закон кожи'},
core: 'Кожа сходит кольцом.',
oracle: '',
shadow: '',
asks: '',
step: '',
binds: '',
cultures: draft.cultures!,
languages: const {},
traditions: const {},
);
expect(prompt, contains('«змей»'));
expect(prompt, contains('закон кожи'));
expect(prompt, contains('Лун отпустил чешую'));
});
test('manual fields survive save, card and import', () async {
SharedPreferences.setMockInitialValues({});
final repo = WordsRepository();
await repo.init(remoteDailyShuffle: false);
await repo.clearAllCustomEdits();
const word = 'змей';
await repo.saveCustomEdit(
word,
core: 'Кожа сходит кольцом.',
oracle: 'Старый покров остаётся на тропе.',
shadow: 'Яд остаётся в снятой коже.',
asks: 'Какое кольцо уже снято?',
step: 'Положи кольцо за порог.',
cultures: const {'Древний Китай': 'Лун отпустил чешую.'},
languages: const {'санскрит': 'прямого корня нет'},
layers: const [
SymbolLayer(system: 'alchemy', title: 'Алхимия', law: 'Чернота снимает цвет.'),
],
binds: const ['кожа'],
reports: const {'mystic': 'закон кожи'},
);
final edited = repo.getWordByName(word)!;
expect(edited.core, 'Кожа сходит кольцом.');
expect(edited.cultures['Древний Китай'], 'Лун отпустил чешую.');
expect(edited.languages['санскрит'], 'прямого корня нет');
expect(edited.layers.any((layer) => layer.system == 'alchemy'), isTrue);
expect(edited.binds, ['кожа']);
expect(repo.customEditOf(word)!['reports']['mystic'], 'закон кожи');
final exported = repo.exportCustomEditsJson();
await repo.clearAllCustomEdits();
expect(repo.getWordByName(word)!.languages, isEmpty);
final count = await repo.importCustomEditsJson(exported);
expect(count, 1);
final again = repo.getWordByName(word)!;
expect(again.cultures['Древний Китай'], 'Лун отпустил чешую.');
expect(again.languages['санскрит'], 'прямого корня нет');
expect(again.layers.any((layer) => layer.law == 'Чернота снимает цвет.'), isTrue);
await repo.clearAllCustomEdits();
});
}