dsh-metaphysics 0.21.0 → 0.34.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 +534 -385
- package/README.md +309 -279
- package/client.js +2190 -69
- package/engine/bazi.js +33 -2
- package/engine/classics.js +264 -0
- package/engine/geo.js +1 -1
- package/engine/index.js +146 -7
- package/engine/interpret-knowledge.js +402 -277
- package/engine/interpret-plain.js +87 -5
- package/engine/interpret.js +131 -7
- package/engine/liuyao.js +702 -237
- package/engine/mbti.js +417 -0
- package/engine/name.js +189 -19
- package/engine/qimen-interpret.js +37 -2
- package/engine/qimen.js +128 -1
- package/engine/ziwei.js +79 -0
- package/index.js +21 -16
- package/locale/en.json +1 -1
- package/locale/zh.json +1 -1
- package/package.json +5 -3
- package//345/221/275/347/220/206/346/216/222/347/233/230.html +17691 -0
package/engine/bazi.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from './calendar.js';
|
|
7
7
|
import { resolveAddress } from './geo.js';
|
|
8
8
|
import { computeBaziShensha } from './shensha.js';
|
|
9
|
-
import { assertCivil } from './validate.js';
|
|
9
|
+
import { assertCivil, daysInMonth } from './validate.js';
|
|
10
10
|
import { applyDst } from './dst.js';
|
|
11
11
|
import { nayinOf } from './nayin.js';
|
|
12
12
|
import { SANHE } from './sanhe.js';
|
|
@@ -277,6 +277,22 @@ export function buildBazi(input) {
|
|
|
277
277
|
// 四舍五入到 12 个月时必须进位,否则显示「X 岁 12 个月起运」
|
|
278
278
|
if (startAgeMonths >= 12) { startAgeMonths -= 12; startAgeYears += 1; }
|
|
279
279
|
|
|
280
|
+
// 交运:三日折一年。
|
|
281
|
+
// 古法三条换算是同一比例的三种说法——3 日折 1 年、1 日折 4 个月、1 时辰折 10 日:
|
|
282
|
+
// 把「出生 → 起运那一侧的节令」的真实间隔按 365.2422/3(≈121.7474)倍放大,
|
|
283
|
+
// 就是起运那一刻;放大后的 1/12 恰好 121.7474/12 ≈ 10.15 天,即「一时辰十日」。
|
|
284
|
+
// 一年取回归年 365.2422 日(交运日细算各家不一,这里固定这一个口径并写明)。
|
|
285
|
+
const JIAO_YEAR_DAYS = 365.2422;
|
|
286
|
+
const JIAO_SCALE = JIAO_YEAR_DAYS / 3;
|
|
287
|
+
const jiaoFromTerm = forward ? nextJieTerm : prevJieTerm;
|
|
288
|
+
const jiaoJd = jd + spanDays * JIAO_SCALE;
|
|
289
|
+
const jiaoParts = jdToParts(jiaoJd);
|
|
290
|
+
// 每步大运在「同月同日同时刻」换;公历闰日(2 月 29 日生)退到 2 月 28 日
|
|
291
|
+
const addYearsClamped = (p, n) => {
|
|
292
|
+
const y = p.year + n;
|
|
293
|
+
return { year: y, month: p.month, day: Math.min(p.day, daysInMonth(y, p.month)), hour: p.hour, minute: p.minute };
|
|
294
|
+
};
|
|
295
|
+
|
|
280
296
|
const dayun = [];
|
|
281
297
|
for (let i = 1; i <= 8; i++) {
|
|
282
298
|
const idx = (((monthIdx + (forward ? i : -i)) % 60) + 60) % 60;
|
|
@@ -289,6 +305,9 @@ export function buildBazi(input) {
|
|
|
289
305
|
branch: g.branch,
|
|
290
306
|
stemTenGod: tenGod(dayStem, g.stem),
|
|
291
307
|
nayin: nayin(idx),
|
|
308
|
+
// 这一步大运的起止交运时刻(与摘要/面板同源,可直接拿来对年表)
|
|
309
|
+
fromDate: formatJd(partsToJd(addYearsClamped(jiaoParts, (i - 1) * 10))),
|
|
310
|
+
toDate: formatJd(partsToJd(addYearsClamped(jiaoParts, i * 10))),
|
|
292
311
|
});
|
|
293
312
|
}
|
|
294
313
|
|
|
@@ -503,10 +522,22 @@ export function buildBazi(input) {
|
|
|
503
522
|
rule: `${isYangYear ? '阳' : '阴'}年${gender === 'male' ? '男' : '女'}${forward ? '顺排' : '逆排'}`,
|
|
504
523
|
startAge: { years: startAgeYears, months: startAgeMonths },
|
|
505
524
|
toNextJieDays: Math.round(spanDays * 100) / 100,
|
|
525
|
+
// 交运时刻(日/时辰级):上方 startAge 是四舍五入到月的旧字段,两者同源、不互相覆盖
|
|
526
|
+
jiao: {
|
|
527
|
+
at: formatJd(jiaoJd),
|
|
528
|
+
jd: Math.round(jiaoJd * 1e6) / 1e6,
|
|
529
|
+
scaleDaysPerDay: JIAO_SCALE,
|
|
530
|
+
yearDays: JIAO_YEAR_DAYS,
|
|
531
|
+
spanDays: Math.round(spanDays * 1e4) / 1e4,
|
|
532
|
+
from: { name: jiaoFromTerm.name, time: formatJd(jiaoFromTerm.jd) },
|
|
533
|
+
frame: solar.offsetMinutes ? '真太阳时' : '平太阳时',
|
|
534
|
+
offsetMinutes: solar.offsetMinutes,
|
|
535
|
+
note: '三日折一年:出生到节令的真实间隔按 365.2422/3 放大后加到出生时刻;同一比例即「一日折四月、一时辰折十日」,每步大运在同月同日同时刻换',
|
|
536
|
+
},
|
|
506
537
|
list: dayun,
|
|
507
538
|
},
|
|
508
539
|
strength,
|
|
509
|
-
frame,
|
|
540
|
+
frame,
|
|
510
541
|
climate: frame.yongshen.climate || frame.yongshen.tiaohou || null,
|
|
511
542
|
liunian,
|
|
512
543
|
liunianFrom: thisYear,
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// 古籍原文库:《子平真诠》《滴天髓》里与「格局取用」「十神喜忌」「寒暖燥湿」直接相关的条目。
|
|
2
|
+
// 原文照录(公共版权:清·沈孝瞻《子平真诠》、明·京图《滴天髓》通行本),仅供文化研究与参考。
|
|
3
|
+
// 出处以中华典藏网在线本为准(逐条给 url),异文处不合并、不改写;plain 是本站自撰白话,不是原文。
|
|
4
|
+
|
|
5
|
+
export const CLASSIC_BOOKS = {
|
|
6
|
+
ziping: { name: '子平真诠', author: '清·沈孝瞻', base: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/' },
|
|
7
|
+
ditian: { name: '滴天髓', author: '明·京图(通行本)', base: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/' },
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export const CLASSICS = [
|
|
11
|
+
{
|
|
12
|
+
id: 'zp-yongshen',
|
|
13
|
+
book: 'ziping',
|
|
14
|
+
chapter: '八、论用神',
|
|
15
|
+
scene: '用神',
|
|
16
|
+
tags: [],
|
|
17
|
+
quote: '八字用神,专求月令,以日干配月令地支,而生克不同,格局分焉。财官印食,此用神之善而顺用之者也;煞伤劫刃,用神之不善而逆用之者也。',
|
|
18
|
+
plain: '用神从月令里找:财、官、印、食四吉神顺用(生之护之),煞、伤、劫、刃四凶神逆用(制之化之)。',
|
|
19
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53628.html',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 'zp-zhenguan',
|
|
23
|
+
book: 'ziping',
|
|
24
|
+
chapter: '三十一、论正官',
|
|
25
|
+
scene: '格局',
|
|
26
|
+
tags: ['正官'],
|
|
27
|
+
quote: '以刑冲破害为忌,则以生之护之为喜矣。存其喜而去其忌则贵,而贵之中又有高低者,何也?',
|
|
28
|
+
plain: '正官格最忌刑冲破害,喜财生官、印护官;去忌存喜才谈得上贵,贵的层次还要看财印是否并透、有无伤官七煞混杂。',
|
|
29
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53651.html',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'zp-cai',
|
|
33
|
+
book: 'ziping',
|
|
34
|
+
chapter: '三十三、论财',
|
|
35
|
+
scene: '格局',
|
|
36
|
+
tags: ['财'],
|
|
37
|
+
quote: '财为我克,使用之物也,以能生官,所以为美。为财帛,为妻妾,为才能,为驿马,皆财类也。',
|
|
38
|
+
plain: '财是我所克、能为我用之物,因能生官而美;它同时代表钱财、配偶、才能、走动,不只「钱」一项。',
|
|
39
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53653.html',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: 'zp-yin',
|
|
43
|
+
book: 'ziping',
|
|
44
|
+
chapter: '三十五、论印绶',
|
|
45
|
+
scene: '格局',
|
|
46
|
+
tags: ['印'],
|
|
47
|
+
quote: '印绶喜其生身,正偏同为美格,故财与印不分偏正,同为一格而论之。',
|
|
48
|
+
plain: '印能生身,正印偏印都算美格,不分偏正而论;印格的关键在身印强弱与官杀、食伤、财的配合。',
|
|
49
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53655.html',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
id: 'zp-shishen',
|
|
53
|
+
book: 'ziping',
|
|
54
|
+
chapter: '三十七、论食神',
|
|
55
|
+
scene: '格局',
|
|
56
|
+
tags: ['食神'],
|
|
57
|
+
quote: '食神本属泄气,以其能生正财,所以喜之。故食神生财,美格也。财要有根,不必偏正叠出,如身强食旺而财透,大贵之格。',
|
|
58
|
+
plain: '食神本是泄气,可贵在能生财;食神生财要财有根,身强、食旺、财透三者齐,格局才大。',
|
|
59
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53657.html',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'zp-pianguan',
|
|
63
|
+
book: 'ziping',
|
|
64
|
+
chapter: '三十九、论偏官',
|
|
65
|
+
scene: '格局',
|
|
66
|
+
tags: ['七杀', '偏官'],
|
|
67
|
+
quote: '煞以攻身,似非美物,百大贵之格,多存七煞。盖控制得宜,煞为我用,如大英雄大豪杰,似难驾驭,而处之有方,则惊天动地之功,忽焉而就。',
|
|
68
|
+
plain: '七煞攻身,看着不美,但大贵之格多有七煞——能控制住就为我所用,像驾驭豪杰,处之有方就能成大事。',
|
|
69
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53659.html',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'zp-shangguan',
|
|
73
|
+
book: 'ziping',
|
|
74
|
+
chapter: '四十一、论伤官',
|
|
75
|
+
scene: '格局',
|
|
76
|
+
tags: ['伤官'],
|
|
77
|
+
quote: '伤官虽非吉神,实为秀气,故文人学士,多于伤官格内得之。而夏木见水,冬金见火,则又为秀之尤秀者也。',
|
|
78
|
+
plain: '伤官不是吉神,却是秀气所在,文人多出伤官格;夏木得水、冬金得火,是秀气里更秀的两种。',
|
|
79
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53661.html',
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: 'zp-yangren',
|
|
83
|
+
book: 'ziping',
|
|
84
|
+
chapter: '四十三、论阳刃',
|
|
85
|
+
scene: '格局',
|
|
86
|
+
tags: ['劫财', '阳刃'],
|
|
87
|
+
quote: '阳刃者,劫我正财之神,乃正财之七煞也。禄前一位,惟五阳有之,故为阳刃。不曰劫而曰刃,劫之甚也。刃宜伏制,官煞皆宜,财印相随,尤为贵显。',
|
|
88
|
+
plain: '阳刃是劫财之极(只有五阳干有),宜用官煞制伏;财印相随而不相碍,格局更显。',
|
|
89
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53663.html',
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
id: 'zp-lujie',
|
|
93
|
+
book: 'ziping',
|
|
94
|
+
chapter: '四十五、论建禄月劫',
|
|
95
|
+
scene: '格局',
|
|
96
|
+
tags: ['比肩', '建禄', '月劫'],
|
|
97
|
+
quote: '故建禄与月劫,可同一格,不必加分,皆以透干支,别取财官煞食为用。',
|
|
98
|
+
plain: '建禄、月劫同看一格,月令本身不算用神,要另看透出的财官煞食取用。',
|
|
99
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53665.html',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
id: 'zp-qihou',
|
|
103
|
+
book: 'ziping',
|
|
104
|
+
chapter: '十四、论用神配气候得失',
|
|
105
|
+
scene: '调候',
|
|
106
|
+
tags: [],
|
|
107
|
+
quote: '论命惟以月令用神为主,然亦须配气候而互参之。譬如英雄豪杰,生得其时,自然事半功倍;遭时不顺,虽有奇才,成功不易。',
|
|
108
|
+
plain: '月令用神为主,但必须配气候参看;同样的格局,生在得时的气候里事半功倍,逆着气候就费劲。',
|
|
109
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/zipingzhenquan/53634.html',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'dt-hannuan',
|
|
113
|
+
book: 'ditian',
|
|
114
|
+
chapter: '通神论·寒暖',
|
|
115
|
+
scene: '调候',
|
|
116
|
+
tags: [],
|
|
117
|
+
quote: '天道有寒暖,生育万物,人道行之,不可过也。',
|
|
118
|
+
plain: '天有寒暖才能生养万物,人命里寒暖也不能过——过寒过热都要调。',
|
|
119
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
id: 'dt-zaoshi',
|
|
123
|
+
book: 'ditian',
|
|
124
|
+
chapter: '通神论·燥湿',
|
|
125
|
+
scene: '调候',
|
|
126
|
+
tags: [],
|
|
127
|
+
quote: '地道有燥湿,生成品汇,人道得之,不可偏也。',
|
|
128
|
+
plain: '地有燥湿才有品类生成,人命得燥湿之气也不能偏。',
|
|
129
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
id: 'dt-shuaiwang',
|
|
133
|
+
book: 'ditian',
|
|
134
|
+
chapter: '通神论·衰旺',
|
|
135
|
+
scene: '调候',
|
|
136
|
+
tags: [],
|
|
137
|
+
quote: '能知旺衰之真机,其于三命之奥,思过半矣。',
|
|
138
|
+
plain: '真正看懂旺衰的机关,命理之奥就过了一半——旺衰不是数个数,要看真机。',
|
|
139
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
id: 'dt-zhonghe',
|
|
143
|
+
book: 'ditian',
|
|
144
|
+
chapter: '通神论·中和',
|
|
145
|
+
scene: '调候',
|
|
146
|
+
tags: [],
|
|
147
|
+
quote: '既识中和之正理,而于五行之妙,有全能焉。',
|
|
148
|
+
plain: '懂得中和的道理,五行的妙处就都在其中了。',
|
|
149
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
id: 'dt-guansha',
|
|
153
|
+
book: 'ditian',
|
|
154
|
+
chapter: '通神论·官杀',
|
|
155
|
+
scene: '十神',
|
|
156
|
+
tags: ['正官', '七杀'],
|
|
157
|
+
quote: '官杀混杂来问我,有可有不可。',
|
|
158
|
+
plain: '官杀混杂不是一律不好,要看能不能去留取清。',
|
|
159
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: 'dt-shangguan',
|
|
163
|
+
book: 'ditian',
|
|
164
|
+
chapter: '通神论·伤官',
|
|
165
|
+
scene: '十神',
|
|
166
|
+
tags: ['伤官'],
|
|
167
|
+
quote: '伤官见官最难辨,可见不可见。',
|
|
168
|
+
plain: '伤官见官是最难分辨的一条:有的能见,有的不能见,不能一句「伤官见官为祸百端」了事。',
|
|
169
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'dt-yueling',
|
|
173
|
+
book: 'ditian',
|
|
174
|
+
chapter: '通神论·月令',
|
|
175
|
+
scene: '用神',
|
|
176
|
+
tags: [],
|
|
177
|
+
quote: '月令乃提纲之府,譬之宅也,人元为用事之神,宅之定向也,不可以不卜。',
|
|
178
|
+
plain: '月令像宅子,藏干是用事之神,像宅子的朝向,必须细看。',
|
|
179
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
id: 'dt-tiyong',
|
|
183
|
+
book: 'ditian',
|
|
184
|
+
chapter: '通神论·体用',
|
|
185
|
+
scene: '用神',
|
|
186
|
+
tags: [],
|
|
187
|
+
quote: '道有体用,不可以一端论也,要在扶之抑之得其宜。',
|
|
188
|
+
plain: '体用不能只看一头,关键是扶抑得宜。',
|
|
189
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
id: 'dt-jingshen',
|
|
193
|
+
book: 'ditian',
|
|
194
|
+
chapter: '通神论·精神',
|
|
195
|
+
scene: '用神',
|
|
196
|
+
tags: [],
|
|
197
|
+
quote: '人有精神,不可以一偏求也,要在损之益之得其中。',
|
|
198
|
+
plain: '看精神不能偏执一端,要在损益之间求其中。',
|
|
199
|
+
url: 'https://www.diancang.xyz/xuanxuewushu/ditiansui/153091.html',
|
|
200
|
+
},
|
|
201
|
+
];
|
|
202
|
+
|
|
203
|
+
const BY_ID = CLASSICS.reduce((m, e) => { m[e.id] = e; return m; }, {});
|
|
204
|
+
|
|
205
|
+
// 格局名 → tags 键(本引擎的格局名都带「格」)
|
|
206
|
+
const GEJU_KEY = {
|
|
207
|
+
正官格: '正官',
|
|
208
|
+
七杀格: '七杀',
|
|
209
|
+
偏官格: '偏官',
|
|
210
|
+
正财格: '财',
|
|
211
|
+
偏财格: '财',
|
|
212
|
+
正印格: '印',
|
|
213
|
+
偏印格: '印',
|
|
214
|
+
食神格: '食神',
|
|
215
|
+
伤官格: '伤官',
|
|
216
|
+
阳刃格: '阳刃',
|
|
217
|
+
月劫格: '月劫',
|
|
218
|
+
建禄格: '建禄',
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
export function classicOf(id) {
|
|
222
|
+
return BY_ID[id] || null;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function tagOf(gejuName) {
|
|
226
|
+
const name = String(gejuName || '');
|
|
227
|
+
if (GEJU_KEY[name]) return GEJU_KEY[name];
|
|
228
|
+
const bare = name.replace(/格$/, '');
|
|
229
|
+
return GEJU_KEY[bare + '格'] || bare;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 根据一张八字结果挑原文:先格局(格局条),再调候(寒暖/燥湿),最后用神通则;去重、限量。
|
|
233
|
+
export function classicsFor(r, limit = 4) {
|
|
234
|
+
if (!r) return [];
|
|
235
|
+
const out = [];
|
|
236
|
+
const seen = new Set();
|
|
237
|
+
const push = (entry, why) => {
|
|
238
|
+
if (!entry || seen.has(entry.id) || out.length >= limit) return;
|
|
239
|
+
seen.add(entry.id);
|
|
240
|
+
out.push({ ...entry, why });
|
|
241
|
+
};
|
|
242
|
+
const gejuList = Array.isArray(r.geju) ? r.geju : (r.frame && Array.isArray(r.frame.geju) ? r.frame.geju : []);
|
|
243
|
+
for (const g of gejuList) {
|
|
244
|
+
if (!g || (g.kind && g.kind !== '月令格')) continue;
|
|
245
|
+
const tag = tagOf(g.name);
|
|
246
|
+
const hit = CLASSICS.find((e) => e.scene === '格局' && e.tags.includes(tag));
|
|
247
|
+
if (hit) push(hit, `你的月令格局是「${g.name}」,故取${CLASSIC_BOOKS[hit.book].name}论${hit.chapter.replace(/^.*、/, '')}`);
|
|
248
|
+
}
|
|
249
|
+
const cli = r.climate || (r.frame && r.frame.yongshen && (r.frame.yongshen.climate || r.frame.yongshen.tiaohou));
|
|
250
|
+
if (cli && cli.kind && cli.kind !== '平和') {
|
|
251
|
+
const cold = !!(cli.cold || cli.kind.indexOf('寒') >= 0);
|
|
252
|
+
const hot = !!(cli.hot || cli.kind.indexOf('热') >= 0);
|
|
253
|
+
push(classicOf(cold ? 'dt-hannuan' : 'dt-zaoshi'), `本盘气候判为「${cli.kind}」,故取${CLASSIC_BOOKS.ditian.name}寒暖燥湿一条`);
|
|
254
|
+
push(classicOf('zp-qihou'), '气候与月令用神要互参,故取子平真诠「用神配气候」一条');
|
|
255
|
+
if (hot) push(classicOf('dt-hannuan'), '本盘偏热,寒暖一条正对');
|
|
256
|
+
}
|
|
257
|
+
push(classicOf('zp-yongshen'), '用神从月令取、四吉顺用四凶逆用,是通用总纲');
|
|
258
|
+
return out;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export function classicsText(rows) {
|
|
262
|
+
if (!rows || !rows.length) return '';
|
|
263
|
+
return rows.map((e) => `《${CLASSIC_BOOKS[e.book].name}·${e.chapter}》「${e.quote}」`).join('\n');
|
|
264
|
+
}
|
package/engine/geo.js
CHANGED
|
@@ -143,7 +143,7 @@ const DETAIL = /(区|县|镇|乡|村|小区|街道|路|号|巷|弄|组|队)/;
|
|
|
143
143
|
|
|
144
144
|
/** OpenStreetMap Nominatim:免密钥、支持中文。失败返回 null。
|
|
145
145
|
* UA 按 OSM 使用政策要求写明应用与联系方式(改版本时同步这里)。 */
|
|
146
|
-
const USER_AGENT = 'dsh-metaphysics/0.
|
|
146
|
+
const USER_AGENT = 'dsh-metaphysics/0.23.0 (+https://github.com/xuanfu-web/dsh-metaphysics)';
|
|
147
147
|
|
|
148
148
|
async function onlineLookup(text, { timeoutMs = 2500 } = {}) {
|
|
149
149
|
if (typeof fetch !== 'function') return null;
|
package/engine/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// 统一入口:解析参数、分派到各体系、生成可读摘要
|
|
2
2
|
import { buildBazi } from './bazi.js';
|
|
3
|
-
import { buildLiuyao, tossLines } from './liuyao.js';
|
|
3
|
+
import { buildLiuyao, tossLines, bodyLabels, yongshenOf, yongshenStrength } from './liuyao.js';
|
|
4
4
|
import { buildZiwei, BRIGHTNESS, flowOf, asOfParts } from './ziwei.js';
|
|
5
5
|
import { drawTarot } from './tarot.js';
|
|
6
6
|
import { buildMeihua } from './meihua.js';
|
|
7
7
|
import { buildDaliuren } from './daliuren.js';
|
|
8
8
|
import { buildHepan } from './hepan.js';
|
|
9
9
|
import { buildZiweiHepan } from './ziwei-hepan.js';
|
|
10
|
-
import { buildQimen } from './qimen.js';
|
|
10
|
+
import { buildQimen, buildSnapshot } from './qimen.js';
|
|
11
11
|
import { geocodeAddress, resolveAddress } from './geo.js';
|
|
12
12
|
import { toJDN, ganzhiName, dayGanzhiIndex } from './calendar.js';
|
|
13
13
|
import { randomOf, isSeed } from './random.js';
|
|
@@ -22,7 +22,9 @@ import { buildChenggu } from './chenggu.js';
|
|
|
22
22
|
import { buildXiaoliuren } from './xiaoliuren.js';
|
|
23
23
|
import { buildStar } from './star.js';
|
|
24
24
|
import { buildNumerology } from './numerology.js';
|
|
25
|
+
import { buildMbti, mbtiPaper } from './mbti.js';
|
|
25
26
|
import { buildConvert } from './convert.js';
|
|
27
|
+
import { classicsFor, classicsText } from './classics.js';
|
|
26
28
|
import { buildTrend } from './trend.js';
|
|
27
29
|
import { buildFengshui } from './fengshui.js';
|
|
28
30
|
import { buildName } from './name.js';
|
|
@@ -96,6 +98,10 @@ function baziText(r) {
|
|
|
96
98
|
: '';
|
|
97
99
|
const dayun = r.dayun.list.slice(0, 8)
|
|
98
100
|
.map((d) => `${d.startAge}岁 ${d.ganzhi}(${d.stemTenGod})${d.luck ? `·${d.luck.tier}` : ''}${d.relations && d.relations.length ? `[${d.relations.join('')}]` : ''}`).join(' ');
|
|
101
|
+
// 交运时刻(日/时辰级):旧结果没有 dayun.jiao,缺省就只说「起运」,不硬凑
|
|
102
|
+
const jiao = r.dayun.jiao && r.dayun.jiao.at
|
|
103
|
+
? `;交运 ${r.dayun.jiao.at}(${r.dayun.jiao.frame},距${r.dayun.jiao.from.name} ${r.dayun.jiao.spanDays} 天,三日折一年)`
|
|
104
|
+
: '';
|
|
99
105
|
// 阈值 20 分钟:与 NAOJ 历要项对拍实测,本引擎节气最多偏早 13.5 分钟(Meeus 低精度上限约 14 分钟)
|
|
100
106
|
const near = r.jieqi.nearBoundaryMinutes < 20
|
|
101
107
|
? `\n⚠ 出生时刻距「节」仅 ${r.jieqi.nearBoundaryMinutes} 分钟,而节气时刻本身有最多约 14 分钟的偏差,月柱与年柱建议人工复核。`
|
|
@@ -127,7 +133,7 @@ function baziText(r) {
|
|
|
127
133
|
shenshaLine,
|
|
128
134
|
`真太阳时:${r.solarTime.trueSolarText}(${r.input.geo ? r.input.geo.note + ';' : ''}${r.solarTime.note}) 晚子时:${r.input.lateZi ? '23:00 后算次日' : '23:00 后仍算当日'}`,
|
|
129
135
|
`节气:上一节 ${r.jieqi.previous.name} ${r.jieqi.previous.time} 下一节 ${r.jieqi.next.name} ${r.jieqi.next.time}`,
|
|
130
|
-
`大运:${r.dayun.rule}(${r.dayun.direction}),${r.dayun.startAge.years}岁${r.dayun.startAge.months}
|
|
136
|
+
`大运:${r.dayun.rule}(${r.dayun.direction}),${r.dayun.startAge.years}岁${r.dayun.startAge.months}个月起运${jiao}`,
|
|
131
137
|
` ${dayun}`,
|
|
132
138
|
`流年:${r.liunian.slice(0, 10).map((l) => `${l.year}${l.ganzhi}(${l.stemTenGod})${l.luck ? `·${l.luck.tier}` : ''}`).join(' ')}`,
|
|
133
139
|
'(格局、用神、行运吉凶为扶抑+简化调候的量化提示,非断语。)',
|
|
@@ -156,6 +162,18 @@ function ziweiText(r) {
|
|
|
156
162
|
: '无明显格局(按内置规则)';
|
|
157
163
|
const daxian = (r.daxianList ?? []).slice(0, 8).map((d) =>
|
|
158
164
|
` ${d.branch}宫(${d.palace})${d.ages[0]}-${d.ages[1]}岁 ${d.ganzhi} 会${d.mainStars.join('') || '—'} 化 ${d.mutagenHits.map((m) => `${m.star}${m.type}→${m.palace || '未上盘'}`).join('、')}`);
|
|
165
|
+
// 命宫四化飞星:宫干化出的星落在哪一宫,一路串下去成环为止
|
|
166
|
+
const flyLine = (() => {
|
|
167
|
+
const fc = r.flyChains;
|
|
168
|
+
if (!fc) return '';
|
|
169
|
+
const one = (t) => {
|
|
170
|
+
const ch = fc[t];
|
|
171
|
+
if (!ch || !ch.steps.length) return '';
|
|
172
|
+
return `${t}:${ch.path.join('→')}${ch.closed ? '(成环)' : ''}`;
|
|
173
|
+
};
|
|
174
|
+
const text = ['禄', '权', '科', '忌'].map(one).filter(Boolean).join(' ');
|
|
175
|
+
return text ? `【命宫飞星】${text}` : '';
|
|
176
|
+
})();
|
|
159
177
|
return [
|
|
160
178
|
`【农历】${lunarText}(月首 ${r.lunar.monthStart}) 时支:${r.hourBranch} 年干支:${r.yearGanzhi}`,
|
|
161
179
|
`【时刻】${r.solarTime ? `${r.solarTime.civilText} → 真太阳时 ${r.solarTime.trueSolarText}${r.input.geo ? '(' + r.input.geo.note + ')' : ''}` : ''}`,
|
|
@@ -164,6 +182,7 @@ function ziweiText(r) {
|
|
|
164
182
|
`【大限】${r.daxian.rule},${r.daxian.startAge}岁起 【小限】${r.xiaoxianRule.direction}`,
|
|
165
183
|
`【昌曲】文昌${r.changqu.wenchang.branch}(${r.changqu.wenchang.palace}${r.changqu.wenchang.mutagen ? '·化' + r.changqu.wenchang.mutagen : ''}) 文曲${r.changqu.wenqu.branch}(${r.changqu.wenqu.palace}${r.changqu.wenqu.mutagen ? '·化' + r.changqu.wenqu.mutagen : ''})`,
|
|
166
184
|
` ${r.changqu.relation} 入命三方:${r.changqu.inSoulSanfang ? '是' : '否'} 吸收面:${r.changqu.absorb.label}(${r.changqu.absorb.reason})`,
|
|
185
|
+
flyLine,
|
|
167
186
|
'十二宫:',
|
|
168
187
|
...rows,
|
|
169
188
|
'大限(按起运年龄排序,前 8 限,宫干四化落宫):',
|
|
@@ -176,6 +195,17 @@ function ziweiText(r) {
|
|
|
176
195
|
].filter(Boolean).join('\n');
|
|
177
196
|
}
|
|
178
197
|
|
|
198
|
+
const STATE_ORDER = ['旺', '相', '休', '囚', '死'];
|
|
199
|
+
/** 门/星的月令五态,按 旺相休囚死 顺序拼成一行 */
|
|
200
|
+
function stateLine(r) {
|
|
201
|
+
const st = r.states;
|
|
202
|
+
const mo = r.month;
|
|
203
|
+
if (!st || !mo) return '无月令数据';
|
|
204
|
+
const fmt = (g) => STATE_ORDER.filter((k) => g && Array.isArray(g[k]) && g[k].length)
|
|
205
|
+
.map((k) => `${k} ${g[k].join('/')}`).join(' ');
|
|
206
|
+
return `月令 ${mo.branch}(${mo.element}) 门 ${fmt(st.gate) || '—'} 星 ${fmt(st.star) || '—'} 干 ${fmt(st.stem) || '—'}`;
|
|
207
|
+
}
|
|
208
|
+
|
|
179
209
|
function qimenText(r) {
|
|
180
210
|
const P = r.palaces;
|
|
181
211
|
const cell = (x) => `${x.palace}宫 ${x.star || '—'}/${x.gate || '—'}/${x.god || '—'}${x.kong ? ' 空' : ''}${x.ma ? ' 马' : ''}`;
|
|
@@ -184,6 +214,8 @@ function qimenText(r) {
|
|
|
184
214
|
`【局数】${r.ju} 节气 ${r.jieqi}(${r.jieqiTime})`,
|
|
185
215
|
`【值符】${r.zhiFu.star}(${r.zhiFu.gong}宫) 【值使】${r.zhiShi.gate}(${r.zhiShi.gong}宫) 旬首 ${r.xunshou}`,
|
|
186
216
|
`【空亡】${r.kongWang.join('') || '—'} 驿马 ${r.ma.zhi || '—'}(${r.ma.gong || '—'}宫)`,
|
|
217
|
+
`【宫位条件】击刑 ${(r.conditions && r.conditions.jiXing || []).map((x) => `${x.palace}宫${x.stem}`).join('、') || '无'} 入墓 ${(r.conditions && r.conditions.ruMu || []).map((x) => `${x.palace}宫${x.stem}`).join('、') || '无'}`,
|
|
218
|
+
`【旺衰】${stateLine(r)}`,
|
|
187
219
|
`【九宫】${P.map(cell).join(' ')}`,
|
|
188
220
|
`※ 晚子时:${r.lateZiHourMode === 'next-day' ? '23:00 后归次日' : '23:00 后仍归当日'}(可用 lateZiHourMode / lateZi 指定)`,
|
|
189
221
|
`※ ${r.rules[r.rules.length - 1]}`,
|
|
@@ -285,6 +317,27 @@ function liuyaoText(r) {
|
|
|
285
317
|
];
|
|
286
318
|
if (r.bian) out.push(`动爻:第 ${r.cast.movingPositions.join('、')} 爻`, '变卦(六亲以变卦自身宫论):', fmt(r.bian));
|
|
287
319
|
else out.push('六爻安静,无变卦。');
|
|
320
|
+
// 结果里已带 labels;只有旧数据或裸对象调用时才现算一份
|
|
321
|
+
const body = (r.body && Array.isArray(r.body.labels)) ? r.body.labels : bodyLabels(r.body);
|
|
322
|
+
out.push(`卦体:${body.length ? body.join(' · ') : '无六冲、六合、伏吟、反吟'}`);
|
|
323
|
+
// 用神:按询问方向取六亲(感情分男女、出行以世为用),不上卦时给伏神
|
|
324
|
+
const ug = r.useGod || yongshenOf(r, {});
|
|
325
|
+
if (ug && ug.liuqin) {
|
|
326
|
+
const where = ug.found.length
|
|
327
|
+
? ug.found.map((f) => `${f.position}爻${f.ganzhi}${f.element}${f.kong ? '(空)' : ''}`).join('、')
|
|
328
|
+
: (ug.fushen.length ? ug.fushen.map((f) => `伏 ${f.position}爻${f.ganzhi}${f.element}(${f.relation || '飞伏关系未知'})`).join('、') : '不上卦');
|
|
329
|
+
out.push(`用神:${ug.byShi ? '世爻' : ug.liuqin}(${ug.ask})→ ${where}${ug.side ? `(${ug.side})` : ''}`);
|
|
330
|
+
const head = ug.byShi ? '用神 世爻' : `用神 ${ug.liuqin}`;
|
|
331
|
+
const extra = ug.labels.filter((x) => x !== head && !x.startsWith(head));
|
|
332
|
+
if (extra.length) out.push(`用神联动:${extra.join(' · ')}`);
|
|
333
|
+
const strength = r.useGodStrength;
|
|
334
|
+
if (strength && strength.labels.length) {
|
|
335
|
+
const m = strength.month && strength.month.branch ? `月建 ${strength.month.branch}(${strength.month.element}) ` : '';
|
|
336
|
+
out.push(`用神旺衰:${m}${strength.labels.join(' · ')}`);
|
|
337
|
+
}
|
|
338
|
+
} else {
|
|
339
|
+
out.push('用神:未取(未指明所问之事;用「询问方向」指定后即按六亲取用)');
|
|
340
|
+
}
|
|
288
341
|
return out.filter(Boolean).join('\n');
|
|
289
342
|
}
|
|
290
343
|
|
|
@@ -301,6 +354,11 @@ function jsonSafe(value) {
|
|
|
301
354
|
*/
|
|
302
355
|
export function compute(args = {}) {
|
|
303
356
|
const r = jsonSafe(computeRaw(args));
|
|
357
|
+
if (r && r.system === 'bazi') {
|
|
358
|
+
r.classics = classicsFor(r);
|
|
359
|
+
const ct = classicsText(r.classics);
|
|
360
|
+
if (ct) r.summary = `${r.summary}\n【古籍】\n${ct}`;
|
|
361
|
+
}
|
|
304
362
|
// 超出 ΔT 覆盖范围时把精度提示顶到摘要最前,别让远期盘悄悄出错
|
|
305
363
|
if (r && r.precision && r.precision.level === 'approx' && r.summary) {
|
|
306
364
|
r.summary = `⚠ ${r.precision.note}\n${r.summary}`;
|
|
@@ -589,6 +647,23 @@ function computeRaw(args = {}) {
|
|
|
589
647
|
} catch (e) {
|
|
590
648
|
throw fail('E_LINES', e && e.message ? e.message : e);
|
|
591
649
|
}
|
|
650
|
+
// 用神挂在结果上:摘要、面板、解析三层读同一份,避免各自取一次走散
|
|
651
|
+
const ug = yongshenOf(result, { direction: args.direction, gender: args.gender });
|
|
652
|
+
if (ug.liuqin) {
|
|
653
|
+
result.useGod = ug;
|
|
654
|
+
// 月建按节气换月、与八字同源:从同一个 snapshot 取月支,取不到就只按日辰算
|
|
655
|
+
let monthBranch = null;
|
|
656
|
+
if (stamp) {
|
|
657
|
+
try {
|
|
658
|
+
const snap = buildSnapshot({ year: stamp.year, month: stamp.month, day: stamp.day, hour: stamp.hour, minute: stamp.minute });
|
|
659
|
+
monthBranch = (snap.monthGanZhi || '')[1] || null;
|
|
660
|
+
} catch {
|
|
661
|
+
monthBranch = null;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
const strength = yongshenStrength(result, ug, { monthBranch, dayBranch: result.dayGanZhi.branch });
|
|
665
|
+
if (strength) result.useGodStrength = strength;
|
|
666
|
+
}
|
|
592
667
|
if (args.seed !== undefined && args.seed !== null && args.seed !== '') result.seed = Number(args.seed);
|
|
593
668
|
return { ...result, ...(asOf ? { asOf } : {}), summary: liuyaoText(result) };
|
|
594
669
|
}
|
|
@@ -663,6 +738,15 @@ function computeRaw(args = {}) {
|
|
|
663
738
|
const result = buildNumerology({ year: dt.year, month: dt.month, day: dt.day });
|
|
664
739
|
return { ...result, summary: numerologyText(result) };
|
|
665
740
|
}
|
|
741
|
+
if (system === 'mbti') {
|
|
742
|
+
// 没给答案就先发问卷:让模型把 24 题交给用户逐题打分,而不是自己编一个类型
|
|
743
|
+
if (args.answers === undefined || args.answers === null) {
|
|
744
|
+
const paper = mbtiPaper();
|
|
745
|
+
return { ...paper, summary: mbtiPaperText(paper) };
|
|
746
|
+
}
|
|
747
|
+
const result = buildMbti({ answers: args.answers });
|
|
748
|
+
return { ...result, summary: mbtiText(result) };
|
|
749
|
+
}
|
|
666
750
|
if (system === 'trend') {
|
|
667
751
|
const dt = parseDateTime(args.datetime);
|
|
668
752
|
const result = buildTrend({
|
|
@@ -703,12 +787,21 @@ function computeRaw(args = {}) {
|
|
|
703
787
|
}
|
|
704
788
|
if (system === 'name') {
|
|
705
789
|
const action = args.action === 'generate' ? 'generate' : 'assess';
|
|
706
|
-
const birth = args.datetime
|
|
790
|
+
const birth = args.datetime
|
|
791
|
+
? parseDateTime(args.datetime)
|
|
792
|
+
: (Number.isInteger(args.year) && Number.isInteger(args.month) && Number.isInteger(args.day)
|
|
793
|
+
? {
|
|
794
|
+
year: args.year, month: args.month, day: args.day,
|
|
795
|
+
...(Number.isInteger(args.hour) ? { hour: args.hour } : {}),
|
|
796
|
+
...(Number.isInteger(args.minute) ? { minute: args.minute } : {}),
|
|
797
|
+
}
|
|
798
|
+
: {});
|
|
707
799
|
const result = buildName({
|
|
708
800
|
action,
|
|
709
801
|
surname: args.surname,
|
|
710
802
|
givenName: args.givenName,
|
|
711
803
|
limit: args.limit,
|
|
804
|
+
charElements: args.charElements && typeof args.charElements === 'object' ? args.charElements : undefined,
|
|
712
805
|
...birth,
|
|
713
806
|
...(args.gender === 'male' || args.gender === 'female' ? { gender: args.gender } : {}),
|
|
714
807
|
...(args.datetime ? {
|
|
@@ -723,9 +816,9 @@ function computeRaw(args = {}) {
|
|
|
723
816
|
return { ...result, summary: nameText(result) };
|
|
724
817
|
}
|
|
725
818
|
if (!system) {
|
|
726
|
-
throw fail('E_INPUT', '缺少 system,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。');
|
|
819
|
+
throw fail('E_INPUT', '缺少 system,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、mbti(十六型人格问卷)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。');
|
|
727
820
|
}
|
|
728
|
-
throw fail('E_SYSTEM', `未知体系「${system}」,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。`);
|
|
821
|
+
throw fail('E_SYSTEM', `未知体系「${system}」,可选:bazi(四柱八字)、ziwei(紫微斗数)、liuyao(六爻)、meihua(梅花易数)、daliuren(大六壬)、qimen(奇门遁甲)、hepan(合盘)、tarot(塔罗)、almanac(黄历)、zeri(择日)、chenggu(称骨)、xiaoliuren(小六壬)、star(星座)、numerology(生命数字)、mbti(十六型人格问卷)、trend(人生 K 线)、fengshui(风水)、name(起名)、convert(公农历互转)。`);
|
|
729
822
|
}
|
|
730
823
|
|
|
731
824
|
/** 黄历文本 */
|
|
@@ -831,6 +924,43 @@ function numerologyText(r) {
|
|
|
831
924
|
].join('\n');
|
|
832
925
|
}
|
|
833
926
|
|
|
927
|
+
/** 十六型人格文本 */
|
|
928
|
+
function mbtiText(r) {
|
|
929
|
+
const dims = r.dims.map((d) => {
|
|
930
|
+
const side = d.picked === d.left ? d.leftSay : d.rightSay;
|
|
931
|
+
const pct = Math.round(d.pct * 100);
|
|
932
|
+
return `${d.left}/${d.right} 取 ${d.picked}(${d.strength} ${pct}%,净分 ${d.sum}) ${side}`;
|
|
933
|
+
});
|
|
934
|
+
const p = r.profile;
|
|
935
|
+
const stack = Array.isArray(p.stack) && p.stack.length
|
|
936
|
+
? p.stack.map((f, i) => `${i === 0 ? '主导 ' : ''}${f.code}`).join(' → ') + `\n ${p.stack.map((f) => `${f.code}:${f.say}`).join('\n ')}`
|
|
937
|
+
: '';
|
|
938
|
+
return [
|
|
939
|
+
`【十六型人格】${r.type}(${p.title})· ${p.keywords} 已答 ${r.answered}/${r.total} 题`,
|
|
940
|
+
`一句:${p.oneLine}`,
|
|
941
|
+
'【四维】',
|
|
942
|
+
...dims,
|
|
943
|
+
`【优势】${p.strengths.join(';')}`,
|
|
944
|
+
`【留意】${p.blindspots.join(';')}`,
|
|
945
|
+
`【课题】${p.growth}`,
|
|
946
|
+
`【认知功能】${stack}`,
|
|
947
|
+
`【工作】${p.work}`,
|
|
948
|
+
`【关系】${p.love}`,
|
|
949
|
+
`【学习】${p.study}`,
|
|
950
|
+
`注:${r.note}`,
|
|
951
|
+
].join('\n');
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
/** 问卷文本(还没答题时) */
|
|
955
|
+
function mbtiPaperText(paper) {
|
|
956
|
+
return [
|
|
957
|
+
`【十六型人格问卷】${paper.total} 题,每题按 1(完全不像我)到 5(很像我)打分`,
|
|
958
|
+
...paper.questions.map((q) => `${q.no}. ${q.text}`),
|
|
959
|
+
`请把 ${paper.total} 个分数按顺序交给 answers(如 [4,2,5,3,…]);可以跳过某些题(填 null),至少答 12 题。`,
|
|
960
|
+
`注:${paper.note}`,
|
|
961
|
+
].join('\n');
|
|
962
|
+
}
|
|
963
|
+
|
|
834
964
|
/** 人生 K 线文本 */
|
|
835
965
|
function trendText(r) {
|
|
836
966
|
const s = r.meta.strength;
|
|
@@ -886,9 +1016,18 @@ function nameText(r) {
|
|
|
886
1016
|
...r.notes.map((n) => `※ ${n}`),
|
|
887
1017
|
].join('\n');
|
|
888
1018
|
}
|
|
1019
|
+
const srcLabel = (c) => (c.source === 'lib' ? '字库' : c.source === 'user' ? '用户指定' : '未收录');
|
|
1020
|
+
const charLine = (c) => {
|
|
1021
|
+
const el = c.element === '未收录' ? '未收录(不猜五行)' : `${c.element}(${srcLabel(c)})`;
|
|
1022
|
+
const fit = c.favorable === true ? '合喜用' : c.favorable === false ? '不合喜用' : '不判';
|
|
1023
|
+
const sug = c.suggest && c.suggest.length
|
|
1024
|
+
? ` 可换:${c.suggest.map((x) => `${x.char}(${x.element})`).join('、')}`
|
|
1025
|
+
: '';
|
|
1026
|
+
return `· ${c.char}:${el}|${fit}|${c.meaning}${sug}`;
|
|
1027
|
+
};
|
|
889
1028
|
return [
|
|
890
1029
|
`【名字评估】${r.fullName}`,
|
|
891
|
-
...r.chars.map(
|
|
1030
|
+
...r.chars.map(charLine),
|
|
892
1031
|
r.bazi ? `【八字】日主 ${r.bazi.dayMaster && r.bazi.dayMaster.stem ? `${r.bazi.dayMaster.stem}(${r.bazi.dayMaster.element})` : r.bazi.dayMaster},旺衰 ${r.bazi.strength.level}(${r.bazi.strength.score}),${r.bazi.basis}` : '',
|
|
893
1032
|
`【结论】${r.verdict}`,
|
|
894
1033
|
...r.notes.map((n) => `※ ${n}`),
|