965 lines
37 KiB
Dart
965 lines
37 KiB
Dart
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,
|
||
),
|
||
),
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
},
|
||
);
|
||
},
|
||
);
|
||
}
|
||
|
||
}
|