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,704 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Relations Analyzer
|
|
4
|
+
* Comprehensive stem and branch relation system from taro-bazi
|
|
5
|
+
* Implements complete Heavenly Stem Combinations and Earthly Branch Relations
|
|
6
|
+
* Returns language-agnostic data with translation keys for internationalization
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.RelationsAnalyzer = void 0;
|
|
10
|
+
const positions_1 = require("../../../core/constants/positions");
|
|
11
|
+
class RelationsAnalyzer {
|
|
12
|
+
// Position indices for distance calculation
|
|
13
|
+
static POSITION_INDEX = positions_1.POSITION_INDICES;
|
|
14
|
+
/**
|
|
15
|
+
* Calculate relation type based on positions
|
|
16
|
+
* Returns positional relationship (相/隔/遥/争/双) and spacing
|
|
17
|
+
*/
|
|
18
|
+
static getRelationByPosition(positions1, positions2) {
|
|
19
|
+
// 转换中文位置名称为内部键
|
|
20
|
+
const convertedPositions1 = positions1.map(pos => {
|
|
21
|
+
const key = (0, positions_1.getPositionKeyByName)(pos);
|
|
22
|
+
return key || pos; // 如果已经是英文键则保持不变
|
|
23
|
+
});
|
|
24
|
+
const convertedPositions2 = positions2.map(pos => {
|
|
25
|
+
const key = (0, positions_1.getPositionKeyByName)(pos);
|
|
26
|
+
return key || pos;
|
|
27
|
+
});
|
|
28
|
+
const totalCount = convertedPositions1.length + convertedPositions2.length;
|
|
29
|
+
if (totalCount === 2) {
|
|
30
|
+
const idx1 = this.POSITION_INDEX[convertedPositions1[0]];
|
|
31
|
+
const idx2 = this.POSITION_INDEX[convertedPositions2[0]];
|
|
32
|
+
const spacing = Math.abs(idx1 - idx2);
|
|
33
|
+
if (spacing === 1)
|
|
34
|
+
return { positionType: '相', spacing }; // Adjacent
|
|
35
|
+
if (spacing === 2)
|
|
36
|
+
return { positionType: '隔', spacing }; // Separated
|
|
37
|
+
if (spacing === 3)
|
|
38
|
+
return { positionType: '遥', spacing }; // Distant
|
|
39
|
+
}
|
|
40
|
+
else if (totalCount === 3) {
|
|
41
|
+
// One side has 2, other has 1
|
|
42
|
+
const multiPositions = convertedPositions1.length > 1 ? convertedPositions1 : convertedPositions2;
|
|
43
|
+
const singlePosition = convertedPositions1.length === 1 ? convertedPositions1[0] : convertedPositions2[0];
|
|
44
|
+
const idx1 = this.POSITION_INDEX[multiPositions[0]];
|
|
45
|
+
const idx2 = this.POSITION_INDEX[multiPositions[1]];
|
|
46
|
+
const idx3 = this.POSITION_INDEX[singlePosition];
|
|
47
|
+
const spacing1 = Math.abs(idx1 - idx3);
|
|
48
|
+
const spacing2 = Math.abs(idx2 - idx3);
|
|
49
|
+
if (spacing1 === 1 && spacing2 === 1) {
|
|
50
|
+
return { positionType: '争', spacing: 1 }; // Competing
|
|
51
|
+
}
|
|
52
|
+
else if (spacing1 === 1 || spacing2 === 1) {
|
|
53
|
+
return { positionType: '相', spacing: 1 }; // Adjacent
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
return { positionType: '遥', spacing: Math.min(spacing1, spacing2) };
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (totalCount === 4) {
|
|
60
|
+
if (convertedPositions1.length === convertedPositions2.length) {
|
|
61
|
+
const idx1 = this.POSITION_INDEX[convertedPositions1[0]];
|
|
62
|
+
const idx2 = this.POSITION_INDEX[convertedPositions1[1]];
|
|
63
|
+
const spacing = Math.abs(idx1 - idx2);
|
|
64
|
+
if (spacing === 1)
|
|
65
|
+
return { positionType: '相', spacing };
|
|
66
|
+
return { positionType: '双', spacing }; // Double
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
const singlePosition = convertedPositions1.length === 1 ? convertedPositions1[0] : convertedPositions2[0];
|
|
70
|
+
const idx = this.POSITION_INDEX[singlePosition];
|
|
71
|
+
if (idx === 1 || idx === 2) { // Month or Day position
|
|
72
|
+
return { positionType: '相', spacing: 1 };
|
|
73
|
+
}
|
|
74
|
+
return { positionType: '争', spacing: 1 };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return { positionType: '遥', spacing: 3 };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Apply position strength modifier based on position type
|
|
81
|
+
* Adjacent relations are stronger, distant ones are weaker
|
|
82
|
+
*/
|
|
83
|
+
static applyPositionModifier(baseStrength, positionType) {
|
|
84
|
+
switch (positionType) {
|
|
85
|
+
case '相': // Adjacent - full strength
|
|
86
|
+
return baseStrength;
|
|
87
|
+
case '争': // Competing - slightly reduced (multiple branches competing)
|
|
88
|
+
return Math.round(baseStrength * 0.9);
|
|
89
|
+
case '双': // Double - slightly enhanced (reinforced relationship)
|
|
90
|
+
return Math.min(10, Math.round(baseStrength * 1.1));
|
|
91
|
+
case '隔': // Separated - moderately reduced
|
|
92
|
+
return Math.round(baseStrength * 0.8);
|
|
93
|
+
case '遥': // Distant - more reduced but still significant
|
|
94
|
+
return Math.round(baseStrength * 0.6);
|
|
95
|
+
default:
|
|
96
|
+
return baseStrength;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Comprehensive analysis of all stem and branch relationships using taro-bazi system
|
|
101
|
+
*/
|
|
102
|
+
static analyze(chart) {
|
|
103
|
+
const stems = [
|
|
104
|
+
{ stem: chart.year.stem, position: '年柱' },
|
|
105
|
+
{ stem: chart.month.stem, position: '月柱' },
|
|
106
|
+
{ stem: chart.day.stem, position: '日柱' },
|
|
107
|
+
{ stem: chart.hour.stem, position: '時柱' }
|
|
108
|
+
];
|
|
109
|
+
const branches = [
|
|
110
|
+
{ branch: chart.year.branch, position: '年柱' },
|
|
111
|
+
{ branch: chart.month.branch, position: '月柱' },
|
|
112
|
+
{ branch: chart.day.branch, position: '日柱' },
|
|
113
|
+
{ branch: chart.hour.branch, position: '時柱' }
|
|
114
|
+
];
|
|
115
|
+
const result = {
|
|
116
|
+
// Heavenly Stem Relations
|
|
117
|
+
stemCombinations: this.findStemCombinations(stems),
|
|
118
|
+
// Earthly Branch Relations
|
|
119
|
+
sixHarmonies: this.findSixHarmonies(branches),
|
|
120
|
+
sixConflicts: this.findSixConflicts(branches),
|
|
121
|
+
sixHarms: this.findSixHarms(branches),
|
|
122
|
+
threePunishments: this.findThreePunishments(branches),
|
|
123
|
+
threeHarmonies: this.findThreeHarmonies(branches),
|
|
124
|
+
sixDestructions: this.findSixDestructions(branches),
|
|
125
|
+
threeMeetings: this.findThreeMeetings(branches),
|
|
126
|
+
overview: {
|
|
127
|
+
totalRelations: 0,
|
|
128
|
+
positiveCount: 0,
|
|
129
|
+
negativeCount: 0,
|
|
130
|
+
dominantPattern: '',
|
|
131
|
+
harmonyScore: 0,
|
|
132
|
+
hasStemCombinations: false
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
// Calculate overview statistics
|
|
136
|
+
result.overview = this.calculateOverview(result);
|
|
137
|
+
return result;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Heavenly Stem Five Combinations (天干五合)
|
|
141
|
+
* Based on the reference document 八字教程-冲合刑害会.md
|
|
142
|
+
*/
|
|
143
|
+
static findStemCombinations(stems) {
|
|
144
|
+
const combinations = [];
|
|
145
|
+
// Five combination pairs with their resulting elements and meanings
|
|
146
|
+
const fiveCombinationPairs = [
|
|
147
|
+
{
|
|
148
|
+
stems: ['甲', '己'],
|
|
149
|
+
element: '土',
|
|
150
|
+
strength: 8,
|
|
151
|
+
description: '甲己合化土',
|
|
152
|
+
meaning: '中正之合' // 中正之合
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
stems: ['乙', '庚'],
|
|
156
|
+
element: '金',
|
|
157
|
+
strength: 8,
|
|
158
|
+
description: '乙庚合化金',
|
|
159
|
+
meaning: '仁義之合' // 仁義之合
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
stems: ['丙', '辛'],
|
|
163
|
+
element: '水',
|
|
164
|
+
strength: 7,
|
|
165
|
+
description: '丙辛合化水',
|
|
166
|
+
meaning: '威制之合' // 威制之合
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
stems: ['丁', '壬'],
|
|
170
|
+
element: '木',
|
|
171
|
+
strength: 6,
|
|
172
|
+
description: '丁壬合化木',
|
|
173
|
+
meaning: '淫慝之合' // 淫慝之合
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
stems: ['戊', '癸'],
|
|
177
|
+
element: '火',
|
|
178
|
+
strength: 6,
|
|
179
|
+
description: '戊癸合化火',
|
|
180
|
+
meaning: '無情之合' // 無情之合
|
|
181
|
+
}
|
|
182
|
+
];
|
|
183
|
+
for (const combination of fiveCombinationPairs) {
|
|
184
|
+
const found1 = stems.find(s => s.stem === combination.stems[0]);
|
|
185
|
+
const found2 = stems.find(s => s.stem === combination.stems[1]);
|
|
186
|
+
if (found1 && found2) {
|
|
187
|
+
combinations.push({
|
|
188
|
+
stems: [found1.stem, found2.stem],
|
|
189
|
+
positions: [found1.position, found2.position],
|
|
190
|
+
type: 'fiveCombination',
|
|
191
|
+
element: combination.element,
|
|
192
|
+
impact: '正面',
|
|
193
|
+
strength: combination.strength,
|
|
194
|
+
description: combination.description,
|
|
195
|
+
meaning: combination.meaning
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return combinations;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Six Harmonies (六合) - Most favorable relationships
|
|
203
|
+
* Precise implementation from taro-bazi
|
|
204
|
+
*/
|
|
205
|
+
static findSixHarmonies(branches) {
|
|
206
|
+
const harmonies = [];
|
|
207
|
+
// Taro-bazi's exact six harmony pairs with their elements
|
|
208
|
+
const sixHarmonyPairs = [
|
|
209
|
+
{ branches: ['子', '丑'], element: '土', strength: 8, description: '子丑合化土' },
|
|
210
|
+
{ branches: ['寅', '亥'], element: '木', strength: 9, description: '寅亥合化木' },
|
|
211
|
+
{ branches: ['卯', '戌'], element: '火', strength: 7, description: '卯戌合化火' },
|
|
212
|
+
{ branches: ['辰', '酉'], element: '金', strength: 8, description: '辰酉合化金' },
|
|
213
|
+
{ branches: ['巳', '申'], element: '水', strength: 6, description: '巳申合化水' },
|
|
214
|
+
{ branches: ['午', '未'], element: '火', strength: 9, description: '午未合化火' }
|
|
215
|
+
];
|
|
216
|
+
for (const harmony of sixHarmonyPairs) {
|
|
217
|
+
const found1 = branches.find(b => b.branch === harmony.branches[0]);
|
|
218
|
+
const found2 = branches.find(b => b.branch === harmony.branches[1]);
|
|
219
|
+
if (found1 && found2) {
|
|
220
|
+
const { positionType, spacing } = this.getRelationByPosition([found1.position], [found2.position]);
|
|
221
|
+
harmonies.push({
|
|
222
|
+
branches: [found1.branch, found2.branch],
|
|
223
|
+
positions: [found1.position, found2.position],
|
|
224
|
+
type: 'sixHarmony',
|
|
225
|
+
impact: '正面',
|
|
226
|
+
strength: this.applyPositionModifier(harmony.strength, positionType),
|
|
227
|
+
element: harmony.element,
|
|
228
|
+
description: harmony.description,
|
|
229
|
+
positionType,
|
|
230
|
+
spacing
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return harmonies;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Six Conflicts (六沖) - Direct opposition relationships
|
|
238
|
+
*/
|
|
239
|
+
static findSixConflicts(branches) {
|
|
240
|
+
const conflicts = [];
|
|
241
|
+
const sixConflictPairs = [
|
|
242
|
+
{ branches: ['子', '午'], strength: 10, description: '子午相沖' },
|
|
243
|
+
{ branches: ['丑', '未'], strength: 8, description: '丑未相沖' },
|
|
244
|
+
{ branches: ['寅', '申'], strength: 9, description: '寅申相沖' },
|
|
245
|
+
{ branches: ['卯', '酉'], strength: 9, description: '卯酉相沖' },
|
|
246
|
+
{ branches: ['辰', '戌'], strength: 7, description: '辰戌相沖' },
|
|
247
|
+
{ branches: ['巳', '亥'], strength: 8, description: '巳亥相沖' }
|
|
248
|
+
];
|
|
249
|
+
for (const conflict of sixConflictPairs) {
|
|
250
|
+
const found1 = branches.find(b => b.branch === conflict.branches[0]);
|
|
251
|
+
const found2 = branches.find(b => b.branch === conflict.branches[1]);
|
|
252
|
+
if (found1 && found2) {
|
|
253
|
+
const { positionType, spacing } = this.getRelationByPosition([found1.position], [found2.position]);
|
|
254
|
+
conflicts.push({
|
|
255
|
+
branches: [found1.branch, found2.branch],
|
|
256
|
+
positions: [found1.position, found2.position],
|
|
257
|
+
type: 'sixConflict',
|
|
258
|
+
impact: '负面',
|
|
259
|
+
strength: this.applyPositionModifier(conflict.strength, positionType),
|
|
260
|
+
description: conflict.description,
|
|
261
|
+
positionType,
|
|
262
|
+
spacing
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return conflicts;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Six Harms (六害) - Mutual harm relationships
|
|
270
|
+
*/
|
|
271
|
+
static findSixHarms(branches) {
|
|
272
|
+
const harms = [];
|
|
273
|
+
const sixHarmPairs = [
|
|
274
|
+
{ branches: ['子', '未'], strength: 7, description: '子未相害' },
|
|
275
|
+
{ branches: ['丑', '午'], strength: 6, description: '丑午相害' },
|
|
276
|
+
{ branches: ['寅', '巳'], strength: 8, description: '寅巳相害' },
|
|
277
|
+
{ branches: ['卯', '辰'], strength: 5, description: '卯辰相害' },
|
|
278
|
+
{ branches: ['申', '亥'], strength: 7, description: '申亥相害' },
|
|
279
|
+
{ branches: ['酉', '戌'], strength: 6, description: '酉戌相害' }
|
|
280
|
+
];
|
|
281
|
+
for (const harm of sixHarmPairs) {
|
|
282
|
+
const found1 = branches.find(b => b.branch === harm.branches[0]);
|
|
283
|
+
const found2 = branches.find(b => b.branch === harm.branches[1]);
|
|
284
|
+
if (found1 && found2) {
|
|
285
|
+
const { positionType, spacing } = this.getRelationByPosition([found1.position], [found2.position]);
|
|
286
|
+
harms.push({
|
|
287
|
+
branches: [found1.branch, found2.branch],
|
|
288
|
+
positions: [found1.position, found2.position],
|
|
289
|
+
type: 'sixHarm',
|
|
290
|
+
impact: '负面',
|
|
291
|
+
strength: this.applyPositionModifier(harm.strength, positionType),
|
|
292
|
+
description: harm.description,
|
|
293
|
+
positionType,
|
|
294
|
+
spacing
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
return harms;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Three Punishments (三刑) - Complex punishment relationships
|
|
302
|
+
* Implements taro-bazi's complete punishment system
|
|
303
|
+
*/
|
|
304
|
+
static findThreePunishments(branches) {
|
|
305
|
+
const punishments = [];
|
|
306
|
+
// Self punishments (自刑)
|
|
307
|
+
const selfPunishments = ['辰', '午', '酉', '亥'];
|
|
308
|
+
for (const selfBranch of selfPunishments) {
|
|
309
|
+
const found = branches.filter(b => b.branch === selfBranch);
|
|
310
|
+
if (found.length > 1) {
|
|
311
|
+
// For self punishments, we analyze pairs
|
|
312
|
+
for (let i = 0; i < found.length - 1; i++) {
|
|
313
|
+
for (let j = i + 1; j < found.length; j++) {
|
|
314
|
+
const { positionType, spacing } = this.getRelationByPosition([found[i].position], [found[j].position]);
|
|
315
|
+
punishments.push({
|
|
316
|
+
branches: [found[i].branch, found[j].branch],
|
|
317
|
+
positions: [found[i].position, found[j].position],
|
|
318
|
+
type: 'threePunishment',
|
|
319
|
+
subtype: 'selfPunishment',
|
|
320
|
+
impact: '负面',
|
|
321
|
+
strength: this.applyPositionModifier(6, positionType),
|
|
322
|
+
description: `${selfBranch}${selfBranch}自刑`,
|
|
323
|
+
positionType,
|
|
324
|
+
spacing
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
// Ungrateful punishment (無恩之刑): 子-卯
|
|
331
|
+
const zi = branches.find(b => b.branch === '子');
|
|
332
|
+
const mao = branches.find(b => b.branch === '卯');
|
|
333
|
+
if (zi && mao) {
|
|
334
|
+
const { positionType, spacing } = this.getRelationByPosition([zi.position], [mao.position]);
|
|
335
|
+
punishments.push({
|
|
336
|
+
branches: [zi.branch, mao.branch],
|
|
337
|
+
positions: [zi.position, mao.position],
|
|
338
|
+
type: 'threePunishment',
|
|
339
|
+
subtype: 'ungratefulPunishment',
|
|
340
|
+
impact: '负面',
|
|
341
|
+
strength: this.applyPositionModifier(8, positionType),
|
|
342
|
+
description: '子卯無恩之刑',
|
|
343
|
+
positionType,
|
|
344
|
+
spacing
|
|
345
|
+
});
|
|
346
|
+
}
|
|
347
|
+
// Bullying punishment (恃勢之刑): 寅巳相刑, 巳申相刑, 申寅相刑
|
|
348
|
+
const yin = branches.find(b => b.branch === '寅');
|
|
349
|
+
const si = branches.find(b => b.branch === '巳');
|
|
350
|
+
const shen = branches.find(b => b.branch === '申');
|
|
351
|
+
// Check each punishment pair separately
|
|
352
|
+
if (yin && si) {
|
|
353
|
+
const { positionType, spacing } = this.getRelationByPosition([yin.position], [si.position]);
|
|
354
|
+
punishments.push({
|
|
355
|
+
branches: [yin.branch, si.branch],
|
|
356
|
+
positions: [yin.position, si.position],
|
|
357
|
+
type: 'threePunishment',
|
|
358
|
+
subtype: 'bullyingPunishment',
|
|
359
|
+
impact: '负面',
|
|
360
|
+
strength: this.applyPositionModifier(8, positionType),
|
|
361
|
+
description: '寅巳恃勢之刑',
|
|
362
|
+
positionType,
|
|
363
|
+
spacing
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
if (si && shen) {
|
|
367
|
+
const { positionType, spacing } = this.getRelationByPosition([si.position], [shen.position]);
|
|
368
|
+
punishments.push({
|
|
369
|
+
branches: [si.branch, shen.branch],
|
|
370
|
+
positions: [si.position, shen.position],
|
|
371
|
+
type: 'threePunishment',
|
|
372
|
+
subtype: 'bullyingPunishment',
|
|
373
|
+
impact: '负面',
|
|
374
|
+
strength: this.applyPositionModifier(8, positionType),
|
|
375
|
+
description: '巳申恃勢之刑',
|
|
376
|
+
positionType,
|
|
377
|
+
spacing
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
if (shen && yin) {
|
|
381
|
+
const { positionType, spacing } = this.getRelationByPosition([shen.position], [yin.position]);
|
|
382
|
+
punishments.push({
|
|
383
|
+
branches: [shen.branch, yin.branch],
|
|
384
|
+
positions: [shen.position, yin.position],
|
|
385
|
+
type: 'threePunishment',
|
|
386
|
+
subtype: 'bullyingPunishment',
|
|
387
|
+
impact: '负面',
|
|
388
|
+
strength: this.applyPositionModifier(8, positionType),
|
|
389
|
+
description: '申寅恃勢之刑',
|
|
390
|
+
positionType,
|
|
391
|
+
spacing
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
// Uncivilized punishment (無禮之刑): 丑戌相刑, 戌未相刑, 未丑相刑
|
|
395
|
+
const chou = branches.find(b => b.branch === '丑');
|
|
396
|
+
const xu = branches.find(b => b.branch === '戌');
|
|
397
|
+
const wei = branches.find(b => b.branch === '未');
|
|
398
|
+
// Check each punishment pair separately
|
|
399
|
+
if (chou && xu) {
|
|
400
|
+
const { positionType, spacing } = this.getRelationByPosition([chou.position], [xu.position]);
|
|
401
|
+
punishments.push({
|
|
402
|
+
branches: [chou.branch, xu.branch],
|
|
403
|
+
positions: [chou.position, xu.position],
|
|
404
|
+
type: 'threePunishment',
|
|
405
|
+
subtype: 'uncivilizedPunishment',
|
|
406
|
+
impact: '负面',
|
|
407
|
+
strength: this.applyPositionModifier(7, positionType),
|
|
408
|
+
description: '丑戌無禮之刑',
|
|
409
|
+
positionType,
|
|
410
|
+
spacing
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
if (xu && wei) {
|
|
414
|
+
const { positionType, spacing } = this.getRelationByPosition([xu.position], [wei.position]);
|
|
415
|
+
punishments.push({
|
|
416
|
+
branches: [xu.branch, wei.branch],
|
|
417
|
+
positions: [xu.position, wei.position],
|
|
418
|
+
type: 'threePunishment',
|
|
419
|
+
subtype: 'uncivilizedPunishment',
|
|
420
|
+
impact: '负面',
|
|
421
|
+
strength: this.applyPositionModifier(7, positionType),
|
|
422
|
+
description: '戌未無禮之刑',
|
|
423
|
+
positionType,
|
|
424
|
+
spacing
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
if (wei && chou) {
|
|
428
|
+
const { positionType, spacing } = this.getRelationByPosition([wei.position], [chou.position]);
|
|
429
|
+
punishments.push({
|
|
430
|
+
branches: [wei.branch, chou.branch],
|
|
431
|
+
positions: [wei.position, chou.position],
|
|
432
|
+
type: 'threePunishment',
|
|
433
|
+
subtype: 'uncivilizedPunishment',
|
|
434
|
+
impact: '负面',
|
|
435
|
+
strength: this.applyPositionModifier(7, positionType),
|
|
436
|
+
description: '未丑無禮之刑',
|
|
437
|
+
positionType,
|
|
438
|
+
spacing
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
return punishments;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Three Harmonies (三合) - Elemental triangle harmonies
|
|
445
|
+
*/
|
|
446
|
+
static findThreeHarmonies(branches) {
|
|
447
|
+
const harmonies = [];
|
|
448
|
+
const threeHarmonyGroups = [
|
|
449
|
+
{ branches: ['申', '子', '辰'], element: '水', strength: 10, description: '申子辰三合水局' },
|
|
450
|
+
{ branches: ['亥', '卯', '未'], element: '木', strength: 10, description: '亥卯未三合木局' },
|
|
451
|
+
{ branches: ['寅', '午', '戌'], element: '火', strength: 10, description: '寅午戌三合火局' },
|
|
452
|
+
{ branches: ['巳', '酉', '丑'], element: '金', strength: 10, description: '巳酉丑三合金局' }
|
|
453
|
+
];
|
|
454
|
+
for (const group of threeHarmonyGroups) {
|
|
455
|
+
const foundBranches = branches.filter(b => group.branches.includes(b.branch));
|
|
456
|
+
if (foundBranches.length >= 2) {
|
|
457
|
+
// Even partial three harmonies are significant
|
|
458
|
+
const baseStrength = foundBranches.length === 3 ? group.strength : group.strength - 2;
|
|
459
|
+
// Calculate position analysis for multi-branch relations
|
|
460
|
+
const positions = foundBranches.map(f => f.position);
|
|
461
|
+
let positionType = '遥';
|
|
462
|
+
let minSpacing = 3;
|
|
463
|
+
// Check spacing between all pairs
|
|
464
|
+
for (let i = 0; i < positions.length - 1; i++) {
|
|
465
|
+
for (let j = i + 1; j < positions.length; j++) {
|
|
466
|
+
// 转换中文位置名称为内部键
|
|
467
|
+
const key_i = (0, positions_1.getPositionKeyByName)(positions[i]) || positions[i];
|
|
468
|
+
const key_j = (0, positions_1.getPositionKeyByName)(positions[j]) || positions[j];
|
|
469
|
+
const spacing = Math.abs(this.POSITION_INDEX[key_i] - this.POSITION_INDEX[key_j]);
|
|
470
|
+
if (spacing < minSpacing) {
|
|
471
|
+
minSpacing = spacing;
|
|
472
|
+
if (spacing === 1)
|
|
473
|
+
positionType = '相';
|
|
474
|
+
else if (spacing === 2)
|
|
475
|
+
positionType = '隔';
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// Special case for three-way harmonies
|
|
480
|
+
if (foundBranches.length === 3) {
|
|
481
|
+
const indices = positions.map(p => {
|
|
482
|
+
const key = (0, positions_1.getPositionKeyByName)(p) || p;
|
|
483
|
+
return this.POSITION_INDEX[key];
|
|
484
|
+
}).sort((a, b) => a - b);
|
|
485
|
+
if (indices[2] - indices[0] === 2) {
|
|
486
|
+
positionType = '争'; // Concentrated three-way harmony
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
harmonies.push({
|
|
490
|
+
branches: foundBranches.map(f => f.branch),
|
|
491
|
+
positions: foundBranches.map(f => f.position),
|
|
492
|
+
type: 'threeHarmony',
|
|
493
|
+
impact: '正面',
|
|
494
|
+
strength: this.applyPositionModifier(baseStrength, positionType),
|
|
495
|
+
element: group.element,
|
|
496
|
+
description: group.description,
|
|
497
|
+
positionType,
|
|
498
|
+
spacing: minSpacing
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
return harmonies;
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Six Destructions (六破) - Destructive relationships
|
|
506
|
+
*/
|
|
507
|
+
static findSixDestructions(branches) {
|
|
508
|
+
const destructions = [];
|
|
509
|
+
// Correct six destruction pairs based on traditional BaZi
|
|
510
|
+
const sixDestructionPairs = [
|
|
511
|
+
{ branches: ['子', '酉'], strength: 6, description: '子酉相破' },
|
|
512
|
+
{ branches: ['卯', '午'], strength: 6, description: '卯午相破' },
|
|
513
|
+
{ branches: ['辰', '丑'], strength: 5, description: '辰丑相破' },
|
|
514
|
+
{ branches: ['戌', '未'], strength: 5, description: '戌未相破' },
|
|
515
|
+
{ branches: ['巳', '寅'], strength: 7, description: '巳寅相破' },
|
|
516
|
+
{ branches: ['申', '亥'], strength: 7, description: '申亥相破' }
|
|
517
|
+
];
|
|
518
|
+
for (const destruction of sixDestructionPairs) {
|
|
519
|
+
const found1 = branches.find(b => b.branch === destruction.branches[0]);
|
|
520
|
+
const found2 = branches.find(b => b.branch === destruction.branches[1]);
|
|
521
|
+
if (found1 && found2) {
|
|
522
|
+
const { positionType, spacing } = this.getRelationByPosition([found1.position], [found2.position]);
|
|
523
|
+
destructions.push({
|
|
524
|
+
branches: [found1.branch, found2.branch],
|
|
525
|
+
positions: [found1.position, found2.position],
|
|
526
|
+
type: 'sixDestruction',
|
|
527
|
+
impact: '负面',
|
|
528
|
+
strength: this.applyPositionModifier(destruction.strength, positionType),
|
|
529
|
+
description: destruction.description,
|
|
530
|
+
positionType,
|
|
531
|
+
spacing
|
|
532
|
+
});
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
return destructions;
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Three Meetings (三會) - Directional season gatherings
|
|
539
|
+
*/
|
|
540
|
+
static findThreeMeetings(branches) {
|
|
541
|
+
const meetings = [];
|
|
542
|
+
const threeMeetingGroups = [
|
|
543
|
+
{ branches: ['亥', '子', '丑'], element: '水', season: 'winter', strength: 8, description: '亥子丑三會水局' },
|
|
544
|
+
{ branches: ['寅', '卯', '辰'], element: '木', season: 'spring', strength: 8, description: '寅卯辰三會木局' },
|
|
545
|
+
{ branches: ['巳', '午', '未'], element: '火', season: 'summer', strength: 8, description: '巳午未三會火局' },
|
|
546
|
+
{ branches: ['申', '酉', '戌'], element: '金', season: 'autumn', strength: 8, description: '申酉戌三會金局' }
|
|
547
|
+
];
|
|
548
|
+
for (const group of threeMeetingGroups) {
|
|
549
|
+
const foundBranches = branches.filter(b => group.branches.includes(b.branch));
|
|
550
|
+
if (foundBranches.length >= 2) {
|
|
551
|
+
const baseStrength = foundBranches.length === 3 ? group.strength : group.strength - 2;
|
|
552
|
+
// Calculate position analysis for multi-branch relations
|
|
553
|
+
const positions = foundBranches.map(f => f.position);
|
|
554
|
+
let positionType = '遥';
|
|
555
|
+
let minSpacing = 3;
|
|
556
|
+
// Check spacing between all pairs
|
|
557
|
+
for (let i = 0; i < positions.length - 1; i++) {
|
|
558
|
+
for (let j = i + 1; j < positions.length; j++) {
|
|
559
|
+
// 转换中文位置名称为内部键
|
|
560
|
+
const key_i = (0, positions_1.getPositionKeyByName)(positions[i]) || positions[i];
|
|
561
|
+
const key_j = (0, positions_1.getPositionKeyByName)(positions[j]) || positions[j];
|
|
562
|
+
const spacing = Math.abs(this.POSITION_INDEX[key_i] - this.POSITION_INDEX[key_j]);
|
|
563
|
+
if (spacing < minSpacing) {
|
|
564
|
+
minSpacing = spacing;
|
|
565
|
+
if (spacing === 1)
|
|
566
|
+
positionType = '相';
|
|
567
|
+
else if (spacing === 2)
|
|
568
|
+
positionType = '隔';
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
// Special case for three meetings - consecutive positions are especially powerful
|
|
573
|
+
if (foundBranches.length === 3) {
|
|
574
|
+
const indices = positions.map(p => {
|
|
575
|
+
const key = (0, positions_1.getPositionKeyByName)(p) || p;
|
|
576
|
+
return this.POSITION_INDEX[key];
|
|
577
|
+
}).sort((a, b) => a - b);
|
|
578
|
+
if (indices[2] - indices[0] === 2 && indices[1] - indices[0] === 1) {
|
|
579
|
+
positionType = '争'; // Perfect seasonal meeting
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
meetings.push({
|
|
583
|
+
branches: foundBranches.map(f => f.branch),
|
|
584
|
+
positions: foundBranches.map(f => f.position),
|
|
585
|
+
type: 'threeMeeting',
|
|
586
|
+
impact: '正面',
|
|
587
|
+
strength: this.applyPositionModifier(baseStrength, positionType),
|
|
588
|
+
element: group.element,
|
|
589
|
+
description: group.description,
|
|
590
|
+
positionType,
|
|
591
|
+
spacing: minSpacing
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return meetings;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Calculate comprehensive overview statistics
|
|
599
|
+
*/
|
|
600
|
+
static calculateOverview(result) {
|
|
601
|
+
const allBranchRelations = [
|
|
602
|
+
...result.sixHarmonies,
|
|
603
|
+
...result.sixConflicts,
|
|
604
|
+
...result.sixHarms,
|
|
605
|
+
...result.threePunishments,
|
|
606
|
+
...result.threeHarmonies,
|
|
607
|
+
...result.sixDestructions,
|
|
608
|
+
...result.threeMeetings
|
|
609
|
+
];
|
|
610
|
+
const totalRelations = allBranchRelations.length + result.stemCombinations.length;
|
|
611
|
+
const positiveCount = allBranchRelations.filter(r => r.impact === '正面').length + result.stemCombinations.length;
|
|
612
|
+
const negativeCount = allBranchRelations.filter(r => r.impact === '负面').length;
|
|
613
|
+
// Calculate harmony score (0-100)
|
|
614
|
+
let harmonyScore = 50; // Base score
|
|
615
|
+
// Add points for positive branch relations
|
|
616
|
+
allBranchRelations.forEach(relation => {
|
|
617
|
+
if (relation.impact === '正面') {
|
|
618
|
+
harmonyScore += relation.strength;
|
|
619
|
+
}
|
|
620
|
+
else if (relation.impact === '负面') {
|
|
621
|
+
harmonyScore -= relation.strength;
|
|
622
|
+
}
|
|
623
|
+
});
|
|
624
|
+
// Add points for stem combinations (always positive)
|
|
625
|
+
result.stemCombinations.forEach(combination => {
|
|
626
|
+
harmonyScore += combination.strength;
|
|
627
|
+
});
|
|
628
|
+
// Normalize to 0-100 range
|
|
629
|
+
harmonyScore = Math.max(0, Math.min(100, harmonyScore));
|
|
630
|
+
// Determine dominant pattern
|
|
631
|
+
let dominantPattern = '平衡';
|
|
632
|
+
if (result.stemCombinations.length >= 2) {
|
|
633
|
+
dominantPattern = '天干五合';
|
|
634
|
+
}
|
|
635
|
+
else if (result.threeHarmonies.length > 0) {
|
|
636
|
+
dominantPattern = '三合局';
|
|
637
|
+
}
|
|
638
|
+
else if (result.sixHarmonies.length >= 2) {
|
|
639
|
+
dominantPattern = '六合';
|
|
640
|
+
}
|
|
641
|
+
else if (result.sixConflicts.length >= 2) {
|
|
642
|
+
dominantPattern = '六沖';
|
|
643
|
+
}
|
|
644
|
+
else if (result.threePunishments.length > 0) {
|
|
645
|
+
dominantPattern = '三刑';
|
|
646
|
+
}
|
|
647
|
+
else if (positiveCount > negativeCount) {
|
|
648
|
+
dominantPattern = '和諧';
|
|
649
|
+
}
|
|
650
|
+
else if (negativeCount > positiveCount) {
|
|
651
|
+
dominantPattern = '衝突';
|
|
652
|
+
}
|
|
653
|
+
return {
|
|
654
|
+
totalRelations,
|
|
655
|
+
positiveCount,
|
|
656
|
+
negativeCount,
|
|
657
|
+
dominantPattern,
|
|
658
|
+
harmonyScore,
|
|
659
|
+
hasStemCombinations: result.stemCombinations.length > 0
|
|
660
|
+
};
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Get relationship strength modifier for fortune calculations
|
|
664
|
+
* Used by other analyzers to factor in branch relationships
|
|
665
|
+
*/
|
|
666
|
+
static getRelationshipModifier(result) {
|
|
667
|
+
const { harmonyScore, dominantPattern } = result.overview;
|
|
668
|
+
// Base modifier from harmony score
|
|
669
|
+
let modifier = (harmonyScore - 50) / 50; // Range: -1 to +1
|
|
670
|
+
// Additional modifiers for special patterns
|
|
671
|
+
if (dominantPattern === 'threeHarmony')
|
|
672
|
+
modifier += 0.3;
|
|
673
|
+
if (dominantPattern === 'sixHarmony')
|
|
674
|
+
modifier += 0.2;
|
|
675
|
+
if (dominantPattern === 'sixConflict')
|
|
676
|
+
modifier -= 0.3;
|
|
677
|
+
if (dominantPattern === 'threePunishment')
|
|
678
|
+
modifier -= 0.4;
|
|
679
|
+
return Math.max(-1, Math.min(1, modifier));
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Check if specific relationship type exists
|
|
683
|
+
* Utility method for other analyzers
|
|
684
|
+
*/
|
|
685
|
+
static hasRelationType(result, type) {
|
|
686
|
+
// Check stem combinations
|
|
687
|
+
if (type === 'fiveCombination' || type === 'stemCombination') {
|
|
688
|
+
return result.stemCombinations.length > 0;
|
|
689
|
+
}
|
|
690
|
+
// Check branch relations
|
|
691
|
+
const allBranchRelations = [
|
|
692
|
+
...result.sixHarmonies,
|
|
693
|
+
...result.sixConflicts,
|
|
694
|
+
...result.sixHarms,
|
|
695
|
+
...result.threePunishments,
|
|
696
|
+
...result.threeHarmonies,
|
|
697
|
+
...result.sixDestructions,
|
|
698
|
+
...result.threeMeetings
|
|
699
|
+
];
|
|
700
|
+
return allBranchRelations.some(relation => relation.type === type);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
exports.RelationsAnalyzer = RelationsAnalyzer;
|
|
704
|
+
//# sourceMappingURL=RelationsAnalyzer.js.map
|