182 lines
5.1 KiB
Dart
182 lines
5.1 KiB
Dart
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,
|
|
);
|
|
}
|
|
}
|