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
+78 -42
View File
@@ -1,3 +1,4 @@
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../models/history_entry_model.dart';
@@ -7,6 +8,7 @@ import '../services/words_repository.dart';
import '../widgets/cleromancy_dialog.dart';
import '../widgets/d10_dice_roller_widget.dart';
import '../widgets/gradient_star_badge.dart';
import '../widgets/interpreter_persona_picker.dart';
import 'session_result_screen.dart';
class HomeSearchScreen extends StatefulWidget {
@@ -183,7 +185,7 @@ class _HomeSearchScreenState extends State<HomeSearchScreen> {
});
}
Future<void> _reshuffleMatrix() async {
Future<void> _rollRandomCleromancy() async {
HapticFeedback.heavyImpact();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
@@ -193,41 +195,67 @@ class _HomeSearchScreenState extends State<HomeSearchScreen> {
SizedBox(width: 10),
Expanded(
child: Text(
'Запрашиваю суточную матрицу у RANDOM.ORG…',
'Бросаю священный жребий (3 × d10)…',
style: TextStyle(fontWeight: FontWeight.w600),
),
),
],
),
duration: Duration(seconds: 2),
duration: Duration(milliseconds: 1000),
behavior: SnackBarBehavior.floating,
),
);
final source = await _repo.reshuffleSessionNumbers();
if (!mounted) return;
_resetSession();
final viaOrg = source == RandomSource.randomOrg;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
const GradientStar(size: 20),
const SizedBox(width: 10),
Expanded(
child: Text(
viaOrg
? 'Матрица #000–#999 на сегодня задана RANDOM.ORG'
: 'RANDOM.ORG недоступен — матрица собрана локально',
style: const TextStyle(fontWeight: FontWeight.w600),
try {
final randomService = TrueRandomService();
final roll = await randomService.take(_wordsCount * 3);
if (!mounted) return;
final newDigits = <String>[];
for (int i = 0; i < _wordsCount; i++) {
final chunk = roll.digits.sublist(i * 3, (i + 1) * 3);
newDigits.add(chunk.join());
}
setState(() {
_wordsDigits = newDigits;
_activeWordIndex = _wordsCount - 1;
});
final viaOrg = roll.source == RandomSource.randomOrg;
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
const GradientStar(size: 20),
const SizedBox(width: 10),
Expanded(
child: Text(
viaOrg
? 'Выпал истинный жребий RANDOM.ORG (3 × d10)'
: 'Выпал криптографический жребий (3 × d10)',
style: const TextStyle(fontWeight: FontWeight.w600),
),
),
),
],
],
),
duration: const Duration(seconds: 2),
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
duration: const Duration(seconds: 3),
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
);
);
} catch (_) {
final rng = math.Random();
if (!mounted) return;
setState(() {
_wordsDigits = List.generate(
_wordsCount,
(_) => List.generate(3, (_) => rng.nextInt(10)).join(),
);
_activeWordIndex = _wordsCount - 1;
});
}
}
@override
@@ -244,7 +272,7 @@ class _HomeSearchScreenState extends State<HomeSearchScreen> {
GradientStar(size: 24),
SizedBox(width: 10),
Text(
'Оракул 999',
'Оракул',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w900,
@@ -265,9 +293,9 @@ class _HomeSearchScreenState extends State<HomeSearchScreen> {
onPressed: _resetSession,
),
IconButton(
tooltip: 'Новая суточная матрица через RANDOM.ORG',
icon: const Icon(Icons.shuffle_rounded),
onPressed: _reshuffleMatrix,
tooltip: 'Бросить священный жребий (3 × d10)',
icon: const Icon(Icons.casino_rounded, color: Color(0xFF64B5F6)),
onPressed: _rollRandomCleromancy,
),
IconButton(
tooltip: _showKeypad ? 'Скрыть панель' : 'Показать панель',
@@ -284,6 +312,8 @@ class _HomeSearchScreenState extends State<HomeSearchScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const InterpreterPersonaPicker(),
const SizedBox(height: 12),
// Row: Question & Words count selector (1..9)
Row(
crossAxisAlignment: CrossAxisAlignment.start,
@@ -499,20 +529,26 @@ class _HomeSearchScreenState extends State<HomeSearchScreen> {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
const Icon(Icons.casino_outlined, size: 15, color: Color(0xFFFFD54F)),
const SizedBox(width: 6),
Text(
'Ввод граней (Слово ${_activeWordIndex + 1} из $_wordsCount):',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w700,
color: Color(0xFFFFD54F),
Expanded(
child: Row(
children: [
const Icon(Icons.casino_outlined, size: 15, color: Color(0xFFFFD54F)),
const SizedBox(width: 6),
Flexible(
child: Text(
'Ввод граней (Слово ${_activeWordIndex + 1} из $_wordsCount):',
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w700,
color: Color(0xFFFFD54F),
),
overflow: TextOverflow.ellipsis,
),
),
),
],
],
),
),
const SizedBox(width: 8),
Text(
currentActiveDigits.length == 3
? 'Код: #$currentActiveDigits'