dsh-metaphysics 0.20.0 → 0.22.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 +28 -0
- package/README.md +10 -6
- package/client.js +1331 -24
- package/engine/geju.js +17 -0
- package/engine/geo.js +1 -1
- package/engine/index.js +23 -4
- package/engine/interpret.js +6 -1
- package/engine/name.js +189 -19
- package/engine/qiongtong.js +1025 -0
- package/engine/tiaohou.js +2 -2
- package/index.js +1 -1
- package/package.json +2 -2
package/engine/geju.js
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
// 调候由 tiaohou.js 独立判定,与扶抑冲突时显式裁决并写明理由,不静默取用。
|
|
9
9
|
|
|
10
10
|
import { judgeClimate, arbitrate } from './tiaohou.js';
|
|
11
|
+
import { qtOf } from './qiongtong.js';
|
|
11
12
|
|
|
12
13
|
const STEMS = ['甲', '乙', '丙', '丁', '戊', '己', '庚', '辛', '壬', '癸'];
|
|
13
14
|
const BRANCHES = ['子', '丑', '寅', '卯', '辰', '巳', '午', '未', '申', '酉', '戌', '亥'];
|
|
@@ -213,6 +214,8 @@ function yongshenOf(dayStem, monthBranch, strength, wuxing, branches = []) {
|
|
|
213
214
|
|
|
214
215
|
// 先判气候,再决定要不要让调候压过扶抑
|
|
215
216
|
const climate = judgeClimate({ monthBranch, dayStem, wuxing, branches });
|
|
217
|
+
// 《穷通宝鉴》120 格:同一「日主 + 月令」的取用顺序。只作展示与加权,不覆盖气候调候
|
|
218
|
+
const qt = qtOf(dayStem, monthBranch);
|
|
216
219
|
const arb = arbitrate(climate, baseFavor, baseAvoid);
|
|
217
220
|
if (climate.need && climate.priority === '调候优先') {
|
|
218
221
|
const needEl = climate.need.element;
|
|
@@ -238,6 +241,7 @@ function yongshenOf(dayStem, monthBranch, strength, wuxing, branches = []) {
|
|
|
238
241
|
? `喜${roles.shi}(食伤)泄秀、${roles.cai}(财)耗、${roles.guan}(官杀)制;忌${me}(比劫)与${roles.inMe}(印)再助。`
|
|
239
242
|
: '身中和,先取调候与通关,喜忌随大运流年动态变化。',
|
|
240
243
|
`调候:${climate.label}(${(climate.evidence || []).join('、')})${climate.need ? `,取${climate.need.stem}${climate.need.element},忌${climate.avoidElement}` : ',气候平和'}。`,
|
|
244
|
+
qt ? `穷通宝鉴:${qt.month}${dayStem}${me},用神${qt.yong.join('、')}(首取${qt.primary})。` : '',
|
|
241
245
|
arb.text,
|
|
242
246
|
arb.clash ? '取舍:本盘按「调候优先、扶抑次之」取用;若你更认同扶抑派,可把调候当环境偏好,强弱判断不受影响。' : '',
|
|
243
247
|
].filter(Boolean).join('');
|
|
@@ -253,6 +257,7 @@ function yongshenOf(dayStem, monthBranch, strength, wuxing, branches = []) {
|
|
|
253
257
|
avoidTenGods,
|
|
254
258
|
tiaohou: { ...climate, ...arb, element: climate.need ? climate.need.element : null },
|
|
255
259
|
climate,
|
|
260
|
+
qt,
|
|
256
261
|
detail,
|
|
257
262
|
};
|
|
258
263
|
}
|
|
@@ -318,6 +323,18 @@ export function scoreLuck(ganzhi, frame) {
|
|
|
318
323
|
|
|
319
324
|
const godStem = tenGod(frame.dayStem, stem);
|
|
320
325
|
const bonus = ys.favorTenGods.includes(godStem) ? 0.3 : 0;
|
|
326
|
+
// 穷通宝鉴:天干正好是这一格的首取/次取时,再给一点「按书取用」的分
|
|
327
|
+
// 只在该干不属于忌神时加分——书里的取用与气候调候不同向时,以调候为先
|
|
328
|
+
const qt = ys.qt || null;
|
|
329
|
+
if (qt && qt.primary && !ys.avoid.includes(STEM_ELEMENT[qt.primary])) {
|
|
330
|
+
if (stem === qt.primary) {
|
|
331
|
+
score += 0.3;
|
|
332
|
+
reasons.push(`天干${stem}正是${qt.branch}月${qt.stem}日的首取(穷通宝鉴)`);
|
|
333
|
+
} else if (qt.yong.includes(stem) && !ys.avoid.includes(STEM_ELEMENT[stem])) {
|
|
334
|
+
score += 0.15;
|
|
335
|
+
reasons.push(`天干${stem}为穷通宝鉴次取`);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
321
338
|
let total = Math.round((score + bonus) * 10) / 10;
|
|
322
339
|
total = Math.max(-4, Math.min(4, total));
|
|
323
340
|
|
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.22.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
|
@@ -21,7 +21,7 @@ import { buildZeri } from './zeri.js';
|
|
|
21
21
|
import { buildChenggu } from './chenggu.js';
|
|
22
22
|
import { buildXiaoliuren } from './xiaoliuren.js';
|
|
23
23
|
import { buildStar } from './star.js';
|
|
24
|
-
import { buildNumerology } from './numerology.js';
|
|
24
|
+
import { buildNumerology } from './numerology.js';
|
|
25
25
|
import { buildConvert } from './convert.js';
|
|
26
26
|
import { buildTrend } from './trend.js';
|
|
27
27
|
import { buildFengshui } from './fengshui.js';
|
|
@@ -110,7 +110,8 @@ function baziText(r) {
|
|
|
110
110
|
` ${r.frame.geju.map((g) => `${g.name}[${g.kind}]`).join(' ')}`,
|
|
111
111
|
`用神:喜${r.frame.yongshen.favor.join('')}(${r.frame.yongshen.favorTenGods.join('、')}) 忌${r.frame.yongshen.avoid.join('')}(${r.frame.yongshen.avoidTenGods.join('、')}) ${r.frame.yongshen.method}`,
|
|
112
112
|
` ${r.frame.yongshen.detail}`,
|
|
113
|
-
`寒暖:${r.climate ? `${r.climate.label}(${(r.climate.evidence || []).join('、')})${r.climate.need ? ` 调候取${r.climate.need.stem}${r.climate.need.element} 忌${r.climate.avoidElement}` : ''}` : '—'}
|
|
113
|
+
`寒暖:${r.climate ? `${r.climate.label}(${(r.climate.evidence || []).join('、')})${r.climate.need ? ` 调候取${r.climate.need.stem}${r.climate.need.element} 忌${r.climate.avoidElement}` : ''}` : '—'}` +
|
|
114
|
+
(r.frame.yongshen.qt ? ` 穷通:${r.frame.yongshen.qt.month}${r.frame.yongshen.qt.stem}取${r.frame.yongshen.qt.yong.join('、')}(首取${r.frame.yongshen.qt.primary})` : ''),
|
|
114
115
|
`十神权重:${Object.entries(r.frame.godStats.groups).map(([k, v]) => `${k}${v}`).join(' ')}`,
|
|
115
116
|
] : [];
|
|
116
117
|
return [
|
|
@@ -702,12 +703,21 @@ function computeRaw(args = {}) {
|
|
|
702
703
|
}
|
|
703
704
|
if (system === 'name') {
|
|
704
705
|
const action = args.action === 'generate' ? 'generate' : 'assess';
|
|
705
|
-
const birth = args.datetime
|
|
706
|
+
const birth = args.datetime
|
|
707
|
+
? parseDateTime(args.datetime)
|
|
708
|
+
: (Number.isInteger(args.year) && Number.isInteger(args.month) && Number.isInteger(args.day)
|
|
709
|
+
? {
|
|
710
|
+
year: args.year, month: args.month, day: args.day,
|
|
711
|
+
...(Number.isInteger(args.hour) ? { hour: args.hour } : {}),
|
|
712
|
+
...(Number.isInteger(args.minute) ? { minute: args.minute } : {}),
|
|
713
|
+
}
|
|
714
|
+
: {});
|
|
706
715
|
const result = buildName({
|
|
707
716
|
action,
|
|
708
717
|
surname: args.surname,
|
|
709
718
|
givenName: args.givenName,
|
|
710
719
|
limit: args.limit,
|
|
720
|
+
charElements: args.charElements && typeof args.charElements === 'object' ? args.charElements : undefined,
|
|
711
721
|
...birth,
|
|
712
722
|
...(args.gender === 'male' || args.gender === 'female' ? { gender: args.gender } : {}),
|
|
713
723
|
...(args.datetime ? {
|
|
@@ -885,9 +895,18 @@ function nameText(r) {
|
|
|
885
895
|
...r.notes.map((n) => `※ ${n}`),
|
|
886
896
|
].join('\n');
|
|
887
897
|
}
|
|
898
|
+
const srcLabel = (c) => (c.source === 'lib' ? '字库' : c.source === 'user' ? '用户指定' : '未收录');
|
|
899
|
+
const charLine = (c) => {
|
|
900
|
+
const el = c.element === '未收录' ? '未收录(不猜五行)' : `${c.element}(${srcLabel(c)})`;
|
|
901
|
+
const fit = c.favorable === true ? '合喜用' : c.favorable === false ? '不合喜用' : '不判';
|
|
902
|
+
const sug = c.suggest && c.suggest.length
|
|
903
|
+
? ` 可换:${c.suggest.map((x) => `${x.char}(${x.element})`).join('、')}`
|
|
904
|
+
: '';
|
|
905
|
+
return `· ${c.char}:${el}|${fit}|${c.meaning}${sug}`;
|
|
906
|
+
};
|
|
888
907
|
return [
|
|
889
908
|
`【名字评估】${r.fullName}`,
|
|
890
|
-
...r.chars.map(
|
|
909
|
+
...r.chars.map(charLine),
|
|
891
910
|
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}` : '',
|
|
892
911
|
`【结论】${r.verdict}`,
|
|
893
912
|
...r.notes.map((n) => `※ ${n}`),
|
package/engine/interpret.js
CHANGED
|
@@ -374,6 +374,11 @@ function baziInterpret(r) {
|
|
|
374
374
|
? `调候取${cli.need.stem}${cli.need.element},忌${cli.avoidElement};${cli.clash ? '与扶抑冲突,本盘以调候为先' : '与扶抑同向'}`
|
|
375
375
|
: '气候平和,调候不作主取'}。`,
|
|
376
376
|
}] : []),
|
|
377
|
+
...(ys.qt ? [{
|
|
378
|
+
key: 'qiongtong', label: '穷通宝鉴',
|
|
379
|
+
text: `${ys.qt.label}:用神 ${ys.qt.yong.join('、')}(首取 ${ys.qt.primary})。原文:「${ys.qt.quote}」` +
|
|
380
|
+
`(《穷通宝鉴》第 ${ys.qt.chapter} 章${ys.qt.note ? ';' + ys.qt.note : ''})`,
|
|
381
|
+
}] : []),
|
|
377
382
|
{
|
|
378
383
|
key: 'geju', label: '格局依据',
|
|
379
384
|
text: (Array.isArray(frame.geju) ? frame.geju : []).map((g) => `${g.name}(${g.kind}):${g.evidence}`).join(';') || '未取到格局',
|
|
@@ -384,7 +389,7 @@ function baziInterpret(r) {
|
|
|
384
389
|
},
|
|
385
390
|
{
|
|
386
391
|
key: 'limits', label: '未纳入',
|
|
387
|
-
text: '
|
|
392
|
+
text: '本盘没有计算:流月与流日、神煞的加权轻重、地支藏干的动态引化(合冲后再论)。取用按「调候优先、扶抑校验」;调候由月令与全局寒暖燥湿判定,并按《穷通宝鉴》120 格给出用神顺序(整理表口径,原文摘句照录,异文处已标 note);各派取法仍有分歧;真太阳时未含历史时区与夏令时。把这些补上会改变"强弱"的边际判断,所以这里只给方向,不下断语。',
|
|
388
393
|
},
|
|
389
394
|
];
|
|
390
395
|
|
package/engine/name.js
CHANGED
|
@@ -116,6 +116,115 @@ export const CHAR_LIB = [
|
|
|
116
116
|
['月', '木', '明月', 'f'], ['言', '木', '言语,信', 'n'],
|
|
117
117
|
['和', '水', '和顺', 'n'], ['安', '土', '安宁', 'n'],
|
|
118
118
|
['宁', '火', '安宁', 'f'],
|
|
119
|
+
// ── 扩充:木 ──
|
|
120
|
+
['林', '木', '林木成片,茂盛有荫', 'n'], ['森', '木', '众木成林,森然', 'n'],
|
|
121
|
+
['枝', '木', '枝条,生发', 'n'], ['果', '木', '果实,有成', 'n'],
|
|
122
|
+
['禾', '木', '禾苗,五谷初生', 'n'], ['秀', '木', '禾吐穗,秀美出众', 'n'],
|
|
123
|
+
['穗', '木', '谷穗,丰实', 'n'], ['稼', '木', '庄稼,耕作有成', 'm'],
|
|
124
|
+
['颖', '木', '禾颖,聪颖', 'n'], ['苗', '木', '苗裔,初生有生机', 'n'],
|
|
125
|
+
['菁', '木', '菁华,草木茂盛', 'f'], ['菡', '木', '荷花含苞', 'f'],
|
|
126
|
+
['蕴', '木', '蕴积,含而不露', 'f'], ['蕾', '木', '花蕾,待放', 'f'],
|
|
127
|
+
['薇', '木', '蔷薇,细而韧', 'f'], ['薏', '木', '薏苡,清润', 'f'],
|
|
128
|
+
['菀', '木', '草木茂盛', 'f'], ['荷', '木', '荷花,出淤泥', 'f'],
|
|
129
|
+
['莲', '木', '莲花,清直', 'f'], ['菱', '木', '菱角,水生', 'f'],
|
|
130
|
+
['苇', '木', '芦苇,柔韧', 'n'], ['荻', '木', '荻草,秋声', 'n'],
|
|
131
|
+
['筠', '木', '竹皮,竹之青', 'n'], ['笛', '木', '竹笛,清音', 'n'],
|
|
132
|
+
['杉', '木', '杉木,挺拔', 'n'], ['柠', '木', '柠檬,清新', 'f'],
|
|
133
|
+
['桢', '木', '桢干,栋梁材', 'm'], ['樾', '木', '树荫,庇下', 'm'],
|
|
134
|
+
['柘', '木', '柘木,坚韧', 'n'], ['权', '木', '权衡,执中', 'm'],
|
|
135
|
+
['材', '木', '木材,成材', 'm'], ['杭', '木', '苏杭,舟行', 'n'],
|
|
136
|
+
['枚', '木', '衔枚,静而进', 'n'], ['梧', '木', '梧桐,栖凤', 'n'],
|
|
137
|
+
['竹', '木', '竹,有节而虚心', 'n'], ['简', '木', '简朴,简静', 'n'],
|
|
138
|
+
['策', '木', '策谋,鞭策', 'm'], ['筹', '木', '筹算,谋划', 'm'],
|
|
139
|
+
['芬', '木', '芬芳', 'f'], ['芳', '木', '芳华', 'f'],
|
|
140
|
+
['花', '木', '花,明媚', 'f'], ['菊', '木', '菊花,晚节', 'f'],
|
|
141
|
+
['兰', '木', '兰花,幽香', 'f'], ['芝', '木', '芝兰,瑞草', 'f'],
|
|
142
|
+
['芹', '木', '芹献,谦诚', 'f'], ['荃', '木', '荃草,香草', 'f'],
|
|
143
|
+
['萃', '木', '荟萃,聚合', 'n'], ['蓁', '木', '蓁蓁,草木盛', 'n'],
|
|
144
|
+
['荞', '木', '荞麦,实而不华', 'f'], ['莞', '木', '莞尔,浅笑', 'f'],
|
|
145
|
+
['萦', '木', '萦绕,绵长', 'f'], ['蔚', '木', '蔚然,文采盛', 'n'],
|
|
146
|
+
['芃', '木', '芃芃,草木茂', 'n'], ['芩', '木', '黄芩,草本', 'f'],
|
|
147
|
+
['苡', '木', '薏苡,清润', 'f'], ['莱', '木', '莱草,野而秀', 'n'],
|
|
148
|
+
['萌', '木', '萌芽,生机', 'n'], ['葆', '木', '永葆,守而不失', 'n'],
|
|
149
|
+
['萧', '木', '萧然,清疏', 'n'], ['樟', '木', '樟木,香而久', 'n'],
|
|
150
|
+
['樱', '木', '樱花,明丽', 'f'], ['栎', '木', '栎树,坚实', 'n'],
|
|
151
|
+
['棹', '木', '舟棹,行水', 'n'], ['楸', '木', '楸树,高直', 'n'],
|
|
152
|
+
['槐', '木', '槐树,三公之位', 'n'], ['橙', '木', '橙,明暖', 'n'],
|
|
153
|
+
['檀', '木', '檀香,沉静', 'n'],
|
|
154
|
+
// ── 扩充:火 ──
|
|
155
|
+
['丰', '火', '丰盛、丰盈(繁体豐从豆,归火)', 'n'], ['日', '火', '太阳,光明', 'm'],
|
|
156
|
+
['阳', '火', '阳光,向阳而生', 'm'], ['光', '火', '光明', 'n'],
|
|
157
|
+
['亮', '火', '明亮,爽朗', 'm'], ['明', '火', '光明、明理', 'n'],
|
|
158
|
+
['晶', '火', '晶莹,三光', 'f'], ['晴', '火', '晴朗,天开', 'f'],
|
|
159
|
+
['夏', '火', '夏天,盛大', 'n'], ['智', '火', '智慧,明达', 'm'],
|
|
160
|
+
['卓', '火', '卓越,卓立', 'm'], ['乐', '火', '和乐', 'n'],
|
|
161
|
+
['恺', '火', '恺悌,和乐', 'm'], ['恬', '火', '恬静', 'f'],
|
|
162
|
+
['甜', '火', '甜美', 'f'], ['亭', '火', '亭亭,端立', 'f'],
|
|
163
|
+
['俊', '火', '俊朗,才俊', 'm'], ['丙', '火', '天干丙,阳火', 'm'],
|
|
164
|
+
['丁', '火', '天干丁,阴火', 'n'], ['鼎', '火', '鼎立,厚重', 'm'],
|
|
165
|
+
['陶', '火', '陶然,自得', 'n'], ['熹', '火', '熹微,晨光', 'n'],
|
|
166
|
+
['炀', '火', '火旺,炽盛', 'm'], ['烜', '火', '烜赫,显明', 'm'],
|
|
167
|
+
['暻', '火', '日光', 'n'], ['晖', '火', '日晖,光彩', 'n'],
|
|
168
|
+
['晔', '火', '光晔,明盛', 'n'], ['旻', '火', '秋天,天高', 'm'],
|
|
169
|
+
['晏', '火', '晏然,安和', 'n'], ['晓', '火', '拂晓,天将明', 'f'],
|
|
170
|
+
['暄', '火', '温暖,日暖', 'f'], ['昆', '火', '昆山,同也', 'm'],
|
|
171
|
+
['伶', '火', '伶俐,聪敏', 'f'],
|
|
172
|
+
// ── 扩充:土 ──
|
|
173
|
+
['山', '土', '山,稳重', 'm'], ['岸', '土', '岸然,独立', 'm'],
|
|
174
|
+
['岑', '土', '小山,高而静', 'n'], ['巍', '土', '巍峨,高大', 'm'],
|
|
175
|
+
['嵩', '土', '嵩山,高峻', 'm'], ['岭', '土', '山岭,绵延', 'n'],
|
|
176
|
+
['奥', '土', '深奥,蕴藉', 'm'], ['宜', '土', '宜然,合度', 'n'],
|
|
177
|
+
['容', '土', '包容,容仪', 'n'], ['意', '土', '心意,诚意', 'f'],
|
|
178
|
+
['依', '土', '依倚,亲近', 'f'], ['悠', '土', '悠然,从容', 'f'],
|
|
179
|
+
['维', '土', '维系,纲维', 'n'], ['纬', '土', '经纬,有条', 'n'],
|
|
180
|
+
['永', '土', '永恒,久长', 'n'], ['远', '土', '高远', 'm'],
|
|
181
|
+
['辰', '土', '星辰、辰时', 'm'], ['壁', '土', '壁立,端正', 'm'],
|
|
182
|
+
['田', '土', '田野,耕获', 'm'], ['由', '土', '由来,自得', 'n'],
|
|
183
|
+
['画', '土', '图画,文采', 'f'], ['延', '土', '延展,绵长', 'm'],
|
|
184
|
+
['建', '土', '建立,树也', 'm'], ['音', '土', '音声,和鸣', 'f'],
|
|
185
|
+
['韵', '土', '韵致,余响', 'f'], ['玮', '土', '美玉,珍奇', 'm'],
|
|
186
|
+
['雍', '土', '雍容,和穆', 'm'], ['懿', '土', '懿德,美善', 'f'],
|
|
187
|
+
// ── 扩充:金 ──
|
|
188
|
+
['金', '金', '金,坚而贵', 'm'], ['秋', '金', '秋收、成熟(秋属金,肃而收)', 'n'],
|
|
189
|
+
['书', '金', '书卷,文墨', 'n'], ['舒', '金', '舒展,从容', 'n'],
|
|
190
|
+
['善', '金', '善良,善成', 'n'], ['信', '金', '诚信,符信', 'm'],
|
|
191
|
+
['修', '金', '修远,修身', 'm'], ['素', '金', '素雅,本色', 'f'],
|
|
192
|
+
['静', '金', '安静,沉静', 'f'], ['心', '金', '心志,中藏', 'f'],
|
|
193
|
+
['新', '金', '新意,日新', 'n'], ['正', '金', '正直,端正', 'm'],
|
|
194
|
+
['世', '金', '世代,绵延', 'm'], ['少', '金', '少年,少壮', 'm'],
|
|
195
|
+
['西', '金', '西方,金位', 'n'], ['白', '金', '洁白,素净', 'n'],
|
|
196
|
+
['辛', '金', '天干辛,阴金', 'n'], ['成', '金', '成器,成事', 'm'],
|
|
197
|
+
['利', '金', '利落,锋利', 'm'], ['剑', '金', '剑,刚锐', 'm'],
|
|
198
|
+
['刚', '金', '刚强,不屈', 'm'], ['则', '金', '法则,有度', 'm'],
|
|
199
|
+
['初', '金', '初心,开端', 'n'], ['硕', '金', '硕大,学殖', 'm'],
|
|
200
|
+
['尚', '金', '崇尚,尚贤', 'n'], ['臣', '金', '臣,佐事', 'm'],
|
|
201
|
+
['川', '金', '川流,通达', 'n'], ['舟', '金', '舟行,济渡', 'n'],
|
|
202
|
+
['州', '金', '州,聚落', 'n'], ['祖', '金', '祖德,源远', 'm'],
|
|
203
|
+
['祥', '金', '吉祥,祥瑞', 'n'], ['禄', '金', '福禄,俸给', 'm'],
|
|
204
|
+
['禧', '金', '禧庆,福', 'n'], ['珍', '金', '珍宝,珍重', 'f'],
|
|
205
|
+
['宣', '金', '宣明,布达', 'n'], ['序', '金', '秩序,庠序', 'n'],
|
|
206
|
+
['谦', '金', '谦逊,有终', 'm'], ['赞', '金', '赞美,佐成', 'm'],
|
|
207
|
+
['超', '金', '超越,越过', 'm'], ['锴', '金', '精铁,坚刚', 'm'],
|
|
208
|
+
// ── 扩充:水 ──
|
|
209
|
+
['水', '水', '水,润下', 'n'], ['冰', '水', '冰清,澄澈', 'f'],
|
|
210
|
+
['洁', '水', '洁净,洁身', 'f'], ['浩', '水', '浩大,广远', 'm'],
|
|
211
|
+
['瀚', '水', '浩瀚,无涯', 'm'], ['渊', '水', '渊深,有本', 'm'],
|
|
212
|
+
['澜', '水', '波澜,壮阔', 'n'], ['潮', '水', '潮涌,有信', 'n'],
|
|
213
|
+
['溪', '水', '溪流,清浅', 'f'], ['湘', '水', '湘水,清深', 'f'],
|
|
214
|
+
['渝', '水', '渝水,守而不变', 'n'], ['深', '水', '深厚,深藏', 'm'],
|
|
215
|
+
['湛', '水', '湛然,清深', 'm'], ['汇', '水', '汇聚,会归', 'n'],
|
|
216
|
+
['洲', '水', '洲渚,水中地', 'n'], ['湾', '水', '水湾,曲处', 'f'],
|
|
217
|
+
['云', '水', '云行,舒卷', 'n'], ['风', '水', '风雅,流动', 'n'],
|
|
218
|
+
['北', '水', '北方,水位', 'n'], ['冬', '水', '冬藏,静敛', 'f'],
|
|
219
|
+
['玄', '水', '玄远,幽深', 'n'], ['子', '水', '子,初生', 'm'],
|
|
220
|
+
['平', '水', '平和,坦易', 'n'], ['方', '水', '方正,有隅', 'n'],
|
|
221
|
+
['帆', '水', '风帆,顺行', 'n'], ['航', '水', '航行,济远', 'm'],
|
|
222
|
+
['敏', '水', '敏思,捷悟', 'f'], ['慧', '水', '慧心,明彻', 'f'],
|
|
223
|
+
['惠', '水', '惠泽,施与', 'f'], ['霈', '水', '霈雨,丰沛', 'm'],
|
|
224
|
+
['灏', '水', '灏气,广大', 'm'], ['湄', '水', '水湄,岸边', 'f'],
|
|
225
|
+
['滨', '水', '水滨,近水', 'n'], ['洛', '水', '洛水,清流', 'n'],
|
|
226
|
+
['津', '水', '津渡,要处', 'n'], ['泊', '水', '淡泊,自守', 'm'],
|
|
227
|
+
['沧', '水', '沧海,苍茫', 'm'], ['浦', '水', '浦,水滨', 'n'],
|
|
119
228
|
];
|
|
120
229
|
|
|
121
230
|
const EL_INDEX = new Map();
|
|
@@ -123,6 +232,24 @@ for (const c of CHAR_LIB) {
|
|
|
123
232
|
if (!EL_INDEX.has(c[0])) EL_INDEX.set(c[0], { c: c[0], el: c[1], meaning: c[2], g: c[3], order: EL_INDEX.size });
|
|
124
233
|
}
|
|
125
234
|
|
|
235
|
+
/** 用户可自带某字的五行(字库未收时用,按你信的那派算;传了就算「用户指定」)。 */
|
|
236
|
+
function userElement(input, ch) {
|
|
237
|
+
const map = input && input.charElements;
|
|
238
|
+
if (!map || typeof map !== 'object') return null;
|
|
239
|
+
const v = map[ch];
|
|
240
|
+
return ALL.includes(v) ? v : null;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** 喜用五行里挑几个可替换的常用字(同性别倾向优先),给未收录字一个落点。 */
|
|
244
|
+
function suggestFor(element, genderPref, exclude, count = 3) {
|
|
245
|
+
const pool = CHAR_LIB.filter((c) => c[1] === element && !exclude.has(c[0]));
|
|
246
|
+
pool.sort((a, b) => {
|
|
247
|
+
const fit = (x) => (x[3] === genderPref || x[3] === 'n' ? 1 : 0);
|
|
248
|
+
return fit(b) - fit(a);
|
|
249
|
+
});
|
|
250
|
+
return pool.slice(0, count).map((c) => ({ char: c[0], element: c[1], meaning: c[2] }));
|
|
251
|
+
}
|
|
252
|
+
|
|
126
253
|
const KIND_LABEL = { m: '男', f: '女', n: '中' };
|
|
127
254
|
|
|
128
255
|
/** 喜用五行(简化判定:旺衰 + 生克泄耗)。 */
|
|
@@ -178,23 +305,44 @@ export function assessName(input) {
|
|
|
178
305
|
baziNote = { dayMaster: r.dayMaster, solarNote: r.solarTime ? r.solarTime.note : '' };
|
|
179
306
|
}
|
|
180
307
|
|
|
308
|
+
const genderPref = input.gender === 'female' ? 'f' : 'm';
|
|
309
|
+
const taken = new Set([surname, ...given]);
|
|
310
|
+
const favPool = favorable.list.length ? favorable.list : ALL.slice();
|
|
181
311
|
const chars = [...given].map((ch) => {
|
|
182
312
|
const info = charInfo(ch);
|
|
183
|
-
const
|
|
313
|
+
const given = userElement(input, ch);
|
|
314
|
+
if (info) {
|
|
315
|
+
return {
|
|
316
|
+
char: ch, element: info.el, meaning: info.meaning,
|
|
317
|
+
genderHint: KIND_LABEL[info.g], favorable: hasBirth ? favorable.list.includes(info.el) : null,
|
|
318
|
+
source: 'lib', note: null,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
if (given) {
|
|
322
|
+
return {
|
|
323
|
+
char: ch, element: given, meaning: '字库未收录;五行按你指定的「' + given + '」计',
|
|
324
|
+
genderHint: null, favorable: hasBirth ? favorable.list.includes(given) : null,
|
|
325
|
+
source: 'user', note: '此字五行由调用方指定,不是字库推断',
|
|
326
|
+
};
|
|
327
|
+
}
|
|
184
328
|
return {
|
|
185
|
-
char: ch,
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
329
|
+
char: ch, element: '未收录', meaning: '字库未收录,未推断五行(不猜)',
|
|
330
|
+
genderHint: null, favorable: null, source: 'none',
|
|
331
|
+
note: hasBirth ? '若想贴合命局,可换用下面的同喜用字' : '字库未收录:给出生辰后可以看同喜用的替换字',
|
|
332
|
+
suggest: hasBirth
|
|
333
|
+
? favPool.flatMap((el) => suggestFor(el, genderPref, taken, 2))
|
|
334
|
+
: [],
|
|
190
335
|
};
|
|
191
336
|
});
|
|
192
|
-
const known = chars.filter((c) => c.
|
|
337
|
+
const known = chars.filter((c) => c.source === 'lib').length;
|
|
338
|
+
const unknown = chars.filter((c) => c.source === 'none').length;
|
|
193
339
|
const favCount = chars.filter((c) => c.favorable === true).length;
|
|
340
|
+
const judged = chars.length - unknown;
|
|
194
341
|
let verdict;
|
|
195
342
|
if (!hasBirth) verdict = '只做了字义与五行归类;给出生年月日才能判断用字是否合喜用。';
|
|
196
|
-
else if (
|
|
197
|
-
else if (favCount > 0) verdict =
|
|
343
|
+
else if (unknown === chars.length) verdict = `两字都不在字库里,没法判断合不合喜用(喜用为 ${favorable.list.join('、')})。下面给了可替换的常用字,或把你自己认定的五行传进来。`;
|
|
344
|
+
else if (favCount === judged && judged > 0) verdict = `用字都落在喜用(${favorable.list.join('、')})上,与命局方向一致。`;
|
|
345
|
+
else if (favCount > 0) verdict = `部分用字合喜用(${favCount}/${judged}),其余可再斟酌;喜用为 ${favorable.list.join('、')}。`;
|
|
198
346
|
else verdict = `用字未落在喜用(${favorable.list.join('、')})上;不必然是坏名,但若想贴合命局可换字再看。`;
|
|
199
347
|
|
|
200
348
|
return {
|
|
@@ -212,10 +360,10 @@ export function assessName(input) {
|
|
|
212
360
|
},
|
|
213
361
|
} : {}),
|
|
214
362
|
chars,
|
|
215
|
-
stats: { chars: chars.length, known, favorableCount: favCount },
|
|
363
|
+
stats: { chars: chars.length, known, unknown, favorableCount: favCount, libSize: CHAR_LIB.length },
|
|
216
364
|
verdict,
|
|
217
365
|
notes: [
|
|
218
|
-
|
|
366
|
+
`字之五行按通行字义/偏旁归类,自建字库共 ${CHAR_LIB.length} 字(常用名用字为主);未收录的字不猜五行,如实标注,「用户指定」是你传入的归类。`,
|
|
219
367
|
'不做五格剖象(需康熙字典笔画),也不做音韵格律判断——谐音、拗口请自己读三遍或用方言读一遍。',
|
|
220
368
|
'起名只做用字参考,不替父母做决定。',
|
|
221
369
|
],
|
|
@@ -267,19 +415,41 @@ export function generateNames(input) {
|
|
|
267
415
|
elements: [a[1], b[1]],
|
|
268
416
|
allFavorable: fav.list.includes(a[1]) && fav.list.includes(b[1]),
|
|
269
417
|
genderScore: gScore,
|
|
270
|
-
order: i *
|
|
418
|
+
order: (i * 7 + j * 13) % 9973, // 打散字库顺序,避免候选清一色都是前几个字
|
|
271
419
|
});
|
|
272
420
|
}
|
|
273
421
|
}
|
|
274
|
-
|
|
422
|
+
const mixed = (c) => (c.elements[0] !== c.elements[1] ? 1 : 0); // 两字异行,比同气堆叠更有层次
|
|
423
|
+
scored.sort((x, y) => (y.allFavorable - x.allFavorable) || (mixed(y) - mixed(x)) || (y.genderScore - x.genderScore) || (x.order - y.order));
|
|
424
|
+
// 去重 + 用字轮换:先收「两个字都没出现过」的候选,再放宽——避免 20 个候选里 13 个都用同一个「梓」
|
|
275
425
|
const out = [];
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
426
|
+
const usedNames = new Set();
|
|
427
|
+
const usedChars = new Set([surname]);
|
|
428
|
+
const usedPairs = new Set();
|
|
429
|
+
const take = (cand, strict, freshPair) => {
|
|
279
430
|
const key = [...cand.name].sort().join('');
|
|
280
|
-
if (
|
|
281
|
-
|
|
431
|
+
if (usedNames.has(key)) return false;
|
|
432
|
+
if (strict && cand.chars.some((x) => usedChars.has(x.char))) return false;
|
|
433
|
+
const pair = cand.elements.join('');
|
|
434
|
+
if (freshPair && usedPairs.has(pair)) return false;
|
|
435
|
+
usedNames.add(key);
|
|
436
|
+
usedPairs.add(pair);
|
|
437
|
+
cand.chars.forEach((x) => usedChars.add(x.char));
|
|
282
438
|
out.push({ rank: out.length + 1, name: surname + cand.name, given: cand.name, chars: cand.chars });
|
|
439
|
+
return true;
|
|
440
|
+
};
|
|
441
|
+
// 三轮:①新字 + 新五行组合 ②新字 ③放开——先保证候选之间不撞字、不撞组合
|
|
442
|
+
for (const cand of scored) {
|
|
443
|
+
if (out.length >= limit) break;
|
|
444
|
+
take(cand, true, true);
|
|
445
|
+
}
|
|
446
|
+
for (const cand of scored) {
|
|
447
|
+
if (out.length >= limit) break;
|
|
448
|
+
take(cand, true, false);
|
|
449
|
+
}
|
|
450
|
+
for (const cand of scored) {
|
|
451
|
+
if (out.length >= limit) break;
|
|
452
|
+
take(cand, false, false);
|
|
283
453
|
}
|
|
284
454
|
return {
|
|
285
455
|
system: 'name',
|
|
@@ -289,7 +459,7 @@ export function generateNames(input) {
|
|
|
289
459
|
bazi: { dayMaster: r.dayMaster, strength, favorable: fav.list, basis: fav.basis },
|
|
290
460
|
candidates: out,
|
|
291
461
|
notes: [
|
|
292
|
-
`字库共 ${CHAR_LIB.length} 字,只在喜用五行(${fav.list.join('、')}
|
|
462
|
+
`字库共 ${CHAR_LIB.length} 字,只在喜用五行(${fav.list.join('、')})里选字;未覆盖的生僻好字可用 charElements 指定五行后评估。`,
|
|
293
463
|
'候选按合喜用与性别倾向确定性排序,不是「吉名」判定;音韵与方言谐音请自行读念检查。',
|
|
294
464
|
'不做五格剖象(需康熙字典笔画)。',
|
|
295
465
|
],
|