dsh-metaphysics 0.14.3 → 0.16.0
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/CHANGELOG.md +213 -166
- package/README.md +229 -221
- package/client.js +1551 -111
- package/engine/bazi.js +505 -515
- package/engine/calendar.js +325 -256
- package/engine/crosscheck.js +133 -0
- package/engine/daliuren.js +339 -342
- package/engine/diff.js +197 -0
- package/engine/fail.js +13 -0
- package/engine/followup.js +173 -0
- package/engine/geo.js +1 -1
- package/engine/hepan.js +147 -144
- package/engine/index.js +566 -513
- package/engine/interpret-knowledge.js +277 -0
- package/engine/interpret-plain.js +197 -0
- package/engine/interpret.js +1356 -1176
- package/engine/liuyao.js +237 -238
- package/engine/lru.js +69 -0
- package/engine/meihua.js +137 -136
- package/engine/nayin.js +24 -0
- package/engine/qimen.js +442 -438
- package/engine/sanhe.js +26 -0
- package/engine/validate.js +56 -0
- package/engine/ziwei-hepan.js +123 -120
- package/engine/ziwei.js +821 -828
- package/index.js +229 -212
- package/package.json +1 -1
package/engine/hepan.js
CHANGED
|
@@ -1,144 +1,147 @@
|
|
|
1
|
-
// 合盘(合婚):日主关系 + 夫妻宫关系 + 五行互补。
|
|
2
|
-
// 口径:日主取五行生克(双向平均),夫妻宫取日支的六合/三合/冲/害/刑/破,
|
|
3
|
-
// 五行互补看「一方喜用是否正是另一方所旺」。各派取法不同,这里只给通用版结论。
|
|
4
|
-
import { buildBazi } from './bazi.js';
|
|
5
|
-
import { STEMS, BRANCHES } from './calendar.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
if (pairIn(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (pairIn(
|
|
36
|
-
return { name: '
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
if (SHENG[
|
|
44
|
-
if (
|
|
45
|
-
return { name: '
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
//
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
'
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
1
|
+
// 合盘(合婚):日主关系 + 夫妻宫关系 + 五行互补。
|
|
2
|
+
// 口径:日主取五行生克(双向平均),夫妻宫取日支的六合/三合/冲/害/刑/破,
|
|
3
|
+
// 五行互补看「一方喜用是否正是另一方所旺」。各派取法不同,这里只给通用版结论。
|
|
4
|
+
import { buildBazi } from './bazi.js';
|
|
5
|
+
import { STEMS, BRANCHES } from './calendar.js';
|
|
6
|
+
import { assertCivil } from './validate.js';
|
|
7
|
+
import { SANHE_GROUPS } from './sanhe.js';
|
|
8
|
+
|
|
9
|
+
const WX_GAN = { 甲: '木', 乙: '木', 丙: '火', 丁: '火', 戊: '土', 己: '土', 庚: '金', 辛: '金', 壬: '水', 癸: '水' };
|
|
10
|
+
const WX_ZHI = { 子: '水', 丑: '土', 寅: '木', 卯: '木', 辰: '土', 巳: '火', 午: '火', 未: '土', 申: '金', 酉: '金', 戌: '土', 亥: '水' };
|
|
11
|
+
const SHENG = { 木: '火', 火: '土', 土: '金', 金: '水', 水: '木' };
|
|
12
|
+
const KE = { 木: '土', 土: '水', 水: '火', 火: '金', 金: '木' };
|
|
13
|
+
|
|
14
|
+
// 地支两两关系(只取合、冲、害、刑、破;三合按半合算)
|
|
15
|
+
const LIU_HE = [['子', '丑'], ['寅', '亥'], ['卯', '戌'], ['辰', '酉'], ['巳', '申'], ['午', '未']];
|
|
16
|
+
const CHONG = [['子', '午'], ['丑', '未'], ['寅', '申'], ['卯', '酉'], ['辰', '戌'], ['巳', '亥']];
|
|
17
|
+
const HAI = [['子', '未'], ['丑', '午'], ['寅', '巳'], ['卯', '辰'], ['申', '亥'], ['酉', '戌']];
|
|
18
|
+
const PO = [['子', '酉'], ['卯', '午'], ['辰', '丑'], ['未', '戌'], ['寅', '亥'], ['巳', '申']];
|
|
19
|
+
const XING = [['寅', '巳', '申'], ['丑', '戌', '未'], ['子', '卯']];
|
|
20
|
+
|
|
21
|
+
const pairIn = (list, a, b) => list.some((g) => g.includes(a) && g.includes(b) && a !== b);
|
|
22
|
+
|
|
23
|
+
function zhiRelation(a, b) {
|
|
24
|
+
if (a === b) return { name: '同支', score: 0, text: '日支相同,性情相近,容易互相理解,也容易同时卡在同一处' };
|
|
25
|
+
if (pairIn(LIU_HE, a, b)) return { name: '六合', score: 20, text: '日支六合,相处自然、彼此补位' };
|
|
26
|
+
if (SANHE_GROUPS.some((g) => g.branches.includes(a) && g.branches.includes(b))) {
|
|
27
|
+
return { name: '半合', score: 14, text: '日支同属三合局,易有共同语言' };
|
|
28
|
+
}
|
|
29
|
+
if (pairIn(CHONG, a, b)) return { name: '相冲', score: -15, text: '日支相冲,节奏与需求容易错位,需要刻意协调' };
|
|
30
|
+
if (pairIn(XING, a, b)) {
|
|
31
|
+
for (const g of XING) {
|
|
32
|
+
if (g.includes(a) && g.includes(b)) return { name: '相刑', score: -10, text: '日支相刑,摩擦多起于细节,宜少用指责' };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (pairIn(HAI, a, b)) return { name: '相害', score: -9, text: '日支相害,容易因第三方或误解生嫌隙' };
|
|
36
|
+
if (pairIn(PO, a, b)) return { name: '相破', score: -5, text: '日支相破,小事易起波澜' };
|
|
37
|
+
return { name: '无直接关系', score: 4, text: '日支之间没有直接刑冲合害,关系好坏主要看经营' };
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** 两个五行之间:对方对我 */
|
|
41
|
+
function wxToMe(other, me) {
|
|
42
|
+
if (other === me) return { name: '比和', score: 13, text: '两人日主同五行,气味相投,也容易一起犯同样的毛病' };
|
|
43
|
+
if (SHENG[other] === me) return { name: '生我', score: 20, text: '对方五行生我,容易得到照顾与助力' };
|
|
44
|
+
if (SHENG[me] === other) return { name: '我生', score: 10, text: '我生对方,多为付出的一方,久了要留意消耗' };
|
|
45
|
+
if (KE[me] === other) return { name: '我克', score: 5, text: '我克对方,主导感较强,需留意对方的空间' };
|
|
46
|
+
return { name: '克我', score: -12, text: '对方克我,压力感偏重,宜把话说开' };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** 合盘主函数 */
|
|
50
|
+
export function buildHepan(input) {
|
|
51
|
+
assertCivil(input && input.a, 'a');
|
|
52
|
+
assertCivil(input && input.b, 'b');
|
|
53
|
+
const A = buildBazi({ ...input.a, gender: input.a.gender });
|
|
54
|
+
const B = buildBazi({ ...input.b, gender: input.b.gender });
|
|
55
|
+
|
|
56
|
+
const aStem = A.pillars.day.stem;
|
|
57
|
+
const bStem = B.pillars.day.stem;
|
|
58
|
+
const aWx = WX_GAN[aStem];
|
|
59
|
+
const bWx = WX_GAN[bStem];
|
|
60
|
+
const aZhi = A.pillars.day.branch;
|
|
61
|
+
const bZhi = B.pillars.day.branch;
|
|
62
|
+
|
|
63
|
+
// ① 日主
|
|
64
|
+
const aToB = wxToMe(bWx, aWx); // 以 A 为主体看 B
|
|
65
|
+
const bToA = wxToMe(aWx, bWx);
|
|
66
|
+
const stemScore = (aToB.score + bToA.score) / 2;
|
|
67
|
+
|
|
68
|
+
// ② 夫妻宫(日支)
|
|
69
|
+
const gong = zhiRelation(aZhi, bZhi);
|
|
70
|
+
|
|
71
|
+
// ③ 五行互补:一方喜用是否正是另一方所旺
|
|
72
|
+
const favorA = (A.frame && A.frame.yongshen ? A.frame.yongshen.favor : []).slice();
|
|
73
|
+
const favorB = (B.frame && B.frame.yongshen ? B.frame.yongshen.favor : []).slice();
|
|
74
|
+
const wxCount = (r) => {
|
|
75
|
+
const m = {};
|
|
76
|
+
for (const k of ['year', 'month', 'day', 'hour']) {
|
|
77
|
+
m[WX_GAN[r.pillars[k].stem]] = (m[WX_GAN[r.pillars[k].stem]] || 0) + 1;
|
|
78
|
+
m[WX_ZHI[r.pillars[k].branch]] = (m[WX_ZHI[r.pillars[k].branch]] || 0) + 1;
|
|
79
|
+
}
|
|
80
|
+
return m;
|
|
81
|
+
};
|
|
82
|
+
const wxA = wxCount(A);
|
|
83
|
+
const wxB = wxCount(B);
|
|
84
|
+
const strongOf = (m) => Object.entries(m).sort((x, y) => y[1] - x[1])[0] || ['', 0];
|
|
85
|
+
const [strongA] = strongOf(wxA);
|
|
86
|
+
const [strongB] = strongOf(wxB);
|
|
87
|
+
const bFeedsA = favorA.includes(strongB);
|
|
88
|
+
const aFeedsB = favorB.includes(strongA);
|
|
89
|
+
let compScore = 0;
|
|
90
|
+
const compNotes = [];
|
|
91
|
+
if (bFeedsA) { compScore += 12; compNotes.push(`对方的旺行 ${strongB} 正是你的喜用`); }
|
|
92
|
+
if (aFeedsB) { compScore += 12; compNotes.push(`你的旺行 ${strongA} 正是对方的喜用`); }
|
|
93
|
+
if (!bFeedsA && !aFeedsB) { compScore += 3; compNotes.push('双方的旺行都不是对方的喜用,互补性一般,靠沟通补'); }
|
|
94
|
+
// 一方缺的五行正好是对方所旺,也算补
|
|
95
|
+
const missingA = ['木', '火', '土', '金', '水'].filter((w) => !wxA[w]);
|
|
96
|
+
const missingB = ['木', '火', '土', '金', '水'].filter((w) => !wxB[w]);
|
|
97
|
+
if (missingA.includes(strongB)) { compScore += 4; compNotes.push(`你命局缺 ${strongB},对方正好偏旺`); }
|
|
98
|
+
if (missingB.includes(strongA)) { compScore += 4; compNotes.push(`对方命局缺 ${strongA},你正好偏旺`); }
|
|
99
|
+
|
|
100
|
+
// ④ 综合
|
|
101
|
+
const raw = stemScore + gong.score + compScore; // 理论区间约 -27 ~ 56
|
|
102
|
+
const pct = Math.max(0, Math.min(100, Math.round(((raw + 27) / 83) * 100)));
|
|
103
|
+
const level = pct >= 75 ? '契合度较高' : pct >= 55 ? '中等偏顺' : pct >= 40 ? '需要磨合' : '差异较大';
|
|
104
|
+
|
|
105
|
+
const dim = (key, label, score, text, extra) => ({ key, label, score: Math.round(score), text, ...(extra || {}) });
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
system: 'hepan',
|
|
109
|
+
a: {
|
|
110
|
+
gender: A.input.gender,
|
|
111
|
+
pillars: ['year', 'month', 'day', 'hour'].map((k) => A.pillars[k].ganzhi),
|
|
112
|
+
dayMaster: `${aStem}${aWx}`,
|
|
113
|
+
dayBranch: aZhi,
|
|
114
|
+
strength: A.strength ? A.strength.level : null,
|
|
115
|
+
favor: favorA.join(''),
|
|
116
|
+
wuxing: wxA,
|
|
117
|
+
// 真太阳时口径要能被看到:合盘与单盘用同一套修正,否则同一个人会出现两套四柱
|
|
118
|
+
longitude: A.input.longitude ?? null,
|
|
119
|
+
trueSolar: A.input.trueSolar !== false,
|
|
120
|
+
solarNote: A.solarTime ? A.solarTime.note : '',
|
|
121
|
+
summary: A.summary,
|
|
122
|
+
},
|
|
123
|
+
b: {
|
|
124
|
+
gender: B.input.gender,
|
|
125
|
+
pillars: ['year', 'month', 'day', 'hour'].map((k) => B.pillars[k].ganzhi),
|
|
126
|
+
dayMaster: `${bStem}${bWx}`,
|
|
127
|
+
dayBranch: bZhi,
|
|
128
|
+
strength: B.strength ? B.strength.level : null,
|
|
129
|
+
favor: favorB.join(''),
|
|
130
|
+
wuxing: wxB,
|
|
131
|
+
longitude: B.input.longitude ?? null,
|
|
132
|
+
trueSolar: B.input.trueSolar !== false,
|
|
133
|
+
solarNote: B.solarTime ? B.solarTime.note : '',
|
|
134
|
+
summary: B.summary,
|
|
135
|
+
},
|
|
136
|
+
score: { total: pct, level },
|
|
137
|
+
dimensions: [
|
|
138
|
+
dim('stem', '日主关系', stemScore, `你的日主 ${aStem}${aWx},对方 ${bStem}${bWx}。${aToB.text};${bToA.text}。`),
|
|
139
|
+
dim('gong', '夫妻宫(日支)', gong.score, `${gong.name}:${gong.text}。你日支 ${aZhi},对方日支 ${bZhi}。`),
|
|
140
|
+
dim('wuxing', '五行互补', compScore, compNotes.join(';') + '。'),
|
|
141
|
+
],
|
|
142
|
+
notes: [
|
|
143
|
+
'合盘看的是相处方式与互补点,不决定关系成败;现实里的沟通与选择分量更重。',
|
|
144
|
+
`口径:日主取五行生克双向平均,夫妻宫取日支关系,五行互补看「一方喜用是否为另一方所旺」。`,
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
}
|