dsh-metaphysics 0.34.0 → 0.38.2
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 +103 -3
- package/README.md +342 -309
- package/client.js +1137 -137
- package/docs/assets/dsh-metaphysics-group.png +0 -0
- package/engine/bazi.js +48 -2
- package/engine/classics.js +123 -7
- package/engine/followup.js +58 -0
- package/engine/index.js +54 -15
- package/engine/interpret-knowledge.js +50 -4
- package/engine/interpret-plain.js +46 -3
- package/engine/interpret.js +78 -1
- package/engine/liuyao.js +145 -0
- package/engine/ziwei.js +119 -13
- package/locale/zh.json +1 -1
- package/package.json +16 -14
- package//345/221/275/347/220/206/346/216/222/347/233/230.html +1213 -167
package/engine/interpret.js
CHANGED
|
@@ -342,6 +342,19 @@ function baziInterpret(r) {
|
|
|
342
342
|
return `${jiaoLine}当前大运:${pick(cur, 'ganzhi', '—')}(${curSpan})。后续两步:${nextTwo}。\n近五年流年:${years || '—'}。\n读法:大运管"这十年的大环境",流年管"今年的具体天气";两者打架时,以能否动到用神为准。`;
|
|
343
343
|
})(),
|
|
344
344
|
},
|
|
345
|
+
(() => {
|
|
346
|
+
const hits = (r.liunian || []).filter((l) => l.suiyun && Array.isArray(l.suiyun.signals) && l.suiyun.signals.length);
|
|
347
|
+
return {
|
|
348
|
+
key: 'suiyun', label: '岁运提示',
|
|
349
|
+
text: hits.length
|
|
350
|
+
? hits.map((l) => {
|
|
351
|
+
const stem = (l.suiyun.dayun || []).map((d) => `第${d.step}步${d.ganzhi}`).join('、');
|
|
352
|
+
return `${l.year} ${l.ganzhi}(${stem || '未到起运'}):${l.suiyun.signals.map((s) => s.detail).join(';')}`;
|
|
353
|
+
}).join('\n') +
|
|
354
|
+
'\n读法:岁运并临、运年反吟与流年伏吟/反吟只说明干支层面重复或对冲,传统上当作「变动感较强」的信号;本插件不据此判吉凶,要落到具体年份,仍看该年是否动到用神。'
|
|
355
|
+
: '近十年没有岁运并临、运年反吟或流年伏吟/反吟。「岁运并临主大凶」这类说法流传很广,本插件只把它当变动提示,没有命中就不作额外解读。',
|
|
356
|
+
};
|
|
357
|
+
})(),
|
|
345
358
|
{
|
|
346
359
|
key: 'checks', label: '交叉校验',
|
|
347
360
|
text: (() => {
|
|
@@ -699,6 +712,39 @@ function ziweiInterpret(r) {
|
|
|
699
712
|
}
|
|
700
713
|
}
|
|
701
714
|
|
|
715
|
+
// 三方四正复合飞化:命宫连同对宫与两个三合宫一起飞,四宫 16 条按落宫归堆
|
|
716
|
+
{
|
|
717
|
+
const fc = r.flyComposite;
|
|
718
|
+
const word = (p) => `${p}${String(p).endsWith('宫') ? '' : '宫'}`;
|
|
719
|
+
if (fc && Array.isArray(fc.sources) && fc.sources.length >= 2) {
|
|
720
|
+
const hubs = fc.targets.filter((t) => t.count >= 2);
|
|
721
|
+
const hubText = hubs.length
|
|
722
|
+
? hubs.slice(0, 5).map((t) => `${word(t.palace)}收了 ${t.incoming.map((x) => `${word(x.from)}化${x.type}${x.star}`).join('、')}`).join(';')
|
|
723
|
+
: '四宫化出去之后没有落在同一宫,力是散开的';
|
|
724
|
+
const readings = [];
|
|
725
|
+
if (fc.groups.doubleJi.length) {
|
|
726
|
+
readings.push(`${fc.groups.doubleJi.map((t) => word(t.palace)).join('、')}收到两个以上的忌——同一件事被反复牵动,传统看作那一宫的事务容易拖着不放`);
|
|
727
|
+
}
|
|
728
|
+
if (fc.groups.luJi.length) {
|
|
729
|
+
readings.push(`${fc.groups.luJi.map((t) => word(t.palace)).join('、')}禄忌同宫:好处与在意的地方绑在一起,越想要的东西越容易反复`);
|
|
730
|
+
}
|
|
731
|
+
if (fc.groups.tripleHua.length) {
|
|
732
|
+
readings.push(`${fc.groups.tripleHua.map((t) => word(t.palace)).join('、')}三化以上会宫:那一宫同时被几种力牵住,常常是这张盘最忙的地方`);
|
|
733
|
+
}
|
|
734
|
+
if (fc.groups.selfHua.length) {
|
|
735
|
+
readings.push(`${fc.groups.selfHua.map((t) => word(t.palace)).join('、')}自化:宫干化出去又落回自己,表现为力气绕回原处`);
|
|
736
|
+
}
|
|
737
|
+
sections.push({
|
|
738
|
+
key: 'flyComposite',
|
|
739
|
+
label: '三方四正飞化',
|
|
740
|
+
text: `上一节是命宫一条线往下追;这一节把命宫连同对宫与两个三合宫(${fc.sanfang.join('、')})一起飞:四宫各化禄权科忌,共 16 条飞化(星未上盘的只记星不记落宫),按落宫归堆。` +
|
|
741
|
+
`${hubText}。` +
|
|
742
|
+
`${readings.length ? `${readings.join(';')}。` : ''}` +
|
|
743
|
+
`读法上,会在一处的化越多,那一宫被牵动的力道越集中;落单的飞化只说明方向,不单独取象。这一层同样只描会照与方向,不折吉凶,也没有叠大限与流年四化。`,
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
702
748
|
// 流月/流日/流时:流年只回答「今年」,再往下才是「这个月」「这两天」
|
|
703
749
|
if (r.flow) {
|
|
704
750
|
const f = r.flow;
|
|
@@ -870,6 +916,10 @@ function liuyaoInterpret(r, ask) {
|
|
|
870
916
|
const tuiYao = (bd.jinTui || []).filter((x) => x.type === '退');
|
|
871
917
|
if (jinYao.length) bodyText.push(`化进神(第${jinYao.map((x) => x.position).join('、')}爻:${jinYao.map((x) => `${x.from}→${x.to}`).join('、')}):变出的地支与本爻同五行、且顺着往前一步,传统读作「进」——这一爻代表的人或事有后劲,往前走比退回去顺。`);
|
|
872
918
|
if (tuiYao.length) bodyText.push(`化退神(第${tuiYao.map((x) => x.position).join('、')}爻:${tuiYao.map((x) => `${x.from}→${x.to}`).join('、')}):变出的地支与本爻同五行、却倒着退一步,传统读作「退」——这一爻代表的人或事渐渐退气,别按原来的势头去推。`);
|
|
919
|
+
const jp = r.jinTuiPower;
|
|
920
|
+
if (jp && Array.isArray(jp.lines) && jp.lines.length) {
|
|
921
|
+
bodyText.push(`进退的力重(放回月建日辰看):${jp.lines.map((l) => `第${l.position}爻${l.say}`).join(';')}。进退只管方向,走不走得动看时令托不托着;用神化进为喜,忌神化进反而是忌。`);
|
|
922
|
+
}
|
|
873
923
|
bodyText.push('这些标签只说明卦体的动势,不直接定吉凶:同一支六冲,近病问的是速愈、久病问的是凶险;同一爻化进,也得看用神旺不旺、有没有月建日辰托着。');
|
|
874
924
|
sections.push({ key: 'body', label: '卦体关系', text: bodyText.join('\n') });
|
|
875
925
|
}
|
|
@@ -929,9 +979,36 @@ function liuyaoInterpret(r, ask) {
|
|
|
929
979
|
sections.push({ key: 'yongshen', label: '用神落位与卦体', text: useText.join('\n') });
|
|
930
980
|
}
|
|
931
981
|
|
|
982
|
+
// 全卦逐爻旺衰:不挑用神,六爻都过一遍,看整张卦的气压在哪一头
|
|
983
|
+
{
|
|
984
|
+
const hs = r.hexStrength;
|
|
985
|
+
if (hs && Array.isArray(hs.lines) && hs.lines.length) {
|
|
986
|
+
const head = hs.month && hs.month.branch
|
|
987
|
+
? `月建 ${hs.month.branch}(${hs.month.element})`
|
|
988
|
+
: '没有月建(未给起卦时间)';
|
|
989
|
+
const day = hs.day && hs.day.branch ? `日辰 ${hs.day.branch}(${hs.day.element})` : '日辰 —';
|
|
990
|
+
const rows = hs.lines.map((l) => {
|
|
991
|
+
const who = l.shi ? '(世)' : l.ying ? '(应)' : '';
|
|
992
|
+
const flags = `${l.moving ? '·动' : ''}${l.kong ? '·旬空' : ''}`;
|
|
993
|
+
return `${l.position}爻${l.liuqin ? l.liuqin : ''}${l.branch}${l.element}${who}${flags}:月建${l.monthState},${l.dayRelation}${l.chongTag ? `,${l.chongTag}` : ''}`;
|
|
994
|
+
});
|
|
995
|
+
const order = ['旺', '相', '休', '囚', '死'];
|
|
996
|
+
const dist = order.filter((k) => hs.counts[k]).map((k) => `${k}${hs.counts[k]}`).join('、');
|
|
997
|
+
const shi = hs.shi ? `世爻在${hs.shi.position}爻(月建${hs.shi.monthState},${hs.shi.dayRelation})` : '';
|
|
998
|
+
const ying = hs.ying ? `应爻在${hs.ying.position}爻(月建${hs.ying.monthState},${hs.ying.dayRelation})` : '';
|
|
999
|
+
sections.push({
|
|
1000
|
+
key: 'hexStrength',
|
|
1001
|
+
label: '全卦逐爻旺衰',
|
|
1002
|
+
text: `整张卦按${head}、${day}逐爻过一遍:${rows.join(';')}。五态分布:${dist}——${[shi, ying].filter(Boolean).join(',')}。` +
|
|
1003
|
+
`气旺的爻对应的事推进起来省力,气弱或遭月破的爻对应的事宜缓;这只是六爻全貌,用神那几爻的细节仍以上一节为准,两处不冲突时再看动爻把哪一头带动。` +
|
|
1004
|
+
`判定与用神旺衰同一套(月令五态、日辰五关系、月破/暗动/冲空),只报状态,不折成分数。`,
|
|
1005
|
+
});
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
|
|
932
1009
|
sections.push({
|
|
933
1010
|
key: 'limits', label: '未纳入',
|
|
934
|
-
text: '
|
|
1011
|
+
text: '本卦没有计算:用神两现时该取哪一爻的权重、伏神出伏的应期。化进/化退的力重只按月建五态给「得令/失令」这类档位,不折成加权分数,也不叠动变连环;这些都会改变"旺不旺"的判断,所以这里只给取象与方向。',
|
|
935
1012
|
});
|
|
936
1013
|
|
|
937
1014
|
const dimensions = [
|
package/engine/liuyao.js
CHANGED
|
@@ -700,3 +700,148 @@ export function yongshenStrength(result, useGod, opts = {}) {
|
|
|
700
700
|
note: '月建主这一段的旺衰,日辰看当天是扶是克;两处都只给状态标签,不折成分数,也不单独断吉凶。',
|
|
701
701
|
};
|
|
702
702
|
}
|
|
703
|
+
|
|
704
|
+
// ── 全卦逐爻旺衰:月建日辰落到六爻全部 ──────────────────────────────
|
|
705
|
+
// 与用神旺衰同一套判定(月令五态、日辰五关系、三种冲法),区别只在不挑用神:
|
|
706
|
+
// 六爻每一爻都给一次,世应、动爻、旬空另标,看得出整张卦的气压在哪一头。
|
|
707
|
+
export function hexagramStrength(result, opts = {}) {
|
|
708
|
+
const rows = (result && result.ben && Array.isArray(result.ben.lines))
|
|
709
|
+
? result.ben.lines
|
|
710
|
+
: (result && Array.isArray(result.lines) ? result.lines : []);
|
|
711
|
+
if (!rows.length) return null;
|
|
712
|
+
const monthBranch = opts.monthBranch || null;
|
|
713
|
+
const dayBranch = opts.dayBranch || (result.dayGanZhi ? result.dayGanZhi.branch : null);
|
|
714
|
+
if (!monthBranch && !dayBranch) return null;
|
|
715
|
+
const monthElement = monthBranch ? zhiElementOf(monthBranch) : null;
|
|
716
|
+
const dayElement = dayBranch ? zhiElementOf(dayBranch) : null;
|
|
717
|
+
const kong = Array.isArray(result.xunKong)
|
|
718
|
+
? result.xunKong
|
|
719
|
+
: (typeof result.xunKong === 'string' ? result.xunKong.split('') : []);
|
|
720
|
+
const shiPos = result.ben ? result.ben.shi : null;
|
|
721
|
+
const yingPos = result.ben ? result.ben.ying : null;
|
|
722
|
+
|
|
723
|
+
const lines = rows.map((l) => {
|
|
724
|
+
const element = l.element || zhiElementOf(l.branch);
|
|
725
|
+
const monthChong = !!(monthBranch && CHONG_OF[l.branch] === monthBranch);
|
|
726
|
+
const dayChong = !!(dayBranch && CHONG_OF[l.branch] === dayBranch);
|
|
727
|
+
const monthState = monthStateOf(element, monthElement);
|
|
728
|
+
const dayRelation = dayRelationOf(element, dayElement);
|
|
729
|
+
const isEmpty = kong.includes(l.branch);
|
|
730
|
+
return {
|
|
731
|
+
position: l.position,
|
|
732
|
+
name: l.name,
|
|
733
|
+
branch: l.branch,
|
|
734
|
+
element,
|
|
735
|
+
liuqin: l.liuqin ?? null,
|
|
736
|
+
shi: l.position === shiPos,
|
|
737
|
+
ying: l.position === yingPos,
|
|
738
|
+
moving: !!l.moving,
|
|
739
|
+
kong: isEmpty,
|
|
740
|
+
monthState,
|
|
741
|
+
monthSay: MONTH_STATE_SAY[monthState] || '',
|
|
742
|
+
monthChong,
|
|
743
|
+
dayRelation,
|
|
744
|
+
daySay: DAY_RELATION_SAY[dayRelation] || '',
|
|
745
|
+
dayChong,
|
|
746
|
+
chongTag: monthChong ? '月破'
|
|
747
|
+
: dayChong ? (isEmpty ? '冲空' : (l.moving ? '逢日辰冲' : '暗动')) : '',
|
|
748
|
+
};
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
const counts = {};
|
|
752
|
+
for (const st of MONTH_STATE_ORDER) counts[st] = lines.filter((l) => l.monthState === st).length;
|
|
753
|
+
|
|
754
|
+
const labels = [];
|
|
755
|
+
for (const st of MONTH_STATE_ORDER) if (counts[st]) labels.push(`全卦${st}${counts[st]}爻`);
|
|
756
|
+
const shiLine = lines.find((l) => l.shi) || null;
|
|
757
|
+
const yingLine = lines.find((l) => l.ying) || null;
|
|
758
|
+
if (shiLine && shiLine.monthState !== 'unknown') labels.push(`世爻月建${shiLine.monthState}`);
|
|
759
|
+
if (yingLine && yingLine.monthState !== 'unknown') labels.push(`应爻月建${yingLine.monthState}`);
|
|
760
|
+
const tagCount = (tag) => lines.filter((l) => l.chongTag === tag).length;
|
|
761
|
+
for (const tag of ['月破', '暗动', '冲空', '逢日辰冲']) {
|
|
762
|
+
const n = tagCount(tag);
|
|
763
|
+
if (n) labels.push(`${tag}${n}爻`);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
return {
|
|
767
|
+
month: monthBranch ? { branch: monthBranch, element: monthElement } : null,
|
|
768
|
+
day: dayBranch ? { branch: dayBranch, element: dayElement } : null,
|
|
769
|
+
lines,
|
|
770
|
+
counts,
|
|
771
|
+
strongest: lines.filter((l) => l.monthState === '旺').map((l) => l.position),
|
|
772
|
+
weakest: lines.filter((l) => l.monthState === '死' || l.monthChong).map((l) => l.position),
|
|
773
|
+
shi: shiLine ? { position: shiLine.position, branch: shiLine.branch, monthState: shiLine.monthState, dayRelation: shiLine.dayRelation } : null,
|
|
774
|
+
ying: yingLine ? { position: yingLine.position, branch: yingLine.branch, monthState: yingLine.monthState, dayRelation: yingLine.dayRelation } : null,
|
|
775
|
+
labels,
|
|
776
|
+
note: '月建主这一段的旺衰、日辰管当天的扶克,六爻逐一给状态;判定与用神旺衰同一套,只多了世应与动爻标记。只报状态、不折分数,也不单独断吉凶。',
|
|
777
|
+
};
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// ── 化进 / 化退的力重:进退只管方向,走不走得动看时令 ─────────────────
|
|
781
|
+
// 化进只说明这一爻顺着往前走一步,能不能走实要放回月建日辰:
|
|
782
|
+
// 得令(旺/相)化进 → 后劲足;休/囚化进 → 后劲有限;逢死 → 进得虚
|
|
783
|
+
// 得令化退 → 退得缓(时令还托着,退得慢);失令化退 → 退得实
|
|
784
|
+
// 月破压过一切:爻遭月建冲,进退都站不稳,先看出空填实。
|
|
785
|
+
// 旬空只标出来、不并进结论——动爻旬空要等出空才算数。
|
|
786
|
+
// 《增删卜易》进神退神章讲「化进神须得日月生扶」,这里只做这一步,不叠动变连环。
|
|
787
|
+
const JIN_VERDICT = { 旺: '后劲足', 相: '后劲足', 休: '后劲有限', 囚: '后劲有限', 死: '进得虚' };
|
|
788
|
+
const TUI_VERDICT = { 旺: '退得缓', 相: '退得缓', 休: '退得实', 囚: '退得实', 死: '退得实' };
|
|
789
|
+
|
|
790
|
+
/**
|
|
791
|
+
* 化进 / 化退的力重:把 body.jinTui 每一条放回月建日辰结算。
|
|
792
|
+
* @param {object} result buildLiuyao 的结果(需带 body.jinTui)
|
|
793
|
+
* @param {{monthBranch?: string, dayBranch?: string}} opts
|
|
794
|
+
*/
|
|
795
|
+
export function jinTuiPower(result, opts = {}) {
|
|
796
|
+
const items = result && result.body && Array.isArray(result.body.jinTui) ? result.body.jinTui : [];
|
|
797
|
+
if (!items.length) return null;
|
|
798
|
+
const rows = result && result.ben && Array.isArray(result.ben.lines) ? result.ben.lines : [];
|
|
799
|
+
const monthBranch = opts.monthBranch || null;
|
|
800
|
+
const dayBranch = opts.dayBranch || (result && result.dayGanZhi ? result.dayGanZhi.branch : null);
|
|
801
|
+
const monthElement = monthBranch ? zhiElementOf(monthBranch) : null;
|
|
802
|
+
const dayElement = dayBranch ? zhiElementOf(dayBranch) : null;
|
|
803
|
+
const kong = Array.isArray(result && result.xunKong)
|
|
804
|
+
? result.xunKong
|
|
805
|
+
: (result && typeof result.xunKong === 'string' ? result.xunKong.split('') : []);
|
|
806
|
+
|
|
807
|
+
const lines = items.map((x) => {
|
|
808
|
+
const line = rows[x.position - 1] || null;
|
|
809
|
+
const element = (line && line.element) || zhiElementOf(x.from);
|
|
810
|
+
const monthState = monthStateOf(element, monthElement);
|
|
811
|
+
const monthChong = !!(monthBranch && CHONG_OF[x.from] === monthBranch);
|
|
812
|
+
const dayChong = !!(dayBranch && CHONG_OF[x.from] === dayBranch);
|
|
813
|
+
const dayRelation = dayRelationOf(element, dayElement);
|
|
814
|
+
const isEmpty = kong.includes(x.from);
|
|
815
|
+
// 判定顺序:无月建只报趋势 → 月破压过一切 → 按五态给进退定档
|
|
816
|
+
const verdict = !monthBranch ? '只报趋势'
|
|
817
|
+
: monthChong ? '月破失据'
|
|
818
|
+
: ((x.type === '进' ? JIN_VERDICT : TUI_VERDICT)[monthState] || '未定');
|
|
819
|
+
const monthSay = monthBranch
|
|
820
|
+
? `月建${monthBranch}(${monthElement})对${element}为${monthState}`
|
|
821
|
+
: '缺月建,只看日辰';
|
|
822
|
+
const daySay = dayRelation === 'unknown' ? '' : `日辰${dayBranch}(${dayElement})${dayRelation}`;
|
|
823
|
+
const extra = [monthChong ? '又遭月破' : '', isEmpty ? '旬空待填' : '', dayChong ? '逢日辰冲' : ''].filter(Boolean);
|
|
824
|
+
return {
|
|
825
|
+
position: x.position,
|
|
826
|
+
from: x.from,
|
|
827
|
+
to: x.to,
|
|
828
|
+
type: x.type,
|
|
829
|
+
element,
|
|
830
|
+
monthState,
|
|
831
|
+
monthChong,
|
|
832
|
+
dayRelation,
|
|
833
|
+
dayChong,
|
|
834
|
+
kong: isEmpty,
|
|
835
|
+
verdict,
|
|
836
|
+
say: `${x.from}→${x.to}(${x.type}):${monthSay}${daySay ? `,${daySay}` : ''}${extra.length ? `,${extra.join('、')}` : ''} → ${verdict}`,
|
|
837
|
+
};
|
|
838
|
+
});
|
|
839
|
+
|
|
840
|
+
return {
|
|
841
|
+
month: monthBranch ? { branch: monthBranch, element: monthElement } : null,
|
|
842
|
+
day: dayBranch ? { branch: dayBranch, element: dayElement } : null,
|
|
843
|
+
lines,
|
|
844
|
+
labels: lines.map((l) => `${l.position}爻化${l.type}·${l.verdict}`),
|
|
845
|
+
note: '进退只说这一爻往哪边走;力重是把它放回月建日辰,看有没有托着——得令则进得动、退得慢,失令则进得虚、退得实,月破压过一切。仍不直接定吉凶:用神化进为喜,忌神化进反而是忌。',
|
|
846
|
+
};
|
|
847
|
+
}
|
package/engine/ziwei.js
CHANGED
|
@@ -518,6 +518,7 @@ export function buildZiwei(input) {
|
|
|
518
518
|
shensha: '长生、博士随大限顺逆;将前、岁前恒顺行;天伤恒在交友、天使恒在疾厄',
|
|
519
519
|
masters: '命主按命宫地支,身主按生年地支',
|
|
520
520
|
liunian: '流年命宫取该年地支宫;三方四正为本宫与 +4/+8/+6;并给该年所属大限与小限',
|
|
521
|
+
flyComposite: '三方四正取本宫、对宫与两个三合宫共四宫,四宫宫干各化禄权科忌共 16 条,按落宫归堆标会聚(双忌会、禄忌同宫、三化会、自化);只描会照,不折吉凶',
|
|
521
522
|
changqu: '昌曲落宫只由时支决定,故与丑未的关系(夹/三合/同宫/无关)是结构性结论;absorb 的「清/杂」是启发式标记,依据昌曲化忌与会煞,不是断语',
|
|
522
523
|
},
|
|
523
524
|
};
|
|
@@ -526,14 +527,16 @@ export function buildZiwei(input) {
|
|
|
526
527
|
chart.daxianList = daxianList(chart);
|
|
527
528
|
chart.fly = flyStars(chart);
|
|
528
529
|
chart.flyChains = flyChains(chart, { from: '命宫' });
|
|
530
|
+
chart.flyComposite = flyComposite(chart, { from: '命宫' });
|
|
529
531
|
enrichLiunian(chart);
|
|
530
532
|
// 流月/流日/流时:默认按本机当前时刻,可用 asOf 指定(如 "2026-10-22T16:00")
|
|
531
533
|
chart.flow = flowOf(chart, input.asOf);
|
|
532
534
|
chart.patternSummary = {
|
|
533
535
|
count: chart.patterns.length,
|
|
534
536
|
good: chart.patterns.filter((p) => p.tone === 'good').map((p) => p.name),
|
|
537
|
+
neutral: chart.patterns.filter((p) => p.tone === 'neutral').map((p) => p.name),
|
|
535
538
|
bad: chart.patterns.filter((p) => p.tone === 'bad').map((p) => p.name),
|
|
536
|
-
note: '
|
|
539
|
+
note: '格局只描述结构,不作吉凶断语;同一命盘可并存吉格、中性结构与忌格',
|
|
537
540
|
};
|
|
538
541
|
return chart;
|
|
539
542
|
}
|
|
@@ -575,19 +578,18 @@ export function detectPatterns(chart) {
|
|
|
575
578
|
|
|
576
579
|
const lu = starBranchOf(chart, '禄存');
|
|
577
580
|
const ma = starBranchOf(chart, '天马');
|
|
578
|
-
if (lu >= 0 && ma >= 0 && (lu === ma || fix(lu - ma) === 6)) add('禄马交驰', `禄存在${
|
|
581
|
+
if (lu >= 0 && ma >= 0 && (lu === ma || fix(lu - ma) === 6)) add('禄马交驰', `禄存在${BRANCHES[lu]},天马在${BRANCHES[ma]}`);
|
|
579
582
|
|
|
580
583
|
const huo = starBranchOf(chart, '火星');
|
|
581
584
|
const ling = starBranchOf(chart, '铃星');
|
|
582
585
|
if (fix(soulIdx - 1) === huo && fix(soulIdx + 1) === ling) add('火铃夹命', '火星在命宫前一宫、铃星在后一宫夹命');
|
|
583
586
|
if (fix(soulIdx - 1) === ling && fix(soulIdx + 1) === huo) add('火铃夹命', '铃星与火星夹命');
|
|
584
587
|
|
|
588
|
+
// 擎羊在禄存 +1、陀罗在禄存 -1,两星只能夹「禄存」那一宫;
|
|
589
|
+
// 所以「羊陀夹忌」实际就是化忌与禄存同宫,按左右两侧去找永远找不到。
|
|
585
590
|
const ji = chart.palaces.find((p) => p.stars.some((s) => s.mutagen === '忌'));
|
|
586
|
-
if (ji) {
|
|
587
|
-
|
|
588
|
-
if (fix(jb - 1) === starBranchOf(chart, '擎羊') && fix(jb + 1) === starBranchOf(chart, '陀罗')) {
|
|
589
|
-
add('羊陀夹忌', `化忌在${ji.branch},擎羊陀罗夹之`);
|
|
590
|
-
}
|
|
591
|
+
if (ji && lu >= 0 && BRANCHES.indexOf(ji.branch) === lu) {
|
|
592
|
+
add('羊陀夹忌', `化忌与禄存在${ji.branch}同宫,擎羊陀罗夹之`);
|
|
591
593
|
}
|
|
592
594
|
|
|
593
595
|
// 铃昌陀武:四星会于命宫三方四正
|
|
@@ -605,10 +607,14 @@ export function detectPatterns(chart) {
|
|
|
605
607
|
// ── 以下为扩展格局(条件都是星位判断,evidence 写明落在哪宫)──
|
|
606
608
|
const inSoul = (name) => soul.stars.some((s) => s.name === name);
|
|
607
609
|
const nearStar = (name) => near.has(name);
|
|
610
|
+
// 「夹」只要求两星分居命宫前后,不分左右——日月、左右、魁钺本来就没有固定左右;
|
|
611
|
+
// 旧写法只认一种顺序,昌曲夹命与羊陀夹命因此从未命中,日月/左右/魁钺也漏掉一半。
|
|
608
612
|
const jia = (a, b) => {
|
|
609
613
|
const ba = starBranchOf(chart, a);
|
|
610
614
|
const bb = starBranchOf(chart, b);
|
|
611
|
-
|
|
615
|
+
if (ba < 0 || bb < 0) return false;
|
|
616
|
+
return (fix(ba + 1) === soulIdx && fix(bb - 1) === soulIdx)
|
|
617
|
+
|| (fix(bb + 1) === soulIdx && fix(ba - 1) === soulIdx);
|
|
612
618
|
};
|
|
613
619
|
const mutagensIn = (indices) => {
|
|
614
620
|
const set = new Set();
|
|
@@ -642,7 +648,7 @@ export function detectPatterns(chart) {
|
|
|
642
648
|
if (jia('左辅', '右弼')) add('左右夹命', '左辅、右弼夹命宫');
|
|
643
649
|
if (jia('文昌', '文曲')) add('昌曲夹命', '文昌、文曲夹命宫');
|
|
644
650
|
if (jia('天魁', '天钺')) add('魁钺夹命', '天魁、天钺夹命宫');
|
|
645
|
-
if (jia('擎羊', '陀罗')) add('羊陀夹命',
|
|
651
|
+
if (jia('擎羊', '陀罗')) add('羊陀夹命', `禄存在${BRANCHES[soulIdx]}守命,擎羊陀罗前后夹之`);
|
|
646
652
|
|
|
647
653
|
// 四化
|
|
648
654
|
const muts = mutagensIn(sanfang);
|
|
@@ -657,9 +663,13 @@ export function detectPatterns(chart) {
|
|
|
657
663
|
const lianzhen = starBranchOf(chart, '廉贞');
|
|
658
664
|
const tianxiang = starBranchOf(chart, '天相');
|
|
659
665
|
const qingyang = starBranchOf(chart, '擎羊');
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
666
|
+
// 天相与廉贞永远隔偶数宫,字面上的「廉贞、擎羊夹天相」不可能成立;
|
|
667
|
+
// 通行说法取「廉贞天相同守命宫于子午、擎羊同宫」——判的是守命那一宫,其它宫位同宫不算。
|
|
668
|
+
// 命宫卯酉、廉贞天相对照遇擎羊的变体未纳入。
|
|
669
|
+
if (lianzhen >= 0 && tianxiang >= 0 && qingyang >= 0
|
|
670
|
+
&& lianzhen === tianxiang && qingyang === tianxiang && tianxiang === soulIdx
|
|
671
|
+
&& (tianxiang === 0 || tianxiang === 6)) {
|
|
672
|
+
add('刑囚夹印', `廉贞天相同守命宫${BRANCHES[tianxiang]},擎羊同宫`);
|
|
663
673
|
}
|
|
664
674
|
if (near.has('贪狼') && (near.has('火星') || near.has('铃星'))) {
|
|
665
675
|
add('火贪铃贪', `贪狼与${near.has('火星') ? '火星' : '铃星'}会于命宫三方四正`);
|
|
@@ -676,7 +686,7 @@ export function detectPatterns(chart) {
|
|
|
676
686
|
.map((p) => ({ ...p, tone: PATTERN_TONE[p.name] || 'neutral' }));
|
|
677
687
|
}
|
|
678
688
|
|
|
679
|
-
const PATTERN_TONE = {
|
|
689
|
+
export const PATTERN_TONE = {
|
|
680
690
|
紫府同宫: 'good', 紫府朝垣: 'good', 君臣庆会: 'good', 极向离明: 'good',
|
|
681
691
|
七杀朝斗: 'good', 英星入庙: 'good', 石中隐玉: 'good', 巨日同宫: 'good',
|
|
682
692
|
日月夹命: 'good', 日月对照: 'good', 左右夹命: 'good', 昌曲夹命: 'good',
|
|
@@ -795,6 +805,102 @@ export function flyChains(chart, { from = '命宫', maxSteps = 12 } = {}) {
|
|
|
795
805
|
return out;
|
|
796
806
|
}
|
|
797
807
|
|
|
808
|
+
// ── 三方四正复合飞化:四宫一起飞、看落到同一宫的会聚 ─────────────────
|
|
809
|
+
// 单宫飞化回答「这一宫自己去找谁」;三方四正看的是本宫连同对宫、两个三合宫
|
|
810
|
+
// 四股力同时飞出去,最后在哪一宫会到一起。会在一处的化越多,那一宫被牵动的力道越集中。
|
|
811
|
+
// 只归堆与标会照,不折吉凶:同样是双忌会一宫,落在生年忌和落在生年禄上意思完全不同。
|
|
812
|
+
const PALACE_SUFFIX = (p) => `${p}${String(p).endsWith('宫') ? '' : '宫'}`;
|
|
813
|
+
|
|
814
|
+
export function flyComposite(chart, { from = '命宫' } = {}) {
|
|
815
|
+
const palaces = chart.palaces || [];
|
|
816
|
+
const src = palaces.find((p) => p.palace === from) || palaces[0];
|
|
817
|
+
if (!src) return null;
|
|
818
|
+
const names = Array.isArray(src.sanfang) && src.sanfang.length
|
|
819
|
+
? [...new Set(src.sanfang)].slice(0, 4)
|
|
820
|
+
: [src.palace];
|
|
821
|
+
|
|
822
|
+
const sources = [];
|
|
823
|
+
for (const name of names) {
|
|
824
|
+
const p = palaces.find((x) => x.palace === name);
|
|
825
|
+
if (!p) continue;
|
|
826
|
+
sources.push({
|
|
827
|
+
palace: p.palace,
|
|
828
|
+
branch: p.branch,
|
|
829
|
+
stem: p.stem,
|
|
830
|
+
flies: FLY_TYPES.map((type) => {
|
|
831
|
+
const star = flyStarOf(p.stem, type);
|
|
832
|
+
const b = star ? starBranchOf(chart, star) : -1;
|
|
833
|
+
const target = b >= 0 ? palaces.find((x) => x.branch === BRANCHES[b]) : null;
|
|
834
|
+
return {
|
|
835
|
+
type,
|
|
836
|
+
star,
|
|
837
|
+
to: target ? target.palace : null,
|
|
838
|
+
toBranch: target ? target.branch : null,
|
|
839
|
+
self: !!(target && target.palace === p.palace),
|
|
840
|
+
};
|
|
841
|
+
}),
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// 16 条飞化按落宫归堆;未上盘的星不计入落点
|
|
846
|
+
const targets = [];
|
|
847
|
+
for (const p of palaces) {
|
|
848
|
+
const incoming = [];
|
|
849
|
+
for (const s of sources) {
|
|
850
|
+
for (const f of s.flies) {
|
|
851
|
+
if (f.to === p.palace) {
|
|
852
|
+
incoming.push({ from: s.palace, fromBranch: s.branch, fromStem: s.stem, type: f.type, star: f.star, self: f.self });
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
if (!incoming.length) continue;
|
|
857
|
+
targets.push({
|
|
858
|
+
palace: p.palace,
|
|
859
|
+
branch: p.branch,
|
|
860
|
+
incoming,
|
|
861
|
+
types: [...new Set(incoming.map((x) => x.type))],
|
|
862
|
+
count: incoming.length,
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
targets.sort((a, b) => b.count - a.count || BRANCHES.indexOf(a.branch) - BRANCHES.indexOf(b.branch));
|
|
866
|
+
|
|
867
|
+
const jiAt = (t) => t.incoming.filter((x) => x.type === '忌').length;
|
|
868
|
+
const groups = {
|
|
869
|
+
doubleJi: targets.filter((t) => jiAt(t) >= 2),
|
|
870
|
+
luJi: targets.filter((t) => t.types.includes('禄') && t.types.includes('忌')),
|
|
871
|
+
tripleHua: targets.filter((t) => t.types.length >= 3),
|
|
872
|
+
selfHua: targets.filter((t) => t.incoming.some((x) => x.self)),
|
|
873
|
+
};
|
|
874
|
+
|
|
875
|
+
const labels = [];
|
|
876
|
+
for (const t of groups.doubleJi) labels.push(`${['', '', '双忌', '三忌', '四忌'][jiAt(t)] || `${jiAt(t)}忌`}会${PALACE_SUFFIX(t.palace)}`);
|
|
877
|
+
for (const t of groups.luJi) labels.push(`禄忌同宫${PALACE_SUFFIX(t.palace)}`);
|
|
878
|
+
const HUA_NUM = { 3: '三化会', 4: '四化会' };
|
|
879
|
+
for (const t of groups.tripleHua) labels.push(`${HUA_NUM[t.types.length] || `${t.types.length}化会`}${PALACE_SUFFIX(t.palace)}`);
|
|
880
|
+
for (const t of groups.selfHua) labels.push(`${PALACE_SUFFIX(t.palace)}自化`);
|
|
881
|
+
|
|
882
|
+
const byType = {};
|
|
883
|
+
for (const type of FLY_TYPES) {
|
|
884
|
+
byType[type] = sources
|
|
885
|
+
.map((s) => {
|
|
886
|
+
const f = s.flies.find((x) => x.type === type);
|
|
887
|
+
return f && f.to ? { from: s.palace, star: f.star, to: f.to, self: f.self } : null;
|
|
888
|
+
})
|
|
889
|
+
.filter(Boolean);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return {
|
|
893
|
+
from: src.palace,
|
|
894
|
+
sanfang: sources.map((s) => s.palace),
|
|
895
|
+
sources,
|
|
896
|
+
targets,
|
|
897
|
+
groups,
|
|
898
|
+
byType,
|
|
899
|
+
labels,
|
|
900
|
+
note: '三方四正取本宫、对宫与两个三合宫共四宫,四宫宫干各化禄权科忌共 16 条飞化,按落宫归堆;只在落宫相同(会照)时标会聚,单条飞出不另立标签。只描会照与方向,不折吉凶,也未叠大限流年四化。',
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
|
|
798
904
|
// ── 流年四化落宫 ────────────────────────────────────────────
|
|
799
905
|
|
|
800
906
|
export function enrichLiunian(chart) {
|
package/locale/zh.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
3
|
"title": "命理排盘(玄学)· 八字紫微六爻梅花六壬奇门合盘塔罗",
|
|
4
|
-
"description": "玄学命理排盘:十九套体系一站排盘——既有的八套排盘(八字、紫微、六爻、梅花、大六壬、奇门、合盘、塔罗)之外,另有十一套速查(黄历、农历互转、择日、称骨、小六壬、星座、生命数字、人生K线、风水、起名、十六型人格):八字(藏干十神、十二长生、42 神煞、旺衰、格局用神、大运流年吉凶评分)、紫微斗数(49 星曜与主星庙旺、四层十二神、34 格局、大限、流年流月流日流时四化)、六爻纳甲、梅花易数、大六壬(天地盘/四课/三传)、奇门遁甲(拆补/超神接气/置闰三派取局)、合盘(八字与紫微两套)与塔罗;另有所问之事驱动的解析与详解。纯本地计算、默认不联网,作为 Agent 工具供对话调用,并提供可切换本命/大限/流年视图的 Web
|
|
4
|
+
"description": "玄学命理排盘:十九套体系一站排盘——既有的八套排盘(八字、紫微、六爻、梅花、大六壬、奇门、合盘、塔罗)之外,另有十一套速查(黄历、农历互转、择日、称骨、小六壬、星座、生命数字、人生K线、风水、起名、十六型人格):八字(藏干十神、十二长生、42 神煞、旺衰、格局用神、大运流年吉凶评分)、紫微斗数(49 星曜与主星庙旺、四层十二神、34 格局、大限、流年流月流日流时四化)、六爻纳甲、梅花易数、大六壬(天地盘/四课/三传)、奇门遁甲(拆补/超神接气/置闰三派取局)、合盘(八字与紫微两套)与塔罗;另有所问之事驱动的解析与详解。纯本地计算、默认不联网,作为 Agent 工具供对话调用,并提供可切换本命/大限/流年视图的 Web 面板。紫微含飞星串连与三方四正复合飞化,六爻含用神旺衰与全卦逐爻旺衰。"
|
|
5
5
|
}
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-metaphysics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.38.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "命理排盘(玄学 xuanxue)for DeepSeek Harness: nineteen systems and eleven quick references (almanac, solar–lunar conversion, …), with climate adjustment (tiaohou), the 120 Qiongtong Baojian entries, 391-char name library, classical quotes (Ziping Zhenquan / Di Tian Sui), hexagram body relations (六冲/六合/伏吟/反吟/化进神/化退神) plus yongshen placement (用神落位) with month/day strength (月建日辰旺衰) for liuyao, plus an MBTI-style 16-type questionnaire and exact dayun handover dates (交运日), palace conditions (击刑/入墓), month states (旺相休囚死) and stem–palace relations (天盘干与宫生克) for qimen, flying four-transformations (四化飞星串连) for ziwei, and a bundled offline single-file page (命理排盘.html).",
|
|
5
|
+
"description": "命理排盘(玄学 xuanxue)for DeepSeek Harness: nineteen systems and eleven quick references (almanac, solar–lunar conversion, …), with climate adjustment (tiaohou), the 120 Qiongtong Baojian entries, 391-char name library, classical quotes (Ziping Zhenquan / Di Tian Sui / San Ming Tong Hui), hexagram body relations (六冲/六合/伏吟/反吟/化进神/化退神) plus yongshen placement (用神落位) with month/day strength (月建日辰旺衰) and whole-hexagram per-line strength (全卦逐爻旺衰) for liuyao, plus an MBTI-style 16-type questionnaire and exact dayun handover dates (交运日) with annual suiyun hints (岁运并临/伏吟反吟), palace conditions (击刑/入墓), month states (旺相休囚死) and stem–palace relations (天盘干与宫生克) for qimen, flying four-transformations with chained flights (四化飞星串连) and three-way-four-corner composite flights (三方四正复合飞化) for ziwei, and a bundled offline single-file page (命理排盘.html), and a panel-to-chat handoff that asks the Harness about a finished chart.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"玄学",
|
|
8
8
|
"玄学排盘",
|
|
@@ -60,6 +60,18 @@
|
|
|
60
60
|
"node": ">=18",
|
|
61
61
|
"dsh": ">=0.2.0"
|
|
62
62
|
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "node tools/build-client.mjs",
|
|
65
|
+
"build:html": "node tools/build-html.mjs",
|
|
66
|
+
"build:desktop": "node tools/build-html.mjs --desktop",
|
|
67
|
+
"test": "node tools/test-all.mjs",
|
|
68
|
+
"test:ci": "node tools/build-client.mjs && node tools/check-bundle.mjs && node tools/test-all.mjs && node tools/check-assertions.mjs && node tools/verify-tests-can-fail.mjs && node tools/check-html-sinks.mjs && node tools/check-patterns.mjs",
|
|
69
|
+
"test:baseline": "node tools/check-assertions.mjs --update",
|
|
70
|
+
"check:html": "node tools/check-html-sinks.mjs",
|
|
71
|
+
"check:bundle": "node tools/check-bundle.mjs",
|
|
72
|
+
"check:patterns": "node tools/check-patterns.mjs",
|
|
73
|
+
"release": "node tools/release.mjs"
|
|
74
|
+
},
|
|
63
75
|
"exports": {
|
|
64
76
|
".": "./index.js",
|
|
65
77
|
"./client": "./client.js",
|
|
@@ -78,6 +90,7 @@
|
|
|
78
90
|
"icon.svg",
|
|
79
91
|
"README.md",
|
|
80
92
|
"CHANGELOG.md",
|
|
93
|
+
"docs/assets",
|
|
81
94
|
"LICENSE"
|
|
82
95
|
],
|
|
83
96
|
"dsh": {
|
|
@@ -89,16 +102,5 @@
|
|
|
89
102
|
"immediately": true,
|
|
90
103
|
"inject": []
|
|
91
104
|
}
|
|
92
|
-
},
|
|
93
|
-
"scripts": {
|
|
94
|
-
"build": "node tools/build-client.mjs",
|
|
95
|
-
"build:html": "node tools/build-html.mjs",
|
|
96
|
-
"test": "node tools/test-all.mjs",
|
|
97
|
-
"test:ci": "node tools/build-client.mjs && node tools/check-bundle.mjs && node tools/test-all.mjs && node tools/check-assertions.mjs && node tools/verify-tests-can-fail.mjs && node tools/check-html-sinks.mjs && node tools/check-patterns.mjs",
|
|
98
|
-
"test:baseline": "node tools/check-assertions.mjs --update",
|
|
99
|
-
"check:html": "node tools/check-html-sinks.mjs",
|
|
100
|
-
"check:bundle": "node tools/check-bundle.mjs",
|
|
101
|
-
"check:patterns": "node tools/check-patterns.mjs",
|
|
102
|
-
"release": "node tools/release.mjs"
|
|
103
105
|
}
|
|
104
|
-
}
|
|
106
|
+
}
|