mingpan 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +118 -0
- package/dist/core/bazi/BaziCore.d.ts +112 -0
- package/dist/core/bazi/BaziCore.d.ts.map +1 -0
- package/dist/core/bazi/BaziCore.js +606 -0
- package/dist/core/bazi/BaziCore.js.map +1 -0
- package/dist/core/bazi/SolarTermCalculator.d.ts +46 -0
- package/dist/core/bazi/SolarTermCalculator.d.ts.map +1 -0
- package/dist/core/bazi/SolarTermCalculator.js +452 -0
- package/dist/core/bazi/SolarTermCalculator.js.map +1 -0
- package/dist/core/bazi/TrueSolarTime.d.ts +64 -0
- package/dist/core/bazi/TrueSolarTime.d.ts.map +1 -0
- package/dist/core/bazi/TrueSolarTime.js +210 -0
- package/dist/core/bazi/TrueSolarTime.js.map +1 -0
- package/dist/core/bazi/ephemerisData.d.ts +10 -0
- package/dist/core/bazi/ephemerisData.d.ts.map +1 -0
- package/dist/core/bazi/ephemerisData.js +88 -0
- package/dist/core/bazi/ephemerisData.js.map +1 -0
- package/dist/core/bazi/index.d.ts +8 -0
- package/dist/core/bazi/index.d.ts.map +1 -0
- package/dist/core/bazi/index.js +30 -0
- package/dist/core/bazi/index.js.map +1 -0
- package/dist/core/bazi/types.d.ts +116 -0
- package/dist/core/bazi/types.d.ts.map +1 -0
- package/dist/core/bazi/types.js +7 -0
- package/dist/core/bazi/types.js.map +1 -0
- package/dist/core/calendar/SolarTermsCalculator.d.ts +33 -0
- package/dist/core/calendar/SolarTermsCalculator.d.ts.map +1 -0
- package/dist/core/calendar/SolarTermsCalculator.js +111 -0
- package/dist/core/calendar/SolarTermsCalculator.js.map +1 -0
- package/dist/core/calendar/astronomicalCalendar.d.ts +74 -0
- package/dist/core/calendar/astronomicalCalendar.d.ts.map +1 -0
- package/dist/core/calendar/astronomicalCalendar.js +276 -0
- package/dist/core/calendar/astronomicalCalendar.js.map +1 -0
- package/dist/core/calendar/calendar.d.ts +81 -0
- package/dist/core/calendar/calendar.d.ts.map +1 -0
- package/dist/core/calendar/calendar.js +223 -0
- package/dist/core/calendar/calendar.js.map +1 -0
- package/dist/core/calendar/constants.d.ts +151 -0
- package/dist/core/calendar/constants.d.ts.map +1 -0
- package/dist/core/calendar/constants.js +97 -0
- package/dist/core/calendar/constants.js.map +1 -0
- package/dist/core/calendar/julian.d.ts +54 -0
- package/dist/core/calendar/julian.d.ts.map +1 -0
- package/dist/core/calendar/julian.js +142 -0
- package/dist/core/calendar/julian.js.map +1 -0
- package/dist/core/calendar/lunarCalendar.d.ts +79 -0
- package/dist/core/calendar/lunarCalendar.d.ts.map +1 -0
- package/dist/core/calendar/lunarCalendar.js +164 -0
- package/dist/core/calendar/lunarCalendar.js.map +1 -0
- package/dist/core/calendar/solarTerms.d.ts +105 -0
- package/dist/core/calendar/solarTerms.d.ts.map +1 -0
- package/dist/core/calendar/solarTerms.js +487 -0
- package/dist/core/calendar/solarTerms.js.map +1 -0
- package/dist/core/constants/bazi.d.ts +138 -0
- package/dist/core/constants/bazi.d.ts.map +1 -0
- package/dist/core/constants/bazi.js +332 -0
- package/dist/core/constants/bazi.js.map +1 -0
- package/dist/core/constants/index.d.ts +6 -0
- package/dist/core/constants/index.d.ts.map +1 -0
- package/dist/core/constants/index.js +37 -0
- package/dist/core/constants/index.js.map +1 -0
- package/dist/core/constants/positions.d.ts +27 -0
- package/dist/core/constants/positions.d.ts.map +1 -0
- package/dist/core/constants/positions.js +39 -0
- package/dist/core/constants/positions.js.map +1 -0
- package/dist/core/ziwei/BrightnessSystem.d.ts +53 -0
- package/dist/core/ziwei/BrightnessSystem.d.ts.map +1 -0
- package/dist/core/ziwei/BrightnessSystem.js +278 -0
- package/dist/core/ziwei/BrightnessSystem.js.map +1 -0
- package/dist/core/ziwei/IztroAdapter.d.ts +78 -0
- package/dist/core/ziwei/IztroAdapter.d.ts.map +1 -0
- package/dist/core/ziwei/IztroAdapter.js +314 -0
- package/dist/core/ziwei/IztroAdapter.js.map +1 -0
- package/dist/core/ziwei/MutagenCore.d.ts +81 -0
- package/dist/core/ziwei/MutagenCore.d.ts.map +1 -0
- package/dist/core/ziwei/MutagenCore.js +246 -0
- package/dist/core/ziwei/MutagenCore.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1101 -0
- package/dist/index.js.map +1 -0
- package/dist/output/fortuneTextRenderer.d.ts +63 -0
- package/dist/output/fortuneTextRenderer.d.ts.map +1 -0
- package/dist/output/fortuneTextRenderer.js +384 -0
- package/dist/output/fortuneTextRenderer.js.map +1 -0
- package/dist/output/listTextRenderer.d.ts +298 -0
- package/dist/output/listTextRenderer.d.ts.map +1 -0
- package/dist/output/listTextRenderer.js +942 -0
- package/dist/output/listTextRenderer.js.map +1 -0
- package/dist/services/bazi/BaziService.d.ts +83 -0
- package/dist/services/bazi/BaziService.d.ts.map +1 -0
- package/dist/services/bazi/BaziService.js +635 -0
- package/dist/services/bazi/BaziService.js.map +1 -0
- package/dist/services/bazi/analyzers/ClimateAnalyzer.d.ts +31 -0
- package/dist/services/bazi/analyzers/ClimateAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/ClimateAnalyzer.js +194 -0
- package/dist/services/bazi/analyzers/ClimateAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.d.ts +16 -0
- package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.js +60 -0
- package/dist/services/bazi/analyzers/HiddenStemsAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/NaYinAnalyzer.d.ts +33 -0
- package/dist/services/bazi/analyzers/NaYinAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/NaYinAnalyzer.js +209 -0
- package/dist/services/bazi/analyzers/NaYinAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/PatternAnalyzer.d.ts +159 -0
- package/dist/services/bazi/analyzers/PatternAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/PatternAnalyzer.js +1150 -0
- package/dist/services/bazi/analyzers/PatternAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/RelationsAnalyzer.d.ts +114 -0
- package/dist/services/bazi/analyzers/RelationsAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/RelationsAnalyzer.js +704 -0
- package/dist/services/bazi/analyzers/RelationsAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/ShenShaAnalyzer.d.ts +236 -0
- package/dist/services/bazi/analyzers/ShenShaAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/ShenShaAnalyzer.js +2079 -0
- package/dist/services/bazi/analyzers/ShenShaAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/StrengthAnalyzer.d.ts +181 -0
- package/dist/services/bazi/analyzers/StrengthAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/StrengthAnalyzer.js +1119 -0
- package/dist/services/bazi/analyzers/StrengthAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/TenGodsAnalyzer.d.ts +78 -0
- package/dist/services/bazi/analyzers/TenGodsAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/TenGodsAnalyzer.js +383 -0
- package/dist/services/bazi/analyzers/TenGodsAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/TraditionalAnalyzer.d.ts +46 -0
- package/dist/services/bazi/analyzers/TraditionalAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/TraditionalAnalyzer.js +260 -0
- package/dist/services/bazi/analyzers/TraditionalAnalyzer.js.map +1 -0
- package/dist/services/bazi/analyzers/YongShenAnalyzer.d.ts +70 -0
- package/dist/services/bazi/analyzers/YongShenAnalyzer.d.ts.map +1 -0
- package/dist/services/bazi/analyzers/YongShenAnalyzer.js +858 -0
- package/dist/services/bazi/analyzers/YongShenAnalyzer.js.map +1 -0
- package/dist/services/bazi/calculators/DaYunCalculator.d.ts +71 -0
- package/dist/services/bazi/calculators/DaYunCalculator.d.ts.map +1 -0
- package/dist/services/bazi/calculators/DaYunCalculator.js +496 -0
- package/dist/services/bazi/calculators/DaYunCalculator.js.map +1 -0
- package/dist/services/bazi/calculators/LiuNianCalculator.d.ts +88 -0
- package/dist/services/bazi/calculators/LiuNianCalculator.d.ts.map +1 -0
- package/dist/services/bazi/calculators/LiuNianCalculator.js +546 -0
- package/dist/services/bazi/calculators/LiuNianCalculator.js.map +1 -0
- package/dist/services/bazi/calculators/LiuRiCalculator.d.ts +66 -0
- package/dist/services/bazi/calculators/LiuRiCalculator.d.ts.map +1 -0
- package/dist/services/bazi/calculators/LiuRiCalculator.js +497 -0
- package/dist/services/bazi/calculators/LiuRiCalculator.js.map +1 -0
- package/dist/services/bazi/calculators/LiuYueCalculator.d.ts +50 -0
- package/dist/services/bazi/calculators/LiuYueCalculator.d.ts.map +1 -0
- package/dist/services/bazi/calculators/LiuYueCalculator.js +338 -0
- package/dist/services/bazi/calculators/LiuYueCalculator.js.map +1 -0
- package/dist/services/bazi/calculators/LuckCycleCalculator.d.ts +123 -0
- package/dist/services/bazi/calculators/LuckCycleCalculator.d.ts.map +1 -0
- package/dist/services/bazi/calculators/LuckCycleCalculator.js +414 -0
- package/dist/services/bazi/calculators/LuckCycleCalculator.js.map +1 -0
- package/dist/services/bazi/index.d.ts +21 -0
- package/dist/services/bazi/index.d.ts.map +1 -0
- package/dist/services/bazi/index.js +83 -0
- package/dist/services/bazi/index.js.map +1 -0
- package/dist/services/bazi/types.d.ts +597 -0
- package/dist/services/bazi/types.d.ts.map +1 -0
- package/dist/services/bazi/types.js +123 -0
- package/dist/services/bazi/types.js.map +1 -0
- package/dist/services/ziwei/ZiweiService.d.ts +86 -0
- package/dist/services/ziwei/ZiweiService.d.ts.map +1 -0
- package/dist/services/ziwei/ZiweiService.js +343 -0
- package/dist/services/ziwei/ZiweiService.js.map +1 -0
- package/dist/services/ziwei/calculators/BrightnessCalculator.d.ts +38 -0
- package/dist/services/ziwei/calculators/BrightnessCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/BrightnessCalculator.js +142 -0
- package/dist/services/ziwei/calculators/BrightnessCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/DailyCalculator.d.ts +27 -0
- package/dist/services/ziwei/calculators/DailyCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/DailyCalculator.js +55 -0
- package/dist/services/ziwei/calculators/DailyCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/DecadeCalculator.d.ts +46 -0
- package/dist/services/ziwei/calculators/DecadeCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/DecadeCalculator.js +181 -0
- package/dist/services/ziwei/calculators/DecadeCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/HoroscopeStarsCalculator.d.ts +28 -0
- package/dist/services/ziwei/calculators/HoroscopeStarsCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/HoroscopeStarsCalculator.js +84 -0
- package/dist/services/ziwei/calculators/HoroscopeStarsCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/HourlyCalculator.d.ts +41 -0
- package/dist/services/ziwei/calculators/HourlyCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/HourlyCalculator.js +139 -0
- package/dist/services/ziwei/calculators/HourlyCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/MinorLimitCalculator.d.ts +30 -0
- package/dist/services/ziwei/calculators/MinorLimitCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/MinorLimitCalculator.js +90 -0
- package/dist/services/ziwei/calculators/MinorLimitCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/MonthlyCalculator.d.ts +39 -0
- package/dist/services/ziwei/calculators/MonthlyCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/MonthlyCalculator.js +128 -0
- package/dist/services/ziwei/calculators/MonthlyCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/MutagenCalculator.d.ts +20 -0
- package/dist/services/ziwei/calculators/MutagenCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/MutagenCalculator.js +121 -0
- package/dist/services/ziwei/calculators/MutagenCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/PalaceDynamicCalculator.d.ts +35 -0
- package/dist/services/ziwei/calculators/PalaceDynamicCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/PalaceDynamicCalculator.js +55 -0
- package/dist/services/ziwei/calculators/PalaceDynamicCalculator.js.map +1 -0
- package/dist/services/ziwei/calculators/YearlyCalculator.d.ts +35 -0
- package/dist/services/ziwei/calculators/YearlyCalculator.d.ts.map +1 -0
- package/dist/services/ziwei/calculators/YearlyCalculator.js +119 -0
- package/dist/services/ziwei/calculators/YearlyCalculator.js.map +1 -0
- package/dist/services/ziwei/index.d.ts +15 -0
- package/dist/services/ziwei/index.d.ts.map +1 -0
- package/dist/services/ziwei/index.js +48 -0
- package/dist/services/ziwei/index.js.map +1 -0
- package/dist/services/ziwei/transformers/PalaceTransformer.d.ts +62 -0
- package/dist/services/ziwei/transformers/PalaceTransformer.d.ts.map +1 -0
- package/dist/services/ziwei/transformers/PalaceTransformer.js +153 -0
- package/dist/services/ziwei/transformers/PalaceTransformer.js.map +1 -0
- package/dist/services/ziwei/types.d.ts +185 -0
- package/dist/services/ziwei/types.d.ts.map +1 -0
- package/dist/services/ziwei/types.js +54 -0
- package/dist/services/ziwei/types.js.map +1 -0
- package/dist/shared/logger.d.ts +51 -0
- package/dist/shared/logger.d.ts.map +1 -0
- package/dist/shared/logger.js +136 -0
- package/dist/shared/logger.js.map +1 -0
- package/dist/shared/types.d.ts +91 -0
- package/dist/shared/types.d.ts.map +1 -0
- package/dist/shared/types.js +7 -0
- package/dist/shared/types.js.map +1 -0
- package/dist/utils/ageCalculator.d.ts +30 -0
- package/dist/utils/ageCalculator.d.ts.map +1 -0
- package/dist/utils/ageCalculator.js +51 -0
- package/dist/utils/ageCalculator.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,1150 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pattern Analyzer
|
|
4
|
+
* Implements taro-bazi's getSituation pattern recognition system
|
|
5
|
+
* Analyzes BaZi chart patterns and overall structure
|
|
6
|
+
* Returns Chinese text data for UI translation
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.PatternAnalyzer = void 0;
|
|
10
|
+
const bazi_1 = require("../../../core/constants/bazi");
|
|
11
|
+
const RelationsAnalyzer_1 = require("./RelationsAnalyzer");
|
|
12
|
+
class PatternAnalyzer {
|
|
13
|
+
/**
|
|
14
|
+
* Main pattern analysis method - implements taro-bazi's getSituation
|
|
15
|
+
*/
|
|
16
|
+
static analyze(chart, relationsResult, strengthAnalysis) {
|
|
17
|
+
// Input validation
|
|
18
|
+
if (!chart || !chart.day || !chart.day.stem) {
|
|
19
|
+
throw new Error('Invalid chart data: missing day master');
|
|
20
|
+
}
|
|
21
|
+
// If relations not provided, calculate them
|
|
22
|
+
if (!relationsResult) {
|
|
23
|
+
relationsResult = RelationsAnalyzer_1.RelationsAnalyzer.analyze(chart);
|
|
24
|
+
}
|
|
25
|
+
// Step 1: Analyze day master strength
|
|
26
|
+
const dayMasterAnalysis = strengthAnalysis
|
|
27
|
+
? this.convertStrengthAnalysis(strengthAnalysis)
|
|
28
|
+
: this.analyzeDayMasterStrength(chart, relationsResult);
|
|
29
|
+
// Validate day master analysis
|
|
30
|
+
if (!dayMasterAnalysis || dayMasterAnalysis.strength === undefined) {
|
|
31
|
+
throw new Error('Day master analysis failed: invalid strength data');
|
|
32
|
+
}
|
|
33
|
+
// Step 2: Identify primary pattern
|
|
34
|
+
const primaryPattern = this.identifyPrimaryPattern(chart, dayMasterAnalysis, relationsResult);
|
|
35
|
+
// Critical validation: ensure primaryPattern is never null
|
|
36
|
+
if (!primaryPattern) {
|
|
37
|
+
throw new Error('Failed to identify primary pattern - this should never happen');
|
|
38
|
+
}
|
|
39
|
+
// Step 3: Find secondary patterns
|
|
40
|
+
const secondaryPatterns = this.findSecondaryPatterns(chart, relationsResult);
|
|
41
|
+
// Step 4: Analyze chart structure
|
|
42
|
+
const chartStructure = this.analyzeChartStructure(chart, dayMasterAnalysis, primaryPattern);
|
|
43
|
+
// Step 5: Identify special features
|
|
44
|
+
const specialFeatures = this.identifySpecialFeatures(chart, relationsResult);
|
|
45
|
+
// Step 6: Generate recommendations
|
|
46
|
+
const recommendations = this.generateRecommendations(primaryPattern, chartStructure);
|
|
47
|
+
return {
|
|
48
|
+
primaryPattern,
|
|
49
|
+
secondaryPatterns,
|
|
50
|
+
chartStructure,
|
|
51
|
+
specialFeatures,
|
|
52
|
+
recommendations
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Analyze day master strength using taro-bazi method
|
|
57
|
+
*/
|
|
58
|
+
static analyzeDayMasterStrength(chart, relationsResult) {
|
|
59
|
+
let strength = 0;
|
|
60
|
+
const dayMaster = chart.day.stem;
|
|
61
|
+
const dayMasterElement = this.getStemElement(dayMaster);
|
|
62
|
+
const supportingElements = [];
|
|
63
|
+
const drainingElements = [];
|
|
64
|
+
// Count same element stems (比劫)
|
|
65
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.day.stem, chart.hour.stem];
|
|
66
|
+
const sameElementCount = allStems.filter(stem => this.getStemElement(stem) === dayMasterElement).length;
|
|
67
|
+
strength += sameElementCount * 8;
|
|
68
|
+
// Count generating element stems (印星)
|
|
69
|
+
const generatingElement = this.getGeneratingElement(dayMasterElement);
|
|
70
|
+
const generatingCount = allStems.filter(stem => this.getStemElement(stem) === generatingElement).length;
|
|
71
|
+
strength += generatingCount * 6;
|
|
72
|
+
if (generatingCount > 0)
|
|
73
|
+
supportingElements.push(generatingElement);
|
|
74
|
+
// Count branches that support day master
|
|
75
|
+
const allBranches = [chart.year.branch, chart.month.branch, chart.day.branch, chart.hour.branch];
|
|
76
|
+
allBranches.forEach(branch => {
|
|
77
|
+
const branchElement = this.getBranchElement(branch);
|
|
78
|
+
if (branchElement === dayMasterElement || branchElement === generatingElement) {
|
|
79
|
+
strength += 4;
|
|
80
|
+
if (!supportingElements.includes(branchElement)) {
|
|
81
|
+
supportingElements.push(branchElement);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
// Subtract draining elements
|
|
86
|
+
const controlledElement = this.getControlledElement(dayMasterElement);
|
|
87
|
+
const controllingElement = this.getControllingElement(dayMasterElement);
|
|
88
|
+
const drainingCount = allStems.filter(stem => {
|
|
89
|
+
const element = this.getStemElement(stem);
|
|
90
|
+
return element === controlledElement || element === controllingElement;
|
|
91
|
+
}).length;
|
|
92
|
+
strength -= drainingCount * 4;
|
|
93
|
+
if (drainingCount > 0) {
|
|
94
|
+
if (!drainingElements.includes(controlledElement))
|
|
95
|
+
drainingElements.push(controlledElement);
|
|
96
|
+
if (!drainingElements.includes(controllingElement))
|
|
97
|
+
drainingElements.push(controllingElement);
|
|
98
|
+
}
|
|
99
|
+
// Factor in relationships
|
|
100
|
+
const relationshipModifier = RelationsAnalyzer_1.RelationsAnalyzer.getRelationshipModifier(relationsResult);
|
|
101
|
+
strength += relationshipModifier * 10;
|
|
102
|
+
// Determine strength type
|
|
103
|
+
let type;
|
|
104
|
+
if (strength >= 80)
|
|
105
|
+
type = '极端';
|
|
106
|
+
else if (strength >= 60)
|
|
107
|
+
type = '身强';
|
|
108
|
+
else if (strength >= 40)
|
|
109
|
+
type = '平衡';
|
|
110
|
+
else
|
|
111
|
+
type = '身弱';
|
|
112
|
+
return { strength, type, supportingElements, drainingElements };
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Identify primary chart pattern
|
|
116
|
+
*/
|
|
117
|
+
static identifyPrimaryPattern(chart, dayMasterAnalysis, relationsResult) {
|
|
118
|
+
const { strength, type } = dayMasterAnalysis;
|
|
119
|
+
// Priority order of pattern detection (highest to lowest)
|
|
120
|
+
const patterns = [];
|
|
121
|
+
// 1. Check for transformation patterns (化氣格) - highest priority
|
|
122
|
+
const transformationPattern = this.checkTransformationPattern(chart, relationsResult);
|
|
123
|
+
if (transformationPattern) {
|
|
124
|
+
patterns.push({ ...transformationPattern, priority: 10 });
|
|
125
|
+
}
|
|
126
|
+
// 2. Check for follow patterns (從格)
|
|
127
|
+
const followPattern = this.checkFollowPatterns(chart, dayMasterAnalysis, relationsResult);
|
|
128
|
+
if (followPattern) {
|
|
129
|
+
patterns.push({ ...followPattern, priority: 9 });
|
|
130
|
+
}
|
|
131
|
+
// 3. Check for dominant element patterns (專旺格)
|
|
132
|
+
const dominantPattern = this.checkDominantElementPattern(chart, relationsResult);
|
|
133
|
+
if (dominantPattern) {
|
|
134
|
+
patterns.push({ ...dominantPattern, priority: 8 });
|
|
135
|
+
}
|
|
136
|
+
// 4. Check for special structures
|
|
137
|
+
const specialPattern = this.checkSpecialPatterns(chart, relationsResult);
|
|
138
|
+
if (specialPattern) {
|
|
139
|
+
patterns.push({ ...specialPattern, priority: 7 });
|
|
140
|
+
}
|
|
141
|
+
// 5. Check for traditional patterns (建祿格, 羊刃格, etc.)
|
|
142
|
+
const traditionalPattern = this.checkTraditionalPatterns(chart);
|
|
143
|
+
if (traditionalPattern) {
|
|
144
|
+
patterns.push({ ...traditionalPattern, priority: 6 });
|
|
145
|
+
}
|
|
146
|
+
// 6. Regular patterns based on day master strength
|
|
147
|
+
if (type === '身強' || type === '身强') {
|
|
148
|
+
patterns.push({
|
|
149
|
+
type: '身旺格',
|
|
150
|
+
strength: 7,
|
|
151
|
+
description: '日主強旺,精力充沛,適合主動發展',
|
|
152
|
+
priority: 5,
|
|
153
|
+
characteristics: ['精力充沛', '領導能力強']
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
else if (type === '身弱') {
|
|
157
|
+
patterns.push({
|
|
158
|
+
type: '身弱格',
|
|
159
|
+
strength: 7,
|
|
160
|
+
description: '日主較弱,需要扶助,適合穩健發展',
|
|
161
|
+
priority: 5,
|
|
162
|
+
characteristics: ['深思熟慮', '善於合作']
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
else if (type === '极端' || type === '極端') {
|
|
166
|
+
patterns.push({
|
|
167
|
+
type: '太旺格',
|
|
168
|
+
strength: 6,
|
|
169
|
+
description: '日主過旺,需要宣洩,注意平衡',
|
|
170
|
+
priority: 4,
|
|
171
|
+
characteristics: ['能量強烈', '需要平衡']
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
// 7. Default to regular pattern - ALWAYS ensure we have at least one pattern
|
|
175
|
+
if (patterns.length === 0) {
|
|
176
|
+
patterns.push({
|
|
177
|
+
type: '正格',
|
|
178
|
+
strength: 5,
|
|
179
|
+
description: '標準格局,五行較為平衡',
|
|
180
|
+
priority: 3,
|
|
181
|
+
characteristics: ['平衡穩定', '發展均衡']
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
// Return the highest priority pattern - guaranteed to exist
|
|
185
|
+
const selectedPattern = patterns.sort((a, b) => b.priority - a.priority)[0];
|
|
186
|
+
// Final safety check
|
|
187
|
+
if (!selectedPattern) {
|
|
188
|
+
// Emergency fallback - should never reach here
|
|
189
|
+
return {
|
|
190
|
+
type: '正格',
|
|
191
|
+
strength: 5,
|
|
192
|
+
description: '標準格局,五行較為平衡',
|
|
193
|
+
priority: 3,
|
|
194
|
+
characteristics: ['平衡穩定', '發展均衡']
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
return selectedPattern;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Check for follow-strong pattern (從強格)
|
|
201
|
+
*/
|
|
202
|
+
static isFollowStrongPattern(chart, relationsResult) {
|
|
203
|
+
// Day master must be extremely strong with overwhelming support
|
|
204
|
+
const dayMaster = chart.day.stem;
|
|
205
|
+
const dayMasterElement = this.getStemElement(dayMaster);
|
|
206
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.day.stem, chart.hour.stem];
|
|
207
|
+
const supportCount = allStems.filter(stem => {
|
|
208
|
+
const element = this.getStemElement(stem);
|
|
209
|
+
return element === dayMasterElement || element === this.getGeneratingElement(dayMasterElement);
|
|
210
|
+
}).length;
|
|
211
|
+
// Must have strong relationship support
|
|
212
|
+
const hasStrongSupport = relationsResult.threeHarmonies.length > 0 ||
|
|
213
|
+
relationsResult.sixHarmonies.length >= 2;
|
|
214
|
+
return supportCount >= 3 && hasStrongSupport;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Check for follow-weak pattern (從弱格)
|
|
218
|
+
*/
|
|
219
|
+
static isFollowWeakPattern(chart) {
|
|
220
|
+
const dayMaster = chart.day.stem;
|
|
221
|
+
const dayMasterElement = this.getStemElement(dayMaster);
|
|
222
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.day.stem, chart.hour.stem];
|
|
223
|
+
const supportCount = allStems.filter(stem => {
|
|
224
|
+
const element = this.getStemElement(stem);
|
|
225
|
+
return element === dayMasterElement || element === this.getGeneratingElement(dayMasterElement);
|
|
226
|
+
}).length;
|
|
227
|
+
// Day master has minimal support (only itself)
|
|
228
|
+
return supportCount <= 1;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Check for special structure patterns
|
|
232
|
+
*/
|
|
233
|
+
static isSpecialStructurePattern(chart, relationsResult) {
|
|
234
|
+
// Check for pure element combinations
|
|
235
|
+
return relationsResult.threeHarmonies.length > 0 ||
|
|
236
|
+
relationsResult.threeMeetings.length > 0 ||
|
|
237
|
+
this.hasDominantElement(chart);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Get special structure subtype
|
|
241
|
+
*/
|
|
242
|
+
static getSpecialStructureSubtype(chart, relationsResult) {
|
|
243
|
+
if (relationsResult.threeHarmonies.length > 0) {
|
|
244
|
+
const harmony = relationsResult.threeHarmonies[0];
|
|
245
|
+
return `sanHe${harmony.element}`;
|
|
246
|
+
}
|
|
247
|
+
if (relationsResult.threeMeetings.length > 0) {
|
|
248
|
+
const meeting = relationsResult.threeMeetings[0];
|
|
249
|
+
return `sanHui${meeting.element}`;
|
|
250
|
+
}
|
|
251
|
+
return 'qita';
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Check if chart has dominant element
|
|
255
|
+
*/
|
|
256
|
+
static hasDominantElement(chart) {
|
|
257
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.day.stem, chart.hour.stem];
|
|
258
|
+
const elementCounts = {};
|
|
259
|
+
allStems.forEach(stem => {
|
|
260
|
+
const element = this.getStemElement(stem);
|
|
261
|
+
elementCounts[element] = (elementCounts[element] || 0) + 1;
|
|
262
|
+
});
|
|
263
|
+
return Object.values(elementCounts).some(count => count >= 3);
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Find secondary patterns
|
|
267
|
+
*/
|
|
268
|
+
static findSecondaryPatterns(chart, relationsResult) {
|
|
269
|
+
const patterns = [];
|
|
270
|
+
// Check for noble person patterns
|
|
271
|
+
if (this.hasNoblePersonPattern(chart)) {
|
|
272
|
+
patterns.push({
|
|
273
|
+
type: '天乙貴人',
|
|
274
|
+
strength: 6,
|
|
275
|
+
description: '天乙貴人星入命,有貴人相助'
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
// Check for wealth patterns
|
|
279
|
+
if (this.hasWealthPattern(chart)) {
|
|
280
|
+
patterns.push({
|
|
281
|
+
type: '財星格',
|
|
282
|
+
strength: 5,
|
|
283
|
+
description: '財星旺盛,適合經商或理財'
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
// Check for officer patterns
|
|
287
|
+
if (this.hasOfficerPattern(chart)) {
|
|
288
|
+
patterns.push({
|
|
289
|
+
type: '官星格',
|
|
290
|
+
strength: 5,
|
|
291
|
+
description: '官星有力,適合公職或管理'
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
return patterns;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* Analyze overall chart structure
|
|
298
|
+
*/
|
|
299
|
+
static analyzeChartStructure(chart, dayMasterAnalysis, primaryPattern) {
|
|
300
|
+
const { type: dayMasterType } = dayMasterAnalysis;
|
|
301
|
+
// Determine useful and avoid gods based on pattern
|
|
302
|
+
const { usefulGods, avoidGods } = this.determineUsefulGods(chart, primaryPattern, dayMasterAnalysis);
|
|
303
|
+
// Calculate structure score
|
|
304
|
+
let structureScore = 50;
|
|
305
|
+
if (primaryPattern.strength >= 8)
|
|
306
|
+
structureScore += 20;
|
|
307
|
+
if (dayMasterType === '平衡')
|
|
308
|
+
structureScore += 15;
|
|
309
|
+
if (usefulGods.length > 0)
|
|
310
|
+
structureScore += 10;
|
|
311
|
+
// Determine balance type
|
|
312
|
+
let balanceType = '平衡';
|
|
313
|
+
if (dayMasterAnalysis.strength >= 80)
|
|
314
|
+
balanceType = '極端';
|
|
315
|
+
else if (dayMasterAnalysis.strength <= 20)
|
|
316
|
+
balanceType = '極端';
|
|
317
|
+
else if (Math.abs(dayMasterAnalysis.strength - 50) > 20)
|
|
318
|
+
balanceType = '不平衡';
|
|
319
|
+
return {
|
|
320
|
+
dayMasterType: dayMasterAnalysis.originalStrength
|
|
321
|
+
? this.mapDetailedStrengthToType(dayMasterAnalysis.originalStrength)
|
|
322
|
+
: this.mapStrengthToType(dayMasterAnalysis.type, dayMasterAnalysis.strength),
|
|
323
|
+
usefulGods,
|
|
324
|
+
avoidGods,
|
|
325
|
+
structureScore: Math.min(100, structureScore),
|
|
326
|
+
balanceType
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Convert StrengthAnalyzer result to internal format
|
|
331
|
+
*/
|
|
332
|
+
static convertStrengthAnalysis(strengthAnalysis) {
|
|
333
|
+
// Map detailed strength to basic type
|
|
334
|
+
let type;
|
|
335
|
+
const dayMasterStrength = strengthAnalysis.dayMasterStrength;
|
|
336
|
+
switch (dayMasterStrength) {
|
|
337
|
+
case '衰極':
|
|
338
|
+
case '身弱':
|
|
339
|
+
case '偏弱':
|
|
340
|
+
type = '身弱';
|
|
341
|
+
break;
|
|
342
|
+
case '中和':
|
|
343
|
+
type = '平衡';
|
|
344
|
+
break;
|
|
345
|
+
case '偏強':
|
|
346
|
+
case '身旺':
|
|
347
|
+
case '旺極':
|
|
348
|
+
type = '身強';
|
|
349
|
+
break;
|
|
350
|
+
default:
|
|
351
|
+
type = '平衡';
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
strength: strengthAnalysis.totalScore || 50,
|
|
355
|
+
type,
|
|
356
|
+
originalStrength: dayMasterStrength,
|
|
357
|
+
supportingElements: [],
|
|
358
|
+
drainingElements: []
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Map strength analysis type to display type
|
|
363
|
+
*/
|
|
364
|
+
static mapStrengthToType(type, strength) {
|
|
365
|
+
// For extreme cases, determine if it's extremely weak or strong
|
|
366
|
+
if (type === '極端') {
|
|
367
|
+
return strength <= 20 ? '身弱' : '身強';
|
|
368
|
+
}
|
|
369
|
+
// Map type to simplified categories
|
|
370
|
+
switch (type) {
|
|
371
|
+
case '身强': // 身强
|
|
372
|
+
return '身強';
|
|
373
|
+
case '身弱': // 身弱
|
|
374
|
+
return '身弱';
|
|
375
|
+
case '平衡': // 平衡
|
|
376
|
+
return '平衡';
|
|
377
|
+
default:
|
|
378
|
+
// For any other case, determine based on strength value
|
|
379
|
+
if (strength <= 40)
|
|
380
|
+
return '身弱';
|
|
381
|
+
if (strength >= 60)
|
|
382
|
+
return '身強';
|
|
383
|
+
return '平衡';
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Map detailed strength levels to display type
|
|
388
|
+
*/
|
|
389
|
+
static mapDetailedStrengthToType(strength) {
|
|
390
|
+
switch (strength) {
|
|
391
|
+
case '衰极':
|
|
392
|
+
case '身弱':
|
|
393
|
+
case '偏弱':
|
|
394
|
+
return '身弱';
|
|
395
|
+
case '中和':
|
|
396
|
+
return '平衡';
|
|
397
|
+
case '偏强':
|
|
398
|
+
case '身旺':
|
|
399
|
+
case '旺极':
|
|
400
|
+
return '身強';
|
|
401
|
+
default:
|
|
402
|
+
return '平衡'; // Default to balanced for unknown values
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Determine useful and avoid gods based on pattern type
|
|
407
|
+
* This affects YongShen determination
|
|
408
|
+
*/
|
|
409
|
+
static determineUsefulGods(chart, primaryPattern, dayMasterAnalysis) {
|
|
410
|
+
const usefulGods = [];
|
|
411
|
+
const avoidGods = [];
|
|
412
|
+
const dayMasterElement = this.getStemElement(chart.day.stem);
|
|
413
|
+
const patternType = primaryPattern.type;
|
|
414
|
+
// Pattern-specific god determination
|
|
415
|
+
switch (patternType) {
|
|
416
|
+
// Follow patterns - go with the flow
|
|
417
|
+
case '從旺格':
|
|
418
|
+
case '從強格':
|
|
419
|
+
// Support the strong trend
|
|
420
|
+
usefulGods.push(dayMasterElement);
|
|
421
|
+
usefulGods.push(this.getGeneratingElement(dayMasterElement));
|
|
422
|
+
avoidGods.push(this.getControllingElement(dayMasterElement));
|
|
423
|
+
avoidGods.push(this.getControlledElement(dayMasterElement));
|
|
424
|
+
break;
|
|
425
|
+
case '從兒格':
|
|
426
|
+
// Support output elements
|
|
427
|
+
const outputElement = this.getControlledElement(dayMasterElement);
|
|
428
|
+
usefulGods.push(outputElement);
|
|
429
|
+
usefulGods.push(this.getControlledElement(outputElement));
|
|
430
|
+
avoidGods.push(this.getControllingElement(dayMasterElement));
|
|
431
|
+
avoidGods.push(this.getGeneratingElement(dayMasterElement));
|
|
432
|
+
break;
|
|
433
|
+
case '從財格':
|
|
434
|
+
// Support wealth elements
|
|
435
|
+
const wealthElement = this.getControllingElement(this.getControlledElement(dayMasterElement));
|
|
436
|
+
usefulGods.push(wealthElement);
|
|
437
|
+
usefulGods.push(this.getControlledElement(dayMasterElement));
|
|
438
|
+
avoidGods.push(dayMasterElement);
|
|
439
|
+
avoidGods.push(this.getGeneratingElement(dayMasterElement));
|
|
440
|
+
break;
|
|
441
|
+
case '從官格':
|
|
442
|
+
// Support officer elements
|
|
443
|
+
const officerElement = this.getControllingElement(dayMasterElement);
|
|
444
|
+
usefulGods.push(officerElement);
|
|
445
|
+
usefulGods.push(this.getGeneratingElement(officerElement));
|
|
446
|
+
avoidGods.push(dayMasterElement);
|
|
447
|
+
avoidGods.push(this.getControlledElement(dayMasterElement));
|
|
448
|
+
break;
|
|
449
|
+
case '從勢格':
|
|
450
|
+
case '從弱格':
|
|
451
|
+
// Support the dominant elements in the chart
|
|
452
|
+
const elementCounts = this.countElements(chart);
|
|
453
|
+
const sortedElements = Object.entries(elementCounts)
|
|
454
|
+
.filter(([elem,]) => elem !== dayMasterElement)
|
|
455
|
+
.sort(([, a], [, b]) => b - a);
|
|
456
|
+
if (sortedElements.length > 0) {
|
|
457
|
+
usefulGods.push(sortedElements[0][0]);
|
|
458
|
+
if (sortedElements.length > 1) {
|
|
459
|
+
usefulGods.push(sortedElements[1][0]);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
avoidGods.push(dayMasterElement);
|
|
463
|
+
avoidGods.push(this.getGeneratingElement(dayMasterElement));
|
|
464
|
+
break;
|
|
465
|
+
// Transformation patterns
|
|
466
|
+
case '化氣格':
|
|
467
|
+
// Support the transformed element
|
|
468
|
+
const transformedElement = primaryPattern.subtype?.split('化氣')[1];
|
|
469
|
+
if (transformedElement) {
|
|
470
|
+
usefulGods.push(transformedElement);
|
|
471
|
+
usefulGods.push(this.getGeneratingElement(transformedElement));
|
|
472
|
+
// Avoid elements that conflict with transformation
|
|
473
|
+
avoidGods.push(this.getControllingElement(transformedElement));
|
|
474
|
+
}
|
|
475
|
+
break;
|
|
476
|
+
// Dominant element patterns
|
|
477
|
+
case '曲直格': // Wood
|
|
478
|
+
usefulGods.push('木', '水');
|
|
479
|
+
avoidGods.push('金');
|
|
480
|
+
break;
|
|
481
|
+
case '炎上格': // Fire
|
|
482
|
+
usefulGods.push('火', '木');
|
|
483
|
+
avoidGods.push('水');
|
|
484
|
+
break;
|
|
485
|
+
case '稼穡格': // Earth
|
|
486
|
+
usefulGods.push('土', '火');
|
|
487
|
+
avoidGods.push('木');
|
|
488
|
+
break;
|
|
489
|
+
case '從革格': // Metal
|
|
490
|
+
usefulGods.push('金', '土');
|
|
491
|
+
avoidGods.push('火');
|
|
492
|
+
break;
|
|
493
|
+
case '潤下格': // Water
|
|
494
|
+
usefulGods.push('水', '金');
|
|
495
|
+
avoidGods.push('土');
|
|
496
|
+
break;
|
|
497
|
+
// Traditional patterns
|
|
498
|
+
case '建祿格':
|
|
499
|
+
case '羊刃格':
|
|
500
|
+
// These patterns indicate strong day master
|
|
501
|
+
usefulGods.push(this.getControlledElement(dayMasterElement));
|
|
502
|
+
usefulGods.push(this.getControllingElement(this.getControlledElement(dayMasterElement)));
|
|
503
|
+
avoidGods.push(dayMasterElement);
|
|
504
|
+
avoidGods.push(this.getGeneratingElement(dayMasterElement));
|
|
505
|
+
break;
|
|
506
|
+
// Regular strength-based patterns
|
|
507
|
+
case '身弱格':
|
|
508
|
+
// Weak day master needs support
|
|
509
|
+
usefulGods.push(this.getGeneratingElement(dayMasterElement));
|
|
510
|
+
usefulGods.push(dayMasterElement);
|
|
511
|
+
avoidGods.push(this.getControlledElement(dayMasterElement));
|
|
512
|
+
avoidGods.push(this.getControllingElement(dayMasterElement));
|
|
513
|
+
break;
|
|
514
|
+
case '身旺格':
|
|
515
|
+
case '太旺格':
|
|
516
|
+
// Strong day master needs draining
|
|
517
|
+
usefulGods.push(this.getControlledElement(dayMasterElement));
|
|
518
|
+
usefulGods.push(this.getControllingElement(this.getControlledElement(dayMasterElement)));
|
|
519
|
+
avoidGods.push(this.getGeneratingElement(dayMasterElement));
|
|
520
|
+
avoidGods.push(dayMasterElement);
|
|
521
|
+
break;
|
|
522
|
+
default:
|
|
523
|
+
// Balanced pattern - flexible approach
|
|
524
|
+
if (dayMasterAnalysis.strength > 50) {
|
|
525
|
+
usefulGods.push(this.getControlledElement(dayMasterElement));
|
|
526
|
+
avoidGods.push(this.getGeneratingElement(dayMasterElement));
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
usefulGods.push(this.getGeneratingElement(dayMasterElement));
|
|
530
|
+
avoidGods.push(this.getControlledElement(dayMasterElement));
|
|
531
|
+
}
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
// Remove duplicates
|
|
535
|
+
return {
|
|
536
|
+
usefulGods: [...new Set(usefulGods)],
|
|
537
|
+
avoidGods: [...new Set(avoidGods)]
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
/**
|
|
541
|
+
* Identify special features
|
|
542
|
+
*/
|
|
543
|
+
static identifySpecialFeatures(chart, relationsResult) {
|
|
544
|
+
const features = [];
|
|
545
|
+
// Check for major relationship patterns
|
|
546
|
+
if (relationsResult.threeHarmonies.length > 0) {
|
|
547
|
+
features.push({
|
|
548
|
+
type: '三合',
|
|
549
|
+
description: '出現三合局,力量集中',
|
|
550
|
+
impact: '正面'
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
if (relationsResult.sixConflicts.length >= 2) {
|
|
554
|
+
features.push({
|
|
555
|
+
type: '多衝',
|
|
556
|
+
description: '出現多個衝克關係,易有動盪',
|
|
557
|
+
impact: '负面'
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
// Check for empty pillars
|
|
561
|
+
if (this.hasEmptyPillars(chart)) {
|
|
562
|
+
features.push({
|
|
563
|
+
type: '空亡',
|
|
564
|
+
description: '命中有空亡,需特別注意',
|
|
565
|
+
impact: '中性'
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
return features;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Generate pattern-based recommendations
|
|
572
|
+
*/
|
|
573
|
+
static generateRecommendations(primaryPattern, chartStructure) {
|
|
574
|
+
const favorableElements = [];
|
|
575
|
+
const unfavorableElements = [];
|
|
576
|
+
const careerSuggestions = [];
|
|
577
|
+
const lifestyleSuggestions = [];
|
|
578
|
+
// Extract elements from useful/avoid gods
|
|
579
|
+
chartStructure.usefulGods.forEach((god) => {
|
|
580
|
+
const element = god.replace('elements.', '');
|
|
581
|
+
favorableElements.push(element);
|
|
582
|
+
});
|
|
583
|
+
chartStructure.avoidGods.forEach((god) => {
|
|
584
|
+
const element = god.replace('elements.', '');
|
|
585
|
+
unfavorableElements.push(element);
|
|
586
|
+
});
|
|
587
|
+
// Pattern-specific career and lifestyle suggestions
|
|
588
|
+
const patternType = primaryPattern.type;
|
|
589
|
+
switch (patternType) {
|
|
590
|
+
// Follow patterns
|
|
591
|
+
case '從旺格':
|
|
592
|
+
case '從強格':
|
|
593
|
+
careerSuggestions.push('適合領導職位');
|
|
594
|
+
careerSuggestions.push('獨立創業');
|
|
595
|
+
careerSuggestions.push('管理經營');
|
|
596
|
+
lifestyleSuggestions.push('果斷決策');
|
|
597
|
+
lifestyleSuggestions.push('保持自信');
|
|
598
|
+
break;
|
|
599
|
+
case '從兒格':
|
|
600
|
+
careerSuggestions.push('創意產業');
|
|
601
|
+
careerSuggestions.push('藝術表演');
|
|
602
|
+
careerSuggestions.push('媒體傳播');
|
|
603
|
+
lifestyleSuggestions.push('充分表達自我');
|
|
604
|
+
lifestyleSuggestions.push('保持創新思維');
|
|
605
|
+
break;
|
|
606
|
+
case '從財格':
|
|
607
|
+
careerSuggestions.push('商業經營');
|
|
608
|
+
careerSuggestions.push('金融理財');
|
|
609
|
+
careerSuggestions.push('投資管理');
|
|
610
|
+
lifestyleSuggestions.push('講求實際');
|
|
611
|
+
lifestyleSuggestions.push('重視物質基礎');
|
|
612
|
+
break;
|
|
613
|
+
case '從官格':
|
|
614
|
+
careerSuggestions.push('公職人員');
|
|
615
|
+
careerSuggestions.push('管理階層');
|
|
616
|
+
careerSuggestions.push('法律相關');
|
|
617
|
+
lifestyleSuggestions.push('紀律嚴明');
|
|
618
|
+
lifestyleSuggestions.push('組織有序');
|
|
619
|
+
break;
|
|
620
|
+
case '從勢格':
|
|
621
|
+
case '從弱格':
|
|
622
|
+
careerSuggestions.push('支援服務');
|
|
623
|
+
careerSuggestions.push('服務業');
|
|
624
|
+
careerSuggestions.push('團隊合作');
|
|
625
|
+
lifestyleSuggestions.push('靈活適應');
|
|
626
|
+
lifestyleSuggestions.push('合作共贏');
|
|
627
|
+
break;
|
|
628
|
+
// Transformation patterns
|
|
629
|
+
case '化氣格':
|
|
630
|
+
careerSuggestions.push('專業技術');
|
|
631
|
+
careerSuggestions.push('技術研發');
|
|
632
|
+
lifestyleSuggestions.push('專注目標');
|
|
633
|
+
lifestyleSuggestions.push('不斷轉型');
|
|
634
|
+
break;
|
|
635
|
+
// Dominant element patterns
|
|
636
|
+
case '曲直格': // Wood
|
|
637
|
+
careerSuggestions.push('教育培訓');
|
|
638
|
+
careerSuggestions.push('成長發展');
|
|
639
|
+
careerSuggestions.push('環保產業');
|
|
640
|
+
lifestyleSuggestions.push('持續成長');
|
|
641
|
+
lifestyleSuggestions.push('不斷學習');
|
|
642
|
+
break;
|
|
643
|
+
case '炎上格': // Fire
|
|
644
|
+
careerSuggestions.push('娛樂表演');
|
|
645
|
+
careerSuggestions.push('科技產業');
|
|
646
|
+
careerSuggestions.push('能源產業');
|
|
647
|
+
lifestyleSuggestions.push('熱情奔放');
|
|
648
|
+
lifestyleSuggestions.push('充滿活力');
|
|
649
|
+
break;
|
|
650
|
+
case '稼穡格': // Earth
|
|
651
|
+
careerSuggestions.push('房地產業');
|
|
652
|
+
careerSuggestions.push('農業發展');
|
|
653
|
+
careerSuggestions.push('諮詢服務');
|
|
654
|
+
lifestyleSuggestions.push('穩定踏實');
|
|
655
|
+
lifestyleSuggestions.push('養育關懷');
|
|
656
|
+
break;
|
|
657
|
+
case '從革格': // Metal
|
|
658
|
+
careerSuggestions.push('工程技術');
|
|
659
|
+
careerSuggestions.push('軍事國防');
|
|
660
|
+
careerSuggestions.push('精密製造');
|
|
661
|
+
lifestyleSuggestions.push('結構嚴謹');
|
|
662
|
+
lifestyleSuggestions.push('精緷優雅');
|
|
663
|
+
break;
|
|
664
|
+
case '潤下格': // Water
|
|
665
|
+
careerSuggestions.push('傳播媒體');
|
|
666
|
+
careerSuggestions.push('物流運輸');
|
|
667
|
+
careerSuggestions.push('研究開發');
|
|
668
|
+
lifestyleSuggestions.push('靈活變通');
|
|
669
|
+
lifestyleSuggestions.push('智慧思考');
|
|
670
|
+
break;
|
|
671
|
+
// Special patterns
|
|
672
|
+
case '五行俱全格':
|
|
673
|
+
careerSuggestions.push('多元發展');
|
|
674
|
+
careerSuggestions.push('全能型人才');
|
|
675
|
+
lifestyleSuggestions.push('平衡發展');
|
|
676
|
+
lifestyleSuggestions.push('多元興趣');
|
|
677
|
+
break;
|
|
678
|
+
case '魁罡格':
|
|
679
|
+
careerSuggestions.push('領導管理');
|
|
680
|
+
careerSuggestions.push('軍警法務');
|
|
681
|
+
careerSuggestions.push('執法部門');
|
|
682
|
+
lifestyleSuggestions.push('威嚴果斷');
|
|
683
|
+
lifestyleSuggestions.push('決策果敢');
|
|
684
|
+
break;
|
|
685
|
+
// Traditional patterns
|
|
686
|
+
case '建祿格':
|
|
687
|
+
careerSuggestions.push('自主創業');
|
|
688
|
+
careerSuggestions.push('專業技能');
|
|
689
|
+
lifestyleSuggestions.push('獨立自主');
|
|
690
|
+
lifestyleSuggestions.push('自力更生');
|
|
691
|
+
break;
|
|
692
|
+
case '羊刃格':
|
|
693
|
+
careerSuggestions.push('競爭激烈行業');
|
|
694
|
+
careerSuggestions.push('體育運動');
|
|
695
|
+
careerSuggestions.push('業務銷售');
|
|
696
|
+
lifestyleSuggestions.push('積極主動');
|
|
697
|
+
lifestyleSuggestions.push('喜歡競爭');
|
|
698
|
+
break;
|
|
699
|
+
// Regular patterns
|
|
700
|
+
case '身旺格':
|
|
701
|
+
careerSuggestions.push('領導管理');
|
|
702
|
+
careerSuggestions.push('積極開拓');
|
|
703
|
+
lifestyleSuggestions.push('充滿活力');
|
|
704
|
+
lifestyleSuggestions.push('主動出擊');
|
|
705
|
+
break;
|
|
706
|
+
case '身弱格':
|
|
707
|
+
careerSuggestions.push('支援服務');
|
|
708
|
+
careerSuggestions.push('分析研究');
|
|
709
|
+
lifestyleSuggestions.push('深思熟慮');
|
|
710
|
+
lifestyleSuggestions.push('謹慎小心');
|
|
711
|
+
break;
|
|
712
|
+
default:
|
|
713
|
+
careerSuggestions.push('穩定職業');
|
|
714
|
+
careerSuggestions.push('傳統行業');
|
|
715
|
+
lifestyleSuggestions.push('平衡生活');
|
|
716
|
+
lifestyleSuggestions.push('中庸之道');
|
|
717
|
+
break;
|
|
718
|
+
}
|
|
719
|
+
// Add general suggestions based on structure score
|
|
720
|
+
if (chartStructure.structureScore < 50) {
|
|
721
|
+
lifestyleSuggestions.push('持續改善');
|
|
722
|
+
lifestyleSuggestions.push('尋求指導');
|
|
723
|
+
}
|
|
724
|
+
return {
|
|
725
|
+
favorableElements: [...new Set(favorableElements)],
|
|
726
|
+
unfavorableElements: [...new Set(unfavorableElements)],
|
|
727
|
+
careerSuggestions: [...new Set(careerSuggestions)],
|
|
728
|
+
lifestyleSuggestions: [...new Set(lifestyleSuggestions)]
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Check for transformation patterns (化氣格)
|
|
733
|
+
* Based on stem combinations with monthly branch support
|
|
734
|
+
*/
|
|
735
|
+
static checkTransformationPattern(chart, relationsResult) {
|
|
736
|
+
const dayMaster = chart.day.stem;
|
|
737
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.hour.stem];
|
|
738
|
+
const monthBranch = chart.month.branch;
|
|
739
|
+
// Transformation combinations: [stem1, stem2, supportBranches, element]
|
|
740
|
+
const transformations = [
|
|
741
|
+
['甲', '己', ['辰', '戌', '丑', '未'], '土'],
|
|
742
|
+
['乙', '庚', ['申', '酉', '戌'], '金'],
|
|
743
|
+
['丙', '辛', ['亥', '子', '丑'], '水'],
|
|
744
|
+
['丁', '壬', ['寅', '卯', '辰'], '木'],
|
|
745
|
+
['戊', '癸', ['巳', '午', '未'], '火']
|
|
746
|
+
];
|
|
747
|
+
for (const [stem1, stem2, supportBranches, element] of transformations) {
|
|
748
|
+
if (dayMaster === stem1 && allStems.includes(stem2)) {
|
|
749
|
+
if (supportBranches.includes(monthBranch)) {
|
|
750
|
+
return {
|
|
751
|
+
type: '化氣格',
|
|
752
|
+
subtype: `化氣${element}格`,
|
|
753
|
+
strength: 9,
|
|
754
|
+
description: `化為${element}氣,特殊轉化格局`,
|
|
755
|
+
priority: 10,
|
|
756
|
+
characteristics: ['轉化特質', `${element}行屬性`]
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
else if (dayMaster === stem2 && allStems.includes(stem1)) {
|
|
761
|
+
if (supportBranches.includes(monthBranch)) {
|
|
762
|
+
return {
|
|
763
|
+
type: '化氣格',
|
|
764
|
+
subtype: `化氣${element}格`,
|
|
765
|
+
strength: 9,
|
|
766
|
+
description: `化為${element}氣,特殊轉化格局`,
|
|
767
|
+
priority: 10,
|
|
768
|
+
characteristics: ['轉化特質', `${element}行屬性`]
|
|
769
|
+
};
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return null;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Check for follow patterns (從格)
|
|
777
|
+
* Including 從兒格, 從財格, 從官格, 從勢格, 從旺格
|
|
778
|
+
*/
|
|
779
|
+
static checkFollowPatterns(chart, dayMasterAnalysis, relationsResult) {
|
|
780
|
+
const dayMaster = chart.day.stem;
|
|
781
|
+
const dayMasterElement = this.getStemElement(dayMaster);
|
|
782
|
+
const { strength, supportingElements, drainingElements } = dayMasterAnalysis;
|
|
783
|
+
// Count ten gods appearances
|
|
784
|
+
const tenGodCounts = this.countTenGods(chart);
|
|
785
|
+
// 從旺格 - Follow strong pattern
|
|
786
|
+
if (strength >= 80 && supportingElements.length >= 2) {
|
|
787
|
+
return {
|
|
788
|
+
type: '從旺格',
|
|
789
|
+
strength: 9,
|
|
790
|
+
description: '日主極強,順勢而為',
|
|
791
|
+
priority: 9,
|
|
792
|
+
characteristics: ['極度強旺', '獨立自主']
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
// 從弱格 - Follow weak pattern (day master has minimal support)
|
|
796
|
+
if (strength <= 20 && supportingElements.length === 0) {
|
|
797
|
+
// Check which element is dominant to determine subtype
|
|
798
|
+
// 從兒格 - Follow output pattern
|
|
799
|
+
if (tenGodCounts['食神'] + tenGodCounts['傷官'] >= 3) {
|
|
800
|
+
return {
|
|
801
|
+
type: '從兒格',
|
|
802
|
+
strength: 9,
|
|
803
|
+
description: '食傷旺盛,從兒之格',
|
|
804
|
+
priority: 9,
|
|
805
|
+
characteristics: ['創意豐富', '表達能力強']
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
// 從財格 - Follow wealth pattern
|
|
809
|
+
if (tenGodCounts['正財'] + tenGodCounts['偏財'] >= 3) {
|
|
810
|
+
return {
|
|
811
|
+
type: '從財格',
|
|
812
|
+
strength: 9,
|
|
813
|
+
description: '財星旺盛,從財之格',
|
|
814
|
+
priority: 9,
|
|
815
|
+
characteristics: ['財運亨通', '實際務實']
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
// 從官格 - Follow officer pattern
|
|
819
|
+
if (tenGodCounts['正官'] + tenGodCounts['七殺'] >= 3) {
|
|
820
|
+
return {
|
|
821
|
+
type: '從官格',
|
|
822
|
+
strength: 9,
|
|
823
|
+
description: '官星旺盛,從官之格',
|
|
824
|
+
priority: 9,
|
|
825
|
+
characteristics: ['權威影響力', '紀律嚴明']
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
// 從勢格 - Follow trend pattern (general weak follow)
|
|
829
|
+
return {
|
|
830
|
+
type: '從勢格',
|
|
831
|
+
strength: 8,
|
|
832
|
+
description: '順從大勢,從勢之格',
|
|
833
|
+
priority: 8,
|
|
834
|
+
characteristics: ['適應力強', '善於合作']
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
/**
|
|
840
|
+
* Check for dominant element patterns (專旺格)
|
|
841
|
+
* Including 曲直格, 炎上格, 稼穡格, 從革格, 潤下格
|
|
842
|
+
*/
|
|
843
|
+
static checkDominantElementPattern(chart, relationsResult) {
|
|
844
|
+
const elementCounts = this.countElements(chart);
|
|
845
|
+
const dominantElement = Object.entries(elementCounts)
|
|
846
|
+
.sort(([, a], [, b]) => b - a)[0];
|
|
847
|
+
// Need at least 5 out of 8 positions to be the same element
|
|
848
|
+
if (dominantElement[1] >= 5) {
|
|
849
|
+
const element = dominantElement[0];
|
|
850
|
+
const patterns = {
|
|
851
|
+
'木': {
|
|
852
|
+
type: '曲直格',
|
|
853
|
+
description: '木氣純粹,曲直之格',
|
|
854
|
+
characteristics: ['生長發展', '靈活變通']
|
|
855
|
+
},
|
|
856
|
+
'火': {
|
|
857
|
+
type: '炎上格',
|
|
858
|
+
description: '火氣純粹,炎上之格',
|
|
859
|
+
characteristics: ['熱情奔放', '光明磊落']
|
|
860
|
+
},
|
|
861
|
+
'土': {
|
|
862
|
+
type: '稼穡格',
|
|
863
|
+
description: '土氣純粹,稼穡之格',
|
|
864
|
+
characteristics: ['穩定實在', '調和養育']
|
|
865
|
+
},
|
|
866
|
+
'金': {
|
|
867
|
+
type: '從革格',
|
|
868
|
+
description: '金氣純粹,從革之格',
|
|
869
|
+
characteristics: ['果敢決斷', '精緷完美']
|
|
870
|
+
},
|
|
871
|
+
'水': {
|
|
872
|
+
type: '潤下格',
|
|
873
|
+
description: '水氣純粹,潤下之格',
|
|
874
|
+
characteristics: ['流動變化', '智慧深沉']
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
if (patterns[element]) {
|
|
878
|
+
return {
|
|
879
|
+
...patterns[element],
|
|
880
|
+
strength: 9,
|
|
881
|
+
priority: 8
|
|
882
|
+
};
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
return null;
|
|
886
|
+
}
|
|
887
|
+
/**
|
|
888
|
+
* Check for special patterns
|
|
889
|
+
* Including 兩神成象格, 五行俱全格, 天元一氣格, 地支一氣格, 魁罡格, 金神格
|
|
890
|
+
*/
|
|
891
|
+
static checkSpecialPatterns(chart, relationsResult) {
|
|
892
|
+
// 五行俱全格 - All five elements present
|
|
893
|
+
const elementCounts = this.countElements(chart);
|
|
894
|
+
if (Object.keys(elementCounts).length === 5 && Object.values(elementCounts).every(count => count > 0)) {
|
|
895
|
+
return {
|
|
896
|
+
type: '五行俱全格',
|
|
897
|
+
strength: 8,
|
|
898
|
+
description: '五行俱全,各元素皆備',
|
|
899
|
+
priority: 7,
|
|
900
|
+
characteristics: ['完整無缺', '多才多藝']
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
// 兩神成象格 - Two elements dominate
|
|
904
|
+
const sortedElements = Object.entries(elementCounts)
|
|
905
|
+
.filter(([, count]) => count > 0)
|
|
906
|
+
.sort(([, a], [, b]) => b - a);
|
|
907
|
+
if (sortedElements.length === 2 && sortedElements[0][1] + sortedElements[1][1] >= 7) {
|
|
908
|
+
return {
|
|
909
|
+
type: '兩神成象格',
|
|
910
|
+
strength: 8,
|
|
911
|
+
description: '兩神成象,專精特化',
|
|
912
|
+
priority: 7,
|
|
913
|
+
characteristics: ['專注集中', '特化發展']
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
// 天元一氣格 - All heavenly stems are the same
|
|
917
|
+
const stems = [chart.year.stem, chart.month.stem, chart.day.stem, chart.hour.stem];
|
|
918
|
+
if (new Set(stems).size === 1) {
|
|
919
|
+
return {
|
|
920
|
+
type: '天元一氣格',
|
|
921
|
+
strength: 9,
|
|
922
|
+
description: '天元一氣,純粹集中',
|
|
923
|
+
priority: 8,
|
|
924
|
+
characteristics: ['純粹無雜', '高度集中']
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
// 地支一氣格 - All earthly branches are the same element
|
|
928
|
+
const branches = [chart.year.branch, chart.month.branch, chart.day.branch, chart.hour.branch];
|
|
929
|
+
const branchElements = branches.map(b => this.getBranchElement(b));
|
|
930
|
+
if (new Set(branchElements).size === 1) {
|
|
931
|
+
return {
|
|
932
|
+
type: '地支一氣格',
|
|
933
|
+
strength: 8,
|
|
934
|
+
description: '地支一氣,統一協調',
|
|
935
|
+
priority: 7,
|
|
936
|
+
characteristics: ['根基穩固', '統一協調']
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
// 魁罡格 - Day pillar is 庚辰, 庚戌, 戊辰, or 戊戌
|
|
940
|
+
const kuiGangPillars = ['庚辰', '庚戌', '戊辰', '戊戌'];
|
|
941
|
+
const dayPillar = chart.day.stem + chart.day.branch;
|
|
942
|
+
if (kuiGangPillars.includes(dayPillar)) {
|
|
943
|
+
return {
|
|
944
|
+
type: '魁罡格',
|
|
945
|
+
strength: 8,
|
|
946
|
+
description: '魁罡入命,威權顯赫',
|
|
947
|
+
priority: 7,
|
|
948
|
+
characteristics: ['權威強大', '威嚴統御']
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
// 金神格 - Specific combinations with metal elements
|
|
952
|
+
if (this.checkJinShenPattern(chart)) {
|
|
953
|
+
return {
|
|
954
|
+
type: '金神格',
|
|
955
|
+
strength: 8,
|
|
956
|
+
description: '金神入命,銳利精明',
|
|
957
|
+
priority: 7,
|
|
958
|
+
characteristics: ['銳利果敢', '策略精明']
|
|
959
|
+
};
|
|
960
|
+
}
|
|
961
|
+
return null;
|
|
962
|
+
}
|
|
963
|
+
/**
|
|
964
|
+
* Check for traditional patterns from taro-bazi
|
|
965
|
+
* Including 建祿格, 羊刃格, etc.
|
|
966
|
+
*/
|
|
967
|
+
static checkTraditionalPatterns(chart) {
|
|
968
|
+
const dayMaster = chart.day.stem;
|
|
969
|
+
const monthBranch = chart.month.branch;
|
|
970
|
+
const monthHiddenStems = this.getHiddenStems(monthBranch);
|
|
971
|
+
// 建祿格 - Day master at prosperous position
|
|
972
|
+
if (monthHiddenStems[0] === dayMaster) {
|
|
973
|
+
return {
|
|
974
|
+
type: '建祿格',
|
|
975
|
+
strength: 8,
|
|
976
|
+
description: '月支帶祿,自力更生',
|
|
977
|
+
priority: 6,
|
|
978
|
+
characteristics: ['自力更生', '能力出眾']
|
|
979
|
+
};
|
|
980
|
+
}
|
|
981
|
+
// 羊刃格 - Yang blade pattern
|
|
982
|
+
const yangBladeMap = {
|
|
983
|
+
'甲': '卯', '丙': '午', '戊': '午', '庚': '酉', '壬': '子'
|
|
984
|
+
};
|
|
985
|
+
if (yangBladeMap[dayMaster] === monthBranch) {
|
|
986
|
+
return {
|
|
987
|
+
type: '羊刃格',
|
|
988
|
+
strength: 8,
|
|
989
|
+
description: '月支為刃,剛強威猛',
|
|
990
|
+
priority: 6,
|
|
991
|
+
characteristics: ['剛強進取', '競爭力強']
|
|
992
|
+
};
|
|
993
|
+
}
|
|
994
|
+
return null;
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Count ten gods appearances in the chart
|
|
998
|
+
*/
|
|
999
|
+
static countTenGods(chart) {
|
|
1000
|
+
const counts = {
|
|
1001
|
+
'比肩': 0, '劫財': 0, '食神': 0, '傷官': 0,
|
|
1002
|
+
'正財': 0, '偏財': 0, '正官': 0, '七殺': 0,
|
|
1003
|
+
'正印': 0, '偏印': 0
|
|
1004
|
+
};
|
|
1005
|
+
const dayMaster = chart.day.stem;
|
|
1006
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.hour.stem];
|
|
1007
|
+
const allBranches = [chart.year.branch, chart.month.branch, chart.day.branch, chart.hour.branch];
|
|
1008
|
+
// Count stems
|
|
1009
|
+
allStems.forEach(stem => {
|
|
1010
|
+
const tenGod = bazi_1.TEN_GODS[dayMaster]?.[stem];
|
|
1011
|
+
if (tenGod && counts[tenGod] !== undefined) {
|
|
1012
|
+
counts[tenGod]++;
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
1015
|
+
// Count hidden stems in branches
|
|
1016
|
+
allBranches.forEach(branch => {
|
|
1017
|
+
const hiddenStems = this.getHiddenStems(branch);
|
|
1018
|
+
hiddenStems.forEach(stem => {
|
|
1019
|
+
const tenGod = bazi_1.TEN_GODS[dayMaster]?.[stem];
|
|
1020
|
+
if (tenGod && counts[tenGod] !== undefined) {
|
|
1021
|
+
counts[tenGod]++;
|
|
1022
|
+
}
|
|
1023
|
+
});
|
|
1024
|
+
});
|
|
1025
|
+
return counts;
|
|
1026
|
+
}
|
|
1027
|
+
/**
|
|
1028
|
+
* Count elements in the chart
|
|
1029
|
+
*/
|
|
1030
|
+
static countElements(chart) {
|
|
1031
|
+
const counts = {
|
|
1032
|
+
'木': 0, '火': 0, '土': 0, '金': 0, '水': 0
|
|
1033
|
+
};
|
|
1034
|
+
// Count stem elements
|
|
1035
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.day.stem, chart.hour.stem];
|
|
1036
|
+
allStems.forEach(stem => {
|
|
1037
|
+
const element = this.getStemElement(stem);
|
|
1038
|
+
if (element)
|
|
1039
|
+
counts[element]++;
|
|
1040
|
+
});
|
|
1041
|
+
// Count branch elements
|
|
1042
|
+
const allBranches = [chart.year.branch, chart.month.branch, chart.day.branch, chart.hour.branch];
|
|
1043
|
+
allBranches.forEach(branch => {
|
|
1044
|
+
const element = this.getBranchElement(branch);
|
|
1045
|
+
if (element)
|
|
1046
|
+
counts[element]++;
|
|
1047
|
+
});
|
|
1048
|
+
return counts;
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Check for Jin Shen pattern
|
|
1052
|
+
*/
|
|
1053
|
+
static checkJinShenPattern(chart) {
|
|
1054
|
+
// Jin Shen pattern requires specific day pillars with metal dominance
|
|
1055
|
+
const jinShenDays = ['乙丑', '己巳', '癸酉'];
|
|
1056
|
+
const dayPillar = chart.day.stem + chart.day.branch;
|
|
1057
|
+
if (!jinShenDays.includes(dayPillar))
|
|
1058
|
+
return false;
|
|
1059
|
+
// Count metal elements
|
|
1060
|
+
const elementCounts = this.countElements(chart);
|
|
1061
|
+
return elementCounts['金'] >= 3;
|
|
1062
|
+
}
|
|
1063
|
+
/**
|
|
1064
|
+
* Get hidden stems for a branch
|
|
1065
|
+
*/
|
|
1066
|
+
static getHiddenStems(branch) {
|
|
1067
|
+
const hiddenStemsMap = {
|
|
1068
|
+
'子': ['癸'],
|
|
1069
|
+
'丑': ['己', '癸', '辛'],
|
|
1070
|
+
'寅': ['甲', '丙', '戊'],
|
|
1071
|
+
'卯': ['乙'],
|
|
1072
|
+
'辰': ['戊', '乙', '癸'],
|
|
1073
|
+
'巳': ['丙', '戊', '庚'],
|
|
1074
|
+
'午': ['丁', '己'],
|
|
1075
|
+
'未': ['己', '丁', '乙'],
|
|
1076
|
+
'申': ['庚', '壬', '戊'],
|
|
1077
|
+
'酉': ['辛'],
|
|
1078
|
+
'戌': ['戊', '辛', '丁'],
|
|
1079
|
+
'亥': ['壬', '甲']
|
|
1080
|
+
};
|
|
1081
|
+
return hiddenStemsMap[branch] || [];
|
|
1082
|
+
}
|
|
1083
|
+
// Helper methods
|
|
1084
|
+
static hasNoblePersonPattern(chart) {
|
|
1085
|
+
// Implementation for noble person star detection
|
|
1086
|
+
// This would check for specific combinations that indicate noble person stars
|
|
1087
|
+
const dayMaster = chart.day.stem;
|
|
1088
|
+
const dayBranch = chart.day.branch;
|
|
1089
|
+
// Simplified noble person detection based on day master
|
|
1090
|
+
const noblePersonMap = {
|
|
1091
|
+
'甲': ['丑', '未'], '戊': ['丑', '未'],
|
|
1092
|
+
'乙': ['子', '申'], '己': ['子', '申'],
|
|
1093
|
+
'丙': ['亥', '酉'], '丁': ['亥', '酉'],
|
|
1094
|
+
'庚': ['寅', '午'], '辛': ['寅', '午'],
|
|
1095
|
+
'壬': ['卯', '巳'], '癸': ['卯', '巳']
|
|
1096
|
+
};
|
|
1097
|
+
const nobleBranches = noblePersonMap[dayMaster] || [];
|
|
1098
|
+
const allBranches = [chart.year.branch, chart.month.branch, chart.hour.branch];
|
|
1099
|
+
return allBranches.some(branch => nobleBranches.includes(branch));
|
|
1100
|
+
}
|
|
1101
|
+
static hasWealthPattern(chart) {
|
|
1102
|
+
const dayMaster = chart.day.stem;
|
|
1103
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.hour.stem];
|
|
1104
|
+
return allStems.some(stem => {
|
|
1105
|
+
const tenGod = bazi_1.TEN_GODS[dayMaster]?.[stem];
|
|
1106
|
+
return tenGod === '正財' || tenGod === '偏財';
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
static hasOfficerPattern(chart) {
|
|
1110
|
+
const dayMaster = chart.day.stem;
|
|
1111
|
+
const allStems = [chart.year.stem, chart.month.stem, chart.hour.stem];
|
|
1112
|
+
return allStems.some(stem => {
|
|
1113
|
+
const tenGod = bazi_1.TEN_GODS[dayMaster]?.[stem];
|
|
1114
|
+
return tenGod === '正官' || tenGod === '七殺';
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
static hasEmptyPillars(chart) {
|
|
1118
|
+
// Check for missing elements or weak pillars
|
|
1119
|
+
return false; // Simplified
|
|
1120
|
+
}
|
|
1121
|
+
// Element relationship helpers
|
|
1122
|
+
static getStemElement(stem) {
|
|
1123
|
+
const stemData = bazi_1.HEAVENLY_STEMS.find(s => s.name === stem);
|
|
1124
|
+
return stemData?.element || '';
|
|
1125
|
+
}
|
|
1126
|
+
static getBranchElement(branch) {
|
|
1127
|
+
const branchData = bazi_1.EARTHLY_BRANCHES.find(b => b.name === branch);
|
|
1128
|
+
return branchData?.element || '';
|
|
1129
|
+
}
|
|
1130
|
+
static getGeneratingElement(element) {
|
|
1131
|
+
const cycle = {
|
|
1132
|
+
'水': '金', '木': '水', '火': '木', '土': '火', '金': '土'
|
|
1133
|
+
};
|
|
1134
|
+
return cycle[element] || '';
|
|
1135
|
+
}
|
|
1136
|
+
static getControlledElement(element) {
|
|
1137
|
+
const cycle = {
|
|
1138
|
+
'木': '火', '火': '土', '土': '金', '金': '水', '水': '木'
|
|
1139
|
+
};
|
|
1140
|
+
return cycle[element] || '';
|
|
1141
|
+
}
|
|
1142
|
+
static getControllingElement(element) {
|
|
1143
|
+
const cycle = {
|
|
1144
|
+
'木': '金', '火': '水', '土': '木', '金': '火', '水': '土'
|
|
1145
|
+
};
|
|
1146
|
+
return cycle[element] || '';
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
exports.PatternAnalyzer = PatternAnalyzer;
|
|
1150
|
+
//# sourceMappingURL=PatternAnalyzer.js.map
|