feat: complete academic symbol lexicon heal, 2-column Cooper extraction, and updated assets
This commit is contained in:
@@ -0,0 +1,964 @@
|
||||
import '../models/syncretic_session_model.dart';
|
||||
import '../services/words_repository.dart';
|
||||
import '../models/history_entry_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import '../models/houses_session_model.dart';
|
||||
import '../models/word_model.dart';
|
||||
import '../services/ai_oracle_service.dart';
|
||||
import '../widgets/gradient_star_badge.dart';
|
||||
import 'house_chains_screen.dart';
|
||||
import 'matrix_geometry_screen.dart';
|
||||
import '../services/oracle_master_prompt_generator.dart';
|
||||
import 'symbol_detail_screen.dart';
|
||||
|
||||
class HousesResultScreen extends StatefulWidget {
|
||||
final HousesSession session;
|
||||
|
||||
const HousesResultScreen({super.key, required this.session});
|
||||
|
||||
@override
|
||||
State<HousesResultScreen> createState() => _HousesResultScreenState();
|
||||
}
|
||||
|
||||
class _HousesResultScreenState extends State<HousesResultScreen> {
|
||||
final _aiService = AiOracleService();
|
||||
|
||||
String? _aiInterpretation;
|
||||
bool _isLoadingAi = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
// Auto-record Houses Session into active Syncretic Day Session
|
||||
final session = widget.session;
|
||||
final items = session.selectedHouses.map((h) {
|
||||
final g = h.guestWord ?? h.houseWord;
|
||||
return ReadingSignItem(
|
||||
title: 'Дом #${(h.houseIndex + 1).toString().padLeft(3, "0")} «${g.word.toUpperCase()}»',
|
||||
subtitle: 'Архонт: ${session.sectors[h.sectorIndex].archonWord.word}',
|
||||
symbol: '🏛️',
|
||||
lore: g.core.isNotEmpty ? g.core : g.description,
|
||||
linkedWord: g,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
WordsRepository().addReadingToSyncreticSession(
|
||||
SyncreticReading(
|
||||
id: 'reading_${session.id}',
|
||||
systemId: 'matrix',
|
||||
systemName: 'Матрица 33×30 (Дома)',
|
||||
systemIcon: '🏛️',
|
||||
timestamp: session.createdAt,
|
||||
layoutTitle: '${items.length} ${items.length == 1 ? "дом" : "домов"}',
|
||||
inputMethod: 'dice',
|
||||
items: items,
|
||||
question: session.question,
|
||||
),
|
||||
question: session.question,
|
||||
);
|
||||
|
||||
// Auto-record Calculated House Chains into active Syncretic Day Session
|
||||
if (session.chains.isNotEmpty) {
|
||||
final chainItems = session.chains.map((chain) {
|
||||
final pathStr = chain.steps.map((s) => '«${s.guest.word.toUpperCase()}»').join(' ➔ ');
|
||||
final startWord = chain.startingHouse.houseWord;
|
||||
return ReadingSignItem(
|
||||
title: 'Цепочка #${chain.chainIndex}: ${chain.endTypeTitle}',
|
||||
subtitle: 'Старт: Дом #${chain.startingHouse.houseIndex + 1} «${startWord.word}» • Шагов: ${chain.steps.length}',
|
||||
symbol: chain.hasLoop ? '🔄' : (chain.endType == ChainEndType.archonThrone ? '👑' : '🔗'),
|
||||
lore: 'Траектория: ' + pathStr + '\n' + chain.description,
|
||||
linkedWord: chain.steps.isNotEmpty ? chain.steps.last.guest : startWord,
|
||||
meta: {
|
||||
'chainIndex': chain.chainIndex,
|
||||
'endType': chain.endType.name,
|
||||
'stepsCount': chain.steps.length,
|
||||
'path': pathStr,
|
||||
},
|
||||
);
|
||||
}).toList();
|
||||
|
||||
WordsRepository().addReadingToSyncreticSession(
|
||||
SyncreticReading(
|
||||
id: 'chains_${session.id}',
|
||||
systemId: 'matrix_chains',
|
||||
systemName: 'Матрица 33×30: Цепочки Домов',
|
||||
systemIcon: '🔗',
|
||||
timestamp: session.createdAt,
|
||||
layoutTitle: '${session.chains.length} ${session.chains.length == 1 ? "цепочка" : (session.chains.length < 5 ? "цепочки" : "цепочек")}',
|
||||
inputMethod: 'dice',
|
||||
items: chainItems,
|
||||
question: session.question,
|
||||
),
|
||||
question: session.question,
|
||||
);
|
||||
}
|
||||
|
||||
_aiInterpretation = widget.session.aiInterpretation;
|
||||
}
|
||||
|
||||
Future<void> _requestAiInterpretation() async {
|
||||
setState(() => _isLoadingAi = true);
|
||||
HapticFeedback.lightImpact();
|
||||
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('Ты — верховный оракул, читающий расклад Домов 33×30 в традиции Оракула 999.');
|
||||
buffer.writeln('В раскладе участвуют 3 уровня реальности:');
|
||||
buffer.writeln('1. Небесный Архонт Сектора — высший закон и климат триады столбцов.');
|
||||
buffer.writeln('2. Земной Дом — конкретная сфера и почва действия.');
|
||||
buffer.writeln('3. Знак-Гость — сила, прибывшая в дом по жребию.\n');
|
||||
|
||||
buffer.writeln('ПОСЛЕДОВАТЕЛЬНОСТЬ ОТКРЫТЫХ ДОМОВ:');
|
||||
for (int i = 0; i < widget.session.selectedHouses.length; i++) {
|
||||
final h = widget.session.selectedHouses[i];
|
||||
final sector = widget.session.sectors[h.sectorIndex];
|
||||
final guest = h.guestWord!;
|
||||
buffer.writeln(
|
||||
'Позиция ${i + 1}: Архонт «${sector.archonWord.word.toUpperCase()}» ➔ Дом «${h.houseWord.word.toUpperCase()}» ➔ Гость «${guest.word.toUpperCase()}»',
|
||||
);
|
||||
if (guest.core.isNotEmpty) {
|
||||
buffer.writeln(' Суть гостя: ${guest.core}');
|
||||
}
|
||||
}
|
||||
|
||||
if (widget.session.chains.isNotEmpty) {
|
||||
buffer.writeln('\nЦЕПОЧКИ ДОМОВ:');
|
||||
for (final c in widget.session.chains) {
|
||||
buffer.writeln('• Цепочка #${c.chainIndex} (${c.hasLoop ? "петля" : "вектор"}): ${c.description}');
|
||||
}
|
||||
}
|
||||
|
||||
buffer.writeln('\nДай развернутое, цельное толкование расклада: как разворачивается путь от первого шага к исходу, как гости чувствуют себя в домах под властью своих Архонтов, и какой главный совет даёт оракул.');
|
||||
|
||||
try {
|
||||
final res = await _aiService.interpretSession(
|
||||
words: widget.session.selectedHouses
|
||||
.map((h) => SessionWord.fromWordItem(
|
||||
h.guestWord!,
|
||||
positionTitle: 'Дом #${h.houseIndex + 1} «${h.houseWord.word}»',
|
||||
))
|
||||
.toList(),
|
||||
question: widget.session.question ?? 'Расклад Домов 33×30',
|
||||
);
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_aiInterpretation = res;
|
||||
_isLoadingAi = false;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_aiInterpretation = 'Ошибка связи с оракулом: $e';
|
||||
_isLoadingAi = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _openWordDossier(WordItem word) {
|
||||
HapticFeedback.selectionClick();
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => SymbolDetailScreen(word: word),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _copyAll() {
|
||||
final buffer = StringBuffer();
|
||||
buffer.writeln('🔮 ОРАКУЛ — РАСКЛАД ДОМОВ 33×30');
|
||||
if (widget.session.question != null && widget.session.question!.isNotEmpty) {
|
||||
buffer.writeln('Вопрос: «${widget.session.question}»');
|
||||
}
|
||||
buffer.writeln('Открыто домов: ${widget.session.selectedHouses.length}\n');
|
||||
|
||||
for (int i = 0; i < widget.session.selectedHouses.length; i++) {
|
||||
final h = widget.session.selectedHouses[i];
|
||||
final sector = widget.session.sectors[h.sectorIndex];
|
||||
final guest = h.guestWord!;
|
||||
buffer.writeln(
|
||||
'#${i + 1} [Сектор: Архонт ${sector.archonWord.word.toUpperCase()}]',
|
||||
);
|
||||
buffer.writeln(' 🏛️ Дом #${(h.houseIndex + 1).toString().padLeft(3, '0')} «${h.houseWord.word.toUpperCase()}»');
|
||||
buffer.writeln(' ✨ Гость: «${guest.word.toUpperCase()}»');
|
||||
if (guest.core.isNotEmpty) {
|
||||
buffer.writeln(' Закон: ${guest.core}');
|
||||
}
|
||||
buffer.writeln();
|
||||
}
|
||||
|
||||
if (_aiInterpretation != null) {
|
||||
buffer.writeln('🤖 Толкование Оракула:\n$_aiInterpretation\n');
|
||||
}
|
||||
|
||||
Clipboard.setData(ClipboardData(text: buffer.toString()));
|
||||
HapticFeedback.mediumImpact();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Полный расклад домов скопирован в буфер'),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final session = widget.session;
|
||||
final activeSectorIndices = session.selectedHouses.map((h) => h.sectorIndex).toSet();
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xFF0A0C16),
|
||||
appBar: AppBar(
|
||||
title: const Row(
|
||||
children: [
|
||||
GradientStar(size: 20),
|
||||
SizedBox(width: 8),
|
||||
Text('Расклад Домов 33×30', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 17)),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
IconButton(
|
||||
tooltip: 'Цепочки Домов',
|
||||
icon: Badge(
|
||||
label: Text('${session.chains.length}'),
|
||||
backgroundColor: const Color(0xFFFFD54F),
|
||||
textColor: Colors.black,
|
||||
child: const Icon(Icons.hub_outlined, color: Color(0xFFFFD54F)),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => HouseChainsScreen(session: session),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Узоры Матрицы 33×30',
|
||||
icon: const Icon(Icons.auto_awesome_mosaic_rounded, color: Color(0xFFFFD54F)),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => MatrixGeometryScreen(session: session),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Скопировать расклад',
|
||||
icon: const Icon(Icons.copy_rounded),
|
||||
onPressed: _copyAll,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: ListView(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 40),
|
||||
children: [
|
||||
// Querent (Significator) Card
|
||||
_buildQuerentSection(session),
|
||||
const SizedBox(height: 16),
|
||||
// Revealed Archons Banner
|
||||
_buildArchonsRevealSection(activeSectorIndices),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Houses sequence header
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.format_list_numbered_rounded, color: Color(0xFFFFD54F), size: 18),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'ПОСЛЕДОВАТЕЛЬНОСТЬ ДОМОВ (${session.selectedHouses.length}):',
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFFFD54F),
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 13,
|
||||
letterSpacing: 0.8,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Houses Cards
|
||||
for (int i = 0; i < session.selectedHouses.length; i++) ...[
|
||||
_buildHouseStepCard(session.selectedHouses[i], i + 1),
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// 1. Master Prompt for Advanced LLMs (Grok / Claude / Gemini / GPT-4)
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF261D48),
|
||||
foregroundColor: const Color(0xFFFFD54F),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
side: const BorderSide(color: Color(0xFFFFD54F), width: 1.4),
|
||||
),
|
||||
elevation: 6,
|
||||
shadowColor: const Color(0x66FFD54F),
|
||||
),
|
||||
onPressed: () => _showMasterPromptDialog(context, session),
|
||||
icon: const Icon(Icons.psychology_alt_rounded, color: Color(0xFFFFD54F), size: 22),
|
||||
label: const Text(
|
||||
'🧠 Мастер-Промпт для Нейросети (Grok / Claude / Gemini)',
|
||||
style: TextStyle(fontWeight: FontWeight.w900, fontSize: 13.5, letterSpacing: 0.3),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// 2. Matrix Geometry & Constellation Pattern
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF19203C),
|
||||
foregroundColor: const Color(0xFF00E5FF),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
side: const BorderSide(color: Color(0xFF00E5FF), width: 1.2),
|
||||
),
|
||||
elevation: 4,
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => MatrixGeometryScreen(session: session),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.auto_awesome_mosaic_rounded, color: Color(0xFF00E5FF)),
|
||||
label: Text(
|
||||
'Узор на Матрице 33×30 (${session.selectedHouses.length} узлов)',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 14.5),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Action Button: House Chains Explorer
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF1E2238),
|
||||
foregroundColor: const Color(0xFFFFD54F),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
side: const BorderSide(color: Color(0xFFFFD54F), width: 1.2),
|
||||
),
|
||||
),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => HouseChainsScreen(session: session),
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.hub_outlined, color: Color(0xFFFFD54F)),
|
||||
label: Text(
|
||||
'Исследовать Цепочки Домов (${session.chains.length})',
|
||||
style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// AI Interpretation Section
|
||||
_buildAiSection(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildArchonsRevealSection(Set<int> activeSectors) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF131627),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(color: const Color(0xFF3949AB).withValues(alpha: 0.4)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Row(
|
||||
children: [
|
||||
Icon(Icons.shield_moon_rounded, color: Color(0xFFFFD54F), size: 20),
|
||||
SizedBox(width: 8),
|
||||
Text(
|
||||
'АРХОНТЫ АКТИВНЫХ СЕКТОРОВ',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFFFF9C4),
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 13,
|
||||
letterSpacing: 0.8,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: activeSectors.map((sectorIdx) {
|
||||
final sector = widget.session.sectors[sectorIdx];
|
||||
return InkWell(
|
||||
onTap: () => _openWordDossier(sector.archonWord),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
decoration: BoxDecoration(
|
||||
color: sector.sectorColor.withValues(alpha: 0.18),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: sector.sectorColor, width: 1.2),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: sector.sectorColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'Триада ${sectorIdx + 1}: «${sector.archonWord.word.toUpperCase()}»',
|
||||
style: TextStyle(
|
||||
color: sector.sectorColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildHouseStepCard(HouseCell cell, int order) {
|
||||
final sector = widget.session.sectors[cell.sectorIndex];
|
||||
final guest = cell.guestWord!;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF141729),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(color: sector.sectorColor.withValues(alpha: 0.4), width: 1.2),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha: 0.25),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Header: Order, Archon triad
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 26,
|
||||
height: 26,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFFFD54F),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'$order',
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 8,
|
||||
height: 8,
|
||||
decoration: BoxDecoration(
|
||||
color: sector.sectorColor,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
'Под властью Архонта «${sector.archonWord.word.toUpperCase()}» (Триада ${cell.sectorIndex + 1})',
|
||||
style: TextStyle(
|
||||
color: sector.sectorColor,
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Host & Guest Banner
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF1C2038),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: const Color(0xFF2A2D4A)),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Host row
|
||||
InkWell(
|
||||
onTap: () => _openWordDossier(cell.houseWord),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.home_work_rounded, color: Color(0xFF90A4AE), size: 18),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
'Дом #${(cell.houseIndex + 1).toString().padLeft(3, '0')}:',
|
||||
style: const TextStyle(color: Color(0xFF90A4AE), fontSize: 13),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
cell.houseWord.word.toUpperCase(),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Icon(Icons.arrow_forward_ios_rounded, size: 12, color: Color(0xFF5C6280)),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Divider(color: Color(0xFF2A2D4A), height: 16),
|
||||
|
||||
// Guest row
|
||||
InkWell(
|
||||
onTap: () => _openWordDossier(guest),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.auto_awesome_rounded, color: Color(0xFFFFD54F), size: 18),
|
||||
const SizedBox(width: 8),
|
||||
const Text(
|
||||
'Пришедший Гость:',
|
||||
style: TextStyle(color: Color(0xFFFFD54F), fontSize: 13, fontWeight: FontWeight.w600),
|
||||
),
|
||||
const SizedBox(width: 6),
|
||||
Text(
|
||||
guest.word.toUpperCase(),
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFFFF9C4),
|
||||
fontWeight: FontWeight.w900,
|
||||
fontSize: 16,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
const Icon(Icons.arrow_forward_ios_rounded, size: 12, color: Color(0xFFFFD54F)),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// Guest Core / Meaning
|
||||
if (guest.core.isNotEmpty) ...[
|
||||
Text(
|
||||
'✨ Закон знака: ${guest.core}',
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFE0E0E0),
|
||||
fontSize: 13,
|
||||
height: 1.4,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
|
||||
if (guest.oracle.isNotEmpty) ...[
|
||||
Text(
|
||||
guest.oracle,
|
||||
maxLines: 3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFB0BEC5),
|
||||
fontSize: 12,
|
||||
height: 1.35,
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAiSection() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF151829),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(color: const Color(0xFFFFD54F).withValues(alpha: 0.4)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const GradientStar(size: 20),
|
||||
const SizedBox(width: 8),
|
||||
const Text(
|
||||
'Толкование Оракула (AI)',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFFFF9C4),
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
if (!_isLoadingAi)
|
||||
IconButton(
|
||||
tooltip: 'Запросить толкование',
|
||||
icon: const Icon(Icons.auto_awesome, color: Color(0xFFFFD54F)),
|
||||
onPressed: _requestAiInterpretation,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
if (_isLoadingAi) ...[
|
||||
const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 24),
|
||||
child: Column(
|
||||
children: [
|
||||
CircularProgressIndicator(color: Color(0xFFFFD54F)),
|
||||
SizedBox(height: 12),
|
||||
Text('Оракул синтезирует Архонтов, Дома и Цепочки...', style: TextStyle(color: Color(0xFF90A4AE), fontSize: 13)),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
] else if (_aiInterpretation != null) ...[
|
||||
Text(
|
||||
_aiInterpretation!,
|
||||
style: const TextStyle(color: Color(0xFFECEFF1), fontSize: 14, height: 1.5),
|
||||
),
|
||||
] else ...[
|
||||
const Text(
|
||||
'Нажмите кнопку ниже, чтобы нейросеть Оракула соединила энергии 10 Архонтов, открытых Домов и Цепочек судьбы в единое предсказание.',
|
||||
style: TextStyle(color: Color(0xFF90A4AE), fontSize: 13, height: 1.4),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFF2A2D4A),
|
||||
foregroundColor: const Color(0xFFFFD54F),
|
||||
minimumSize: const Size.fromHeight(44),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
side: const BorderSide(color: Color(0xFFFFD54F), width: 0.8),
|
||||
),
|
||||
),
|
||||
onPressed: _requestAiInterpretation,
|
||||
icon: const Icon(Icons.auto_awesome_rounded),
|
||||
label: const Text('Получить толкование Оракула'),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildQuerentSection(HousesSession session) {
|
||||
final q = session.querentWord;
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
gradient: const LinearGradient(
|
||||
colors: [Color(0xFF2A164D), Color(0xFF161933)],
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
border: Border.all(color: const Color(0xFFFFD54F), width: 1.5),
|
||||
boxShadow: const [
|
||||
BoxShadow(
|
||||
color: Color(0x55FFD54F),
|
||||
blurRadius: 16,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: const Color(0xFFFFD54F).withValues(alpha: 0.18),
|
||||
border: Border.all(color: const Color(0xFFFFD54F), width: 1.2),
|
||||
),
|
||||
child: const Icon(Icons.workspace_premium_rounded, color: Color(0xFFFFD54F), size: 20),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text(
|
||||
'КВЕРЕНТ / СИГНИФИКАТОР РАСКЛАДА',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFFFD54F),
|
||||
fontSize: 10.5,
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 1.0,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
Text(
|
||||
q != null ? q.word.toUpperCase() : 'ОТКРЫТЫЙ ФОКУС',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
letterSpacing: 0.5,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (session.querentHouseIndex != null)
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF3B246B),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: const Color(0xFFFFD54F), width: 0.8),
|
||||
),
|
||||
child: Text(
|
||||
'Дом #${(session.querentHouseIndex! + 1).toString().padLeft(3, "0")}',
|
||||
style: const TextStyle(color: Color(0xFFFFD54F), fontSize: 11, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (q != null) ...[
|
||||
const SizedBox(height: 10),
|
||||
if (q.core.isNotEmpty) ...[
|
||||
Text(
|
||||
'Суть объекта: ${q.core}',
|
||||
style: const TextStyle(color: Color(0xFFCFD8DC), fontSize: 13, height: 1.4),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
],
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withValues(alpha: 0.08),
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
),
|
||||
child: Text(
|
||||
q.category,
|
||||
style: const TextStyle(color: Color(0xFF9FA8DA), fontSize: 10.5),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
q.partOfSpeech,
|
||||
style: const TextStyle(color: Color(0xFF78909C), fontSize: 11, fontStyle: FontStyle.italic),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
if (session.question != null && session.question!.trim().isNotEmpty) ...[
|
||||
const SizedBox(height: 10),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF101323),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: const Color(0xFF33385C), width: 0.8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Icons.help_outline_rounded, size: 16, color: Color(0xFFFFD54F)),
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Вопрос: «${session.question!.trim()}»',
|
||||
style: const TextStyle(color: Color(0xFFFFF9C4), fontSize: 12.5, fontWeight: FontWeight.w500),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showMasterPromptDialog(BuildContext context, HousesSession session) {
|
||||
HapticFeedback.mediumImpact();
|
||||
final prompt = OracleMasterPromptGenerator.generate(session);
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: const Color(0xFF0F1222),
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(24)),
|
||||
),
|
||||
builder: (ctx) {
|
||||
return DraggableScrollableSheet(
|
||||
initialChildSize: 0.85,
|
||||
minChildSize: 0.5,
|
||||
maxChildSize: 0.95,
|
||||
expand: false,
|
||||
builder: (context, scrollController) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 12, 20, 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Center(
|
||||
child: Container(
|
||||
width: 44,
|
||||
height: 4,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white24,
|
||||
borderRadius: BorderRadius.circular(2),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.psychology_alt_rounded, color: Color(0xFFFFD54F), size: 24),
|
||||
const SizedBox(width: 10),
|
||||
const Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Мастер-Промпт для Нейросети',
|
||||
style: TextStyle(color: Colors.white, fontSize: 17, fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
'Для Grok, Claude 3.5 Sonnet, Gemini 1.5 Pro, GPT-4',
|
||||
style: TextStyle(color: Color(0xFF90A4AE), fontSize: 11),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.close_rounded, color: Color(0xFF90A4AE)),
|
||||
onPressed: () => Navigator.pop(ctx),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// Quick Actions Bar
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF1C223D),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
'${prompt.length} символов • ${prompt.split(RegExp(r"\s+")).length} слов',
|
||||
style: const TextStyle(color: Color(0xFF90CAF9), fontSize: 11),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
ElevatedButton.icon(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFFFD54F),
|
||||
foregroundColor: Colors.black,
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8),
|
||||
),
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: prompt));
|
||||
HapticFeedback.heavyImpact();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Мастер-промпт скопирован в буфер обмена! Вставьте в Grok или Claude.'),
|
||||
backgroundColor: Color(0xFF388E3C),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Icons.copy_rounded, size: 16),
|
||||
label: const Text('Скопировать всё', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12.5)),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
// Scrollable Prompt Text Area
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF090A14),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: const Color(0xFF232742), width: 1.0),
|
||||
),
|
||||
child: SingleChildScrollView(
|
||||
controller: scrollController,
|
||||
child: SelectableText(
|
||||
prompt,
|
||||
style: const TextStyle(
|
||||
color: Color(0xFFECEFF1),
|
||||
fontFamily: 'monospace',
|
||||
fontSize: 11.5,
|
||||
height: 1.45,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user