348 lines
10 KiB
Dart
348 lines
10 KiB
Dart
import 'divination_params.dart';
|
|
import 'divination_result.dart';
|
|
|
|
class PointsBalanceData {
|
|
const PointsBalanceData({
|
|
required this.balance,
|
|
required this.frozenBalance,
|
|
required this.availableBalance,
|
|
required this.runCost,
|
|
required this.canRun,
|
|
});
|
|
|
|
factory PointsBalanceData.fromJson(Map<String, dynamic> json) {
|
|
return PointsBalanceData(
|
|
balance: _requiredInt(json, 'balance'),
|
|
frozenBalance: _requiredInt(json, 'frozenBalance'),
|
|
availableBalance: _requiredInt(json, 'availableBalance'),
|
|
runCost: _requiredInt(json, 'runCost'),
|
|
canRun: _requiredBool(json, 'canRun'),
|
|
);
|
|
}
|
|
|
|
final int balance;
|
|
final int frozenBalance;
|
|
final int availableBalance;
|
|
final int runCost;
|
|
final bool canRun;
|
|
}
|
|
|
|
class RunAcceptedData {
|
|
const RunAcceptedData({
|
|
required this.taskId,
|
|
required this.threadId,
|
|
required this.runId,
|
|
required this.created,
|
|
});
|
|
|
|
factory RunAcceptedData.fromJson(Map<String, dynamic> json) {
|
|
return RunAcceptedData(
|
|
taskId: _requiredString(json, 'taskId'),
|
|
threadId: _requiredString(json, 'threadId'),
|
|
runId: _requiredString(json, 'runId'),
|
|
created: _requiredBool(json, 'created'),
|
|
);
|
|
}
|
|
|
|
final String taskId;
|
|
final String threadId;
|
|
final String runId;
|
|
final bool created;
|
|
}
|
|
|
|
class DivinationRunAggregate {
|
|
const DivinationRunAggregate({
|
|
required this.derived,
|
|
required this.signLevel,
|
|
required this.summary,
|
|
required this.conclusion,
|
|
required this.focusPoints,
|
|
required this.advice,
|
|
required this.keywords,
|
|
required this.answer,
|
|
});
|
|
|
|
final DerivedDivinationData derived;
|
|
final String signLevel;
|
|
final String summary;
|
|
final List<String> conclusion;
|
|
final List<String> focusPoints;
|
|
final List<String> advice;
|
|
final List<String> keywords;
|
|
final String answer;
|
|
|
|
DivinationResultData toViewData(DivinationParams params) {
|
|
return DivinationResultData(
|
|
params: params,
|
|
binaryCode: derived.binaryCode,
|
|
changedBinaryCode: derived.changedBinaryCode,
|
|
guaName: derived.guaName,
|
|
targetGuaName: derived.targetGuaName,
|
|
upperName: derived.upperName,
|
|
lowerName: derived.lowerName,
|
|
signType: signLevel,
|
|
keywords: keywords.join('、'),
|
|
conclusion: _asBullet(conclusion),
|
|
analysis: summary.isEmpty ? answer : '$summary\n\n$answer',
|
|
suggestion: _asBullet(advice),
|
|
ganzhi: GanzhiData(
|
|
yearGanZhi: derived.ganzhi.yearGanZhi,
|
|
monthGanZhi: derived.ganzhi.monthGanZhi,
|
|
dayGanZhi: derived.ganzhi.dayGanZhi,
|
|
timeGanZhi: derived.ganzhi.timeGanZhi,
|
|
yearKongWang: derived.ganzhi.yearKongWang,
|
|
monthKongWang: derived.ganzhi.monthKongWang,
|
|
dayKongWang: derived.ganzhi.dayKongWang,
|
|
timeKongWang: derived.ganzhi.timeKongWang,
|
|
yueJian: derived.ganzhi.yueJian,
|
|
riChen: derived.ganzhi.riChen,
|
|
yuePo: derived.ganzhi.yuePo,
|
|
riChong: derived.ganzhi.riChong,
|
|
),
|
|
wuXingStatus: derived.wuXingStatuses,
|
|
yaoLines: derived.yaoInfoList
|
|
.map((line) => line.toViewModel())
|
|
.toList(growable: false),
|
|
targetYaoLines: derived.targetYaoInfoList
|
|
.map((line) => line.toViewModel())
|
|
.toList(growable: false),
|
|
);
|
|
}
|
|
|
|
String _asBullet(List<String> lines) {
|
|
if (lines.isEmpty) {
|
|
return '';
|
|
}
|
|
return List<String>.generate(
|
|
lines.length,
|
|
(i) => '${i + 1}. ${lines[i]}',
|
|
growable: false,
|
|
).join('\n');
|
|
}
|
|
}
|
|
|
|
class DerivedDivinationData {
|
|
const DerivedDivinationData({
|
|
required this.question,
|
|
required this.questionType,
|
|
required this.divinationMethod,
|
|
required this.divinationTime,
|
|
required this.binaryCode,
|
|
required this.changedBinaryCode,
|
|
required this.guaName,
|
|
required this.upperName,
|
|
required this.lowerName,
|
|
required this.targetGuaName,
|
|
required this.worldPosition,
|
|
required this.responsePosition,
|
|
required this.hasChangingYao,
|
|
required this.ganzhi,
|
|
required this.wuXingStatuses,
|
|
required this.yaoInfoList,
|
|
required this.targetYaoInfoList,
|
|
});
|
|
|
|
factory DerivedDivinationData.fromJson(Map<String, dynamic> json) {
|
|
final wuXingRaw = _requiredMap(json, 'wuXingStatuses');
|
|
return DerivedDivinationData(
|
|
question: _requiredString(json, 'question'),
|
|
questionType: _requiredString(json, 'questionType'),
|
|
divinationMethod: _requiredString(json, 'divinationMethod'),
|
|
divinationTime: _requiredString(json, 'divinationTime'),
|
|
binaryCode: _requiredString(json, 'binaryCode'),
|
|
changedBinaryCode: _requiredString(json, 'changedBinaryCode'),
|
|
guaName: _requiredString(json, 'guaName'),
|
|
upperName: _requiredString(json, 'upperName'),
|
|
lowerName: _requiredString(json, 'lowerName'),
|
|
targetGuaName: _requiredString(json, 'targetGuaName'),
|
|
worldPosition: _requiredInt(json, 'worldPosition'),
|
|
responsePosition: _requiredInt(json, 'responsePosition'),
|
|
hasChangingYao: _requiredBool(json, 'hasChangingYao'),
|
|
ganzhi: GanzhiBackend.fromJson(_requiredMap(json, 'ganzhi')),
|
|
wuXingStatuses: wuXingRaw.map(
|
|
(key, value) => MapEntry(key, value.toString()),
|
|
),
|
|
yaoInfoList: _parseYaoList(json['yaoInfoList']),
|
|
targetYaoInfoList: _parseYaoList(json['targetYaoInfoList']),
|
|
);
|
|
}
|
|
|
|
final String question;
|
|
final String questionType;
|
|
final String divinationMethod;
|
|
final String divinationTime;
|
|
final String binaryCode;
|
|
final String changedBinaryCode;
|
|
final String guaName;
|
|
final String upperName;
|
|
final String lowerName;
|
|
final String targetGuaName;
|
|
final int worldPosition;
|
|
final int responsePosition;
|
|
final bool hasChangingYao;
|
|
final GanzhiBackend ganzhi;
|
|
final Map<String, String> wuXingStatuses;
|
|
final List<YaoBackendLine> yaoInfoList;
|
|
final List<YaoBackendLine> targetYaoInfoList;
|
|
|
|
static List<YaoBackendLine> _parseYaoList(Object? raw) {
|
|
final list = raw as List<dynamic>?;
|
|
if (list == null) {
|
|
throw const FormatException(
|
|
'Missing required list: yaoInfoList/targetYaoInfoList',
|
|
);
|
|
}
|
|
return list
|
|
.map((item) {
|
|
if (item is! Map<String, dynamic>) {
|
|
throw const FormatException('Invalid yao line item');
|
|
}
|
|
return YaoBackendLine.fromJson(item);
|
|
})
|
|
.toList(growable: false);
|
|
}
|
|
}
|
|
|
|
class GanzhiBackend {
|
|
const GanzhiBackend({
|
|
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,
|
|
});
|
|
|
|
factory GanzhiBackend.fromJson(Map<String, dynamic> json) {
|
|
return GanzhiBackend(
|
|
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'),
|
|
);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
class YaoBackendLine {
|
|
const YaoBackendLine({
|
|
required this.position,
|
|
required this.spiritName,
|
|
required this.relationName,
|
|
required this.tiganName,
|
|
required this.elementName,
|
|
required this.isYang,
|
|
required this.isChanging,
|
|
required this.specialMark,
|
|
});
|
|
|
|
factory YaoBackendLine.fromJson(Map<String, dynamic> json) {
|
|
return YaoBackendLine(
|
|
position: _requiredInt(json, 'position'),
|
|
spiritName: _requiredString(json, 'spiritName'),
|
|
relationName: _requiredString(json, 'relationName'),
|
|
tiganName: _requiredString(json, 'tiganName'),
|
|
elementName: _requiredString(json, 'elementName'),
|
|
isYang: _requiredBool(json, 'isYang'),
|
|
isChanging: _requiredBool(json, 'isChanging'),
|
|
specialMark: _requiredStringAllowEmpty(json, 'specialMark'),
|
|
);
|
|
}
|
|
|
|
final int position;
|
|
final String spiritName;
|
|
final String relationName;
|
|
final String tiganName;
|
|
final String elementName;
|
|
final bool isYang;
|
|
final bool isChanging;
|
|
final String specialMark;
|
|
|
|
YaoLineData toViewModel() {
|
|
final type = switch ((isYang, isChanging)) {
|
|
(true, false) => YaoType.youngYang,
|
|
(false, false) => YaoType.youngYin,
|
|
(true, true) => YaoType.oldYang,
|
|
(false, true) => YaoType.oldYin,
|
|
};
|
|
return YaoLineData(
|
|
index: position - 1,
|
|
spirit: spiritName,
|
|
relation: relationName,
|
|
branch: tiganName,
|
|
element: elementName,
|
|
type: type,
|
|
mark: specialMark,
|
|
);
|
|
}
|
|
}
|
|
|
|
String _requiredStringAllowEmpty(Map<String, dynamic> json, String key) {
|
|
if (!json.containsKey(key)) {
|
|
throw FormatException('Invalid or missing field: $key');
|
|
}
|
|
final value = json[key];
|
|
if (value is! String) {
|
|
throw FormatException('Invalid or missing field: $key');
|
|
}
|
|
return value;
|
|
}
|
|
|
|
String _requiredString(Map<String, dynamic> json, String key) {
|
|
final value = json[key];
|
|
if (value is! String || value.isEmpty) {
|
|
throw FormatException('Invalid or missing field: $key');
|
|
}
|
|
return value;
|
|
}
|
|
|
|
int _requiredInt(Map<String, dynamic> json, String key) {
|
|
final value = json[key];
|
|
if (value is! num) {
|
|
throw FormatException('Invalid or missing field: $key');
|
|
}
|
|
return value.toInt();
|
|
}
|
|
|
|
bool _requiredBool(Map<String, dynamic> json, String key) {
|
|
final value = json[key];
|
|
if (value is! bool) {
|
|
throw FormatException('Invalid or missing field: $key');
|
|
}
|
|
return value;
|
|
}
|
|
|
|
Map<String, dynamic> _requiredMap(Map<String, dynamic> json, String key) {
|
|
final value = json[key];
|
|
if (value is! Map<String, dynamic>) {
|
|
throw FormatException('Invalid or missing field: $key');
|
|
}
|
|
return value;
|
|
}
|