2026-04-03 16:56:47 +08:00
|
|
|
import 'divination_params.dart';
|
|
|
|
|
|
2026-04-29 14:26:15 +08:00
|
|
|
enum DivinationRunStatus { success, failed, refused }
|
|
|
|
|
|
2026-04-03 16:56:47 +08:00
|
|
|
class DivinationResultData {
|
|
|
|
|
const DivinationResultData({
|
2026-04-08 17:23:02 +08:00
|
|
|
this.threadId,
|
2026-04-03 16:56:47 +08:00
|
|
|
required this.params,
|
|
|
|
|
required this.binaryCode,
|
|
|
|
|
required this.changedBinaryCode,
|
|
|
|
|
required this.guaName,
|
|
|
|
|
required this.targetGuaName,
|
|
|
|
|
required this.upperName,
|
|
|
|
|
required this.lowerName,
|
|
|
|
|
required this.signType,
|
|
|
|
|
required this.keywords,
|
2026-04-07 18:41:08 +08:00
|
|
|
required this.focusPoints,
|
2026-04-03 16:56:47 +08:00
|
|
|
required this.conclusion,
|
|
|
|
|
required this.analysis,
|
|
|
|
|
required this.suggestion,
|
|
|
|
|
required this.ganzhi,
|
|
|
|
|
required this.wuXingStatus,
|
|
|
|
|
required this.yaoLines,
|
|
|
|
|
required this.targetYaoLines,
|
2026-04-29 14:26:15 +08:00
|
|
|
this.status = DivinationRunStatus.success,
|
2026-04-03 16:56:47 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
final DivinationParams params;
|
2026-04-08 17:23:02 +08:00
|
|
|
final String? threadId;
|
2026-04-03 16:56:47 +08:00
|
|
|
final String binaryCode;
|
|
|
|
|
final String changedBinaryCode;
|
|
|
|
|
final String guaName;
|
|
|
|
|
final String targetGuaName;
|
|
|
|
|
final String upperName;
|
|
|
|
|
final String lowerName;
|
|
|
|
|
final String signType;
|
|
|
|
|
final String keywords;
|
2026-04-07 18:41:08 +08:00
|
|
|
final List<String> focusPoints;
|
2026-04-03 16:56:47 +08:00
|
|
|
final String conclusion;
|
|
|
|
|
final String analysis;
|
|
|
|
|
final String suggestion;
|
|
|
|
|
final GanzhiData ganzhi;
|
|
|
|
|
final Map<String, String> wuXingStatus;
|
|
|
|
|
final List<YaoLineData> yaoLines;
|
|
|
|
|
final List<YaoLineData> targetYaoLines;
|
2026-04-29 14:26:15 +08:00
|
|
|
final DivinationRunStatus status;
|
2026-04-03 16:56:47 +08:00
|
|
|
|
|
|
|
|
bool get hasChangingYao => binaryCode != changedBinaryCode;
|
2026-04-29 14:26:15 +08:00
|
|
|
bool get isSuccess => status == DivinationRunStatus.success;
|
2026-04-06 01:28:10 +08:00
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() {
|
|
|
|
|
return <String, dynamic>{
|
|
|
|
|
'params': params.toPayload(),
|
2026-04-08 17:23:02 +08:00
|
|
|
'threadId': threadId,
|
2026-04-06 01:28:10 +08:00
|
|
|
'binaryCode': binaryCode,
|
|
|
|
|
'changedBinaryCode': changedBinaryCode,
|
|
|
|
|
'guaName': guaName,
|
|
|
|
|
'targetGuaName': targetGuaName,
|
|
|
|
|
'upperName': upperName,
|
|
|
|
|
'lowerName': lowerName,
|
|
|
|
|
'signType': signType,
|
|
|
|
|
'keywords': keywords,
|
2026-04-07 18:41:08 +08:00
|
|
|
'focusPoints': focusPoints,
|
2026-04-06 01:28:10 +08:00
|
|
|
'conclusion': conclusion,
|
|
|
|
|
'analysis': analysis,
|
|
|
|
|
'suggestion': suggestion,
|
|
|
|
|
'ganzhi': ganzhi.toJson(),
|
|
|
|
|
'wuXingStatus': wuXingStatus,
|
|
|
|
|
'yaoLines': yaoLines.map((line) => line.toJson()).toList(growable: false),
|
|
|
|
|
'targetYaoLines': targetYaoLines
|
|
|
|
|
.map((line) => line.toJson())
|
|
|
|
|
.toList(growable: false),
|
2026-04-29 14:26:15 +08:00
|
|
|
'status': status.name,
|
2026-04-06 01:28:10 +08:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
factory DivinationResultData.fromJson(Map<String, dynamic> json) {
|
|
|
|
|
final paramsRaw = json['params'];
|
|
|
|
|
final ganzhiRaw = json['ganzhi'];
|
|
|
|
|
final wuXingRaw = json['wuXingStatus'];
|
|
|
|
|
final yaoLinesRaw = json['yaoLines'];
|
|
|
|
|
final targetYaoLinesRaw = json['targetYaoLines'];
|
|
|
|
|
if (paramsRaw is! Map<String, dynamic> ||
|
|
|
|
|
ganzhiRaw is! Map<String, dynamic> ||
|
|
|
|
|
wuXingRaw is! Map<String, dynamic> ||
|
|
|
|
|
yaoLinesRaw is! List<dynamic> ||
|
|
|
|
|
targetYaoLinesRaw is! List<dynamic>) {
|
|
|
|
|
throw const FormatException('Invalid divination result payload');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return DivinationResultData(
|
|
|
|
|
params: DivinationParams.fromPayload(paramsRaw),
|
2026-04-08 17:23:02 +08:00
|
|
|
threadId: json['threadId'] as String?,
|
2026-04-06 01:28:10 +08:00
|
|
|
binaryCode: _requiredString(json, 'binaryCode'),
|
|
|
|
|
changedBinaryCode: _requiredString(json, 'changedBinaryCode'),
|
|
|
|
|
guaName: _requiredString(json, 'guaName'),
|
|
|
|
|
targetGuaName: _requiredString(json, 'targetGuaName'),
|
|
|
|
|
upperName: _requiredString(json, 'upperName'),
|
|
|
|
|
lowerName: _requiredString(json, 'lowerName'),
|
|
|
|
|
signType: _requiredString(json, 'signType'),
|
|
|
|
|
keywords: _requiredString(json, 'keywords'),
|
2026-04-07 18:41:08 +08:00
|
|
|
focusPoints: _requiredStringList(json, 'focusPoints'),
|
2026-04-06 01:28:10 +08:00
|
|
|
conclusion: _requiredString(json, 'conclusion'),
|
|
|
|
|
analysis: _requiredString(json, 'analysis'),
|
|
|
|
|
suggestion: _requiredString(json, 'suggestion'),
|
|
|
|
|
ganzhi: GanzhiData.fromJson(ganzhiRaw),
|
|
|
|
|
wuXingStatus: wuXingRaw.map(
|
|
|
|
|
(key, value) => MapEntry(key, value.toString()),
|
|
|
|
|
),
|
|
|
|
|
yaoLines: yaoLinesRaw
|
|
|
|
|
.map((raw) {
|
|
|
|
|
if (raw is! Map<String, dynamic>) {
|
|
|
|
|
throw const FormatException('Invalid yao line payload');
|
|
|
|
|
}
|
|
|
|
|
return YaoLineData.fromJson(raw);
|
|
|
|
|
})
|
|
|
|
|
.toList(growable: false),
|
|
|
|
|
targetYaoLines: targetYaoLinesRaw
|
|
|
|
|
.map((raw) {
|
|
|
|
|
if (raw is! Map<String, dynamic>) {
|
|
|
|
|
throw const FormatException('Invalid target yao line payload');
|
|
|
|
|
}
|
|
|
|
|
return YaoLineData.fromJson(raw);
|
|
|
|
|
})
|
|
|
|
|
.toList(growable: false),
|
2026-04-29 14:26:15 +08:00
|
|
|
status: _parseStatus(json['status']),
|
2026-04-06 01:28:10 +08:00
|
|
|
);
|
|
|
|
|
}
|
2026-04-29 14:26:15 +08:00
|
|
|
|
|
|
|
|
static DivinationRunStatus _parseStatus(Object? value) {
|
|
|
|
|
if (value is! String) {
|
|
|
|
|
return DivinationRunStatus.success;
|
|
|
|
|
}
|
|
|
|
|
return switch (value) {
|
|
|
|
|
'success' => DivinationRunStatus.success,
|
|
|
|
|
'failed' => DivinationRunStatus.failed,
|
|
|
|
|
'refused' => DivinationRunStatus.refused,
|
|
|
|
|
_ => DivinationRunStatus.success,
|
|
|
|
|
};
|
|
|
|
|
}
|
2026-04-03 16:56:47 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-07 18:41:08 +08:00
|
|
|
List<String> _requiredStringList(Map<String, dynamic> json, String key) {
|
|
|
|
|
final raw = json[key];
|
|
|
|
|
if (raw is! List<dynamic>) {
|
|
|
|
|
throw FormatException('Invalid $key payload');
|
|
|
|
|
}
|
|
|
|
|
return raw
|
|
|
|
|
.map((item) {
|
|
|
|
|
if (item is! String) {
|
|
|
|
|
throw FormatException('Invalid $key item payload');
|
|
|
|
|
}
|
|
|
|
|
return item;
|
|
|
|
|
})
|
|
|
|
|
.toList(growable: false);
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-03 16:56:47 +08:00
|
|
|
class GanzhiData {
|
|
|
|
|
const GanzhiData({
|
|
|
|
|
required this.yearGanZhi,
|
|
|
|
|
required this.monthGanZhi,
|
|
|
|
|
required this.dayGanZhi,
|
|
|
|
|
required this.timeGanZhi,
|
|
|
|
|
required this.yearKongWang,
|
|
|
|
|
required this.monthKongWang,
|
|
|
|
|
required this.dayKongWang,
|
|
|
|
|
required this.timeKongWang,
|
|
|
|
|
required this.yueJian,
|
|
|
|
|
required this.riChen,
|
|
|
|
|
required this.yuePo,
|
|
|
|
|
required this.riChong,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
final String yearGanZhi;
|
|
|
|
|
final String monthGanZhi;
|
|
|
|
|
final String dayGanZhi;
|
|
|
|
|
final String timeGanZhi;
|
|
|
|
|
final String yearKongWang;
|
|
|
|
|
final String monthKongWang;
|
|
|
|
|
final String dayKongWang;
|
|
|
|
|
final String timeKongWang;
|
|
|
|
|
final String yueJian;
|
|
|
|
|
final String riChen;
|
|
|
|
|
final String yuePo;
|
|
|
|
|
final String riChong;
|
2026-04-06 01:28:10 +08:00
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() {
|
|
|
|
|
return <String, dynamic>{
|
|
|
|
|
'yearGanZhi': yearGanZhi,
|
|
|
|
|
'monthGanZhi': monthGanZhi,
|
|
|
|
|
'dayGanZhi': dayGanZhi,
|
|
|
|
|
'timeGanZhi': timeGanZhi,
|
|
|
|
|
'yearKongWang': yearKongWang,
|
|
|
|
|
'monthKongWang': monthKongWang,
|
|
|
|
|
'dayKongWang': dayKongWang,
|
|
|
|
|
'timeKongWang': timeKongWang,
|
|
|
|
|
'yueJian': yueJian,
|
|
|
|
|
'riChen': riChen,
|
|
|
|
|
'yuePo': yuePo,
|
|
|
|
|
'riChong': riChong,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
factory GanzhiData.fromJson(Map<String, dynamic> json) {
|
|
|
|
|
return GanzhiData(
|
|
|
|
|
yearGanZhi: _requiredString(json, 'yearGanZhi'),
|
|
|
|
|
monthGanZhi: _requiredString(json, 'monthGanZhi'),
|
|
|
|
|
dayGanZhi: _requiredString(json, 'dayGanZhi'),
|
|
|
|
|
timeGanZhi: _requiredString(json, 'timeGanZhi'),
|
|
|
|
|
yearKongWang: _requiredString(json, 'yearKongWang'),
|
|
|
|
|
monthKongWang: _requiredString(json, 'monthKongWang'),
|
|
|
|
|
dayKongWang: _requiredString(json, 'dayKongWang'),
|
|
|
|
|
timeKongWang: _requiredString(json, 'timeKongWang'),
|
|
|
|
|
yueJian: _requiredString(json, 'yueJian'),
|
|
|
|
|
riChen: _requiredString(json, 'riChen'),
|
|
|
|
|
yuePo: _requiredString(json, 'yuePo'),
|
|
|
|
|
riChong: _requiredString(json, 'riChong'),
|
|
|
|
|
);
|
|
|
|
|
}
|
2026-04-03 16:56:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
class YaoLineData {
|
|
|
|
|
const YaoLineData({
|
|
|
|
|
required this.index,
|
|
|
|
|
required this.spirit,
|
|
|
|
|
required this.relation,
|
|
|
|
|
required this.branch,
|
|
|
|
|
required this.element,
|
|
|
|
|
required this.type,
|
|
|
|
|
required this.mark,
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
final int index;
|
|
|
|
|
final String spirit;
|
|
|
|
|
final String relation;
|
|
|
|
|
final String branch;
|
|
|
|
|
final String element;
|
|
|
|
|
final YaoType type;
|
|
|
|
|
final String mark;
|
2026-04-06 01:28:10 +08:00
|
|
|
|
|
|
|
|
Map<String, dynamic> toJson() {
|
|
|
|
|
return <String, dynamic>{
|
|
|
|
|
'index': index,
|
|
|
|
|
'spirit': spirit,
|
|
|
|
|
'relation': relation,
|
|
|
|
|
'branch': branch,
|
|
|
|
|
'element': element,
|
|
|
|
|
'type': type.name,
|
|
|
|
|
'mark': mark,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
factory YaoLineData.fromJson(Map<String, dynamic> json) {
|
|
|
|
|
return YaoLineData(
|
|
|
|
|
index: _requiredInt(json, 'index'),
|
|
|
|
|
spirit: _requiredString(json, 'spirit'),
|
|
|
|
|
relation: _requiredString(json, 'relation'),
|
|
|
|
|
branch: _requiredString(json, 'branch'),
|
|
|
|
|
element: _requiredString(json, 'element'),
|
|
|
|
|
type: yaoTypeFromName(_requiredString(json, 'type')),
|
|
|
|
|
mark: _requiredString(json, 'mark'),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String _requiredString(Map<String, dynamic> json, String key) {
|
|
|
|
|
final value = json[key];
|
|
|
|
|
if (value is! String || value.isEmpty) {
|
|
|
|
|
throw FormatException('Missing required string: $key');
|
|
|
|
|
}
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int _requiredInt(Map<String, dynamic> json, String key) {
|
|
|
|
|
final value = json[key];
|
|
|
|
|
if (value is int) {
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
if (value is num) {
|
|
|
|
|
return value.toInt();
|
|
|
|
|
}
|
|
|
|
|
throw FormatException('Missing required int: $key');
|
2026-04-03 16:56:47 +08:00
|
|
|
}
|