dsh-metaphysics 0.18.0 → 0.18.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 +23 -1
- package/README.md +5 -5
- package/client.js +172 -4
- package/engine/geo.js +1 -1
- package/index.js +2 -2
- package/locale/en.json +2 -2
- package/locale/zh.json +2 -2
- package/package.json +8 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
版本按「一组可感知的改动」发,README 与市场条目描述随能力同步。
|
|
4
4
|
|
|
5
|
-
## 0.18.
|
|
5
|
+
## 0.18.2(已发布)
|
|
6
|
+
|
|
7
|
+
人生 K 线从「等宽文本 + ASCII」升级成真正的蜡烛图,并嵌进八字结果:
|
|
8
|
+
|
|
9
|
+
- 新增 `PP.trendChart` / `PP.trendHTML`:实体=该岁相对上一岁的涨跌、影线=±4 分;叠 5 年 / 10 年均线、
|
|
10
|
+
大运交替底色与分界虚线(段名标顶部)、0–100 固定量程网格、年龄刻度、最高/最低岁标记;悬停看逐年
|
|
11
|
+
「多少岁 / 哪一年 / 什么干支 / 多少分 / 落在哪步大运」。颜色全走 CSS 变量,深浅色与打印跟随
|
|
12
|
+
- 「人生K线」tab 不再输出纯文本摘要,直接给图 + 大运分段 chips + 高低年份;数据不足或空值时安全退回文本
|
|
13
|
+
- **八字结果底部直接嵌同一张 K 线**(面板与独立页在排八字时顺带算一次 `trend`),与原有的
|
|
14
|
+
「人生运势曲线」(大运阶梯 + 流年折线)并存:曲线看趋势形态,K 线看逐年涨跌
|
|
15
|
+
- 新增 `test/kline.test.mjs`(23 条):结构、坐标不越界、无 NaN、空/单点安全、旺衰边界不出高低结论、
|
|
16
|
+
两处嵌入点都在源码里
|
|
17
|
+
- 统计:58 个测试文件 / 1644 条断言
|
|
18
|
+
|
|
19
|
+
## 0.18.1(已发布)
|
|
20
|
+
|
|
21
|
+
元数据与检索入口同步,**无运行时行为变化**:
|
|
22
|
+
|
|
23
|
+
- 把「玄学 / 算命 / 占卜 / 运势」加进 `package.json` 关键词与描述、`locale/*.json`、市场条目描述、README 与工具描述——之前只写「命理排盘」,用户搜「玄学」搜不到;现在搜「玄学」应能命中
|
|
24
|
+
- 工具描述补一条触发条件:用户只搜「玄学」或问「有什么玄学工具」时也应介绍本插件
|
|
25
|
+
- 排盘逻辑、输出与测试断言不变;仅 UA 随版本号更新(`dsh-metaphysics/0.18.1`)
|
|
26
|
+
|
|
27
|
+
## 0.18.0(已发布)
|
|
6
28
|
|
|
7
29
|
吸收同生态另一款命理插件「玄机阁」(dsh-xuanji,MIT)的能力:**按行为规格独立实现,不 vendor 源码、
|
|
8
30
|
不引入 iztro / lunar-javascript 依赖**,引擎仍为零外部依赖的纯 ESM。
|
package/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
# dsh-metaphysics · 命理排盘
|
|
2
2
|
|
|
3
|
-
Chinese metaphysics for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): BaZi (Four Pillars), Zi Wei Dou Shu, LiuYao, MeiHua YiShu, Da Liu Ren, Qi Men Dun Jia, relationship compatibility, Tarot, plus quick-reference tools — almanac, date selection, bone-weight fortune, Xiao Liu Ren, horoscope, numerology, life-curve, feng shui and name analysis.
|
|
3
|
+
Chinese metaphysics (玄学 / xuanxue) for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness): BaZi (Four Pillars), Zi Wei Dou Shu, LiuYao, MeiHua YiShu, Da Liu Ren, Qi Men Dun Jia, relationship compatibility, Tarot, plus quick-reference tools — almanac, date selection, bone-weight fortune, Xiao Liu Ren, horoscope, numerology, life-curve, feng shui and name analysis.
|
|
4
4
|
|
|
5
|
-
给 DeepSeek Harness
|
|
5
|
+
给 DeepSeek Harness 用的**玄学命理**插件:**四柱八字、紫微斗数、六爻纳甲、梅花易数、大六壬、奇门遁甲、合盘、塔罗牌**八大排盘体系,外加**黄历、择日、称骨、小六壬、星座、生命数字、人生K线、风水、起名**九套速查,同时提供 Agent 工具与 Web 面板。
|
|
6
6
|
|
|
7
7
|
> 传统命理与占卜属文化娱乐用途,不构成医疗、投资、法律或生死判断的依据。
|
|
8
8
|
|
|
9
9
|
## 插件市场备注
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**命理排盘(玄学)· 八字 / 紫微 / 六爻 / 梅花 / 六壬 / 奇门 / 合盘 / 塔罗 + 黄历 / 择日 / 称骨 / 小六壬 / 星座 / 生命数字 / 人生K线 / 风水 / 起名** —— 一个插件把十七套体系装进 Harness:对话里说一句就排盘,侧栏还有可视化面板。
|
|
12
12
|
|
|
13
13
|
- **八字**:42 颗神煞(分吉凶七类,天干星双查年干与日干、三合星双查年支与日支,悬停看查法)、日主旺衰量化并给出依据、格局与用神(月令取格 + 化气/专旺/从格 + 十神组合,每条附判定依据)、大运流年按喜忌五行与十神打分(大吉/吉/平/忌/大忌,可看逐项理由)
|
|
14
14
|
- **紫微**:十四主星与 49 星曜(主星带**庙旺得利平不陷**亮度标注)、四层十二神、生年四化与宫干自化、34 条格局(标吉/忌倾向与依据)、大限一览、流年四化落宫;本命/大限/流年三视图一键切换,命宫红框、三方四正浅底标出;竖屏与窄侧栏保持 4×4 宫盘(宫位相对位置不丢)
|
|
@@ -91,7 +91,7 @@ Chinese metaphysics for [DeepSeek Harness](https://github.com/deepseek-ai/deepse
|
|
|
91
91
|
- **小六壬 `xiaoliuren`**:时间起课(农历月/日/时三掐)与报数起课(三个 1–99),六宫吉凶与白话断语;缺时辰会明确要求补,不默认某个时辰
|
|
92
92
|
- **星座 `star`**:太阳星座档案(四象、守护星、关键词、契合星座)+ 当日四维基调;基调由日期哈希确定性生成,明写「不是随机数」,纯娱乐向
|
|
93
93
|
- **生命数字 `numerology`**:生命路径数 / 生日数 / 态度数,11/22/33 主数保留;与八字口径不同,混问时会说明两套不可互相印证
|
|
94
|
-
- **人生 K 线 `trend`**:复用八字的旺衰、大运与流年十神,按固定计分表给出 1–100
|
|
94
|
+
- **人生 K 线 `trend`**:复用八字的旺衰、大运与流年十神,按固定计分表给出 1–100 岁逐年分与最佳/最差年份;面板与独立页画的是**蜡烛图**(实体=相对上一岁的涨跌、影线=±4 分,叠 5/10 年均线、大运分界与最高/最低岁标记),并直接嵌在八字结果底部,与「人生运势曲线」(大运阶梯 + 流年折线)互补:曲线看趋势,K 线看逐年涨跌。旺衰正好落在换档阈值(±0.3)时只提示、不给顺位结论
|
|
95
95
|
- **风水 `fengshui`**:八宅命卦(1900s/2000s 男女公式、立春界)、大游年四吉四凶、流年九宫飞白、24 山门主灶布局倾向、命宅配调停文案;`scope` 明写**不含**玄空各运盘与现场勘舆
|
|
96
96
|
- **起名 `name`**:评估现有名字或按喜用五行生成候选名;241 字自建字库,未收录的字如实标「未收录」;**不做五格剖象**(需康熙字典笔画)与音韵判断
|
|
97
97
|
|
|
@@ -107,7 +107,7 @@ Chinese metaphysics for [DeepSeek Harness](https://github.com/deepseek-ai/deepse
|
|
|
107
107
|
- **追问**:工具参数 `ask`、面板与独立页的追问输入框——围绕**已算好的盘**回答「2027 年事业怎么样」「财运如何」这类问题;只取盘面已有字段(流年/大运/宫位/分节),不重排、不猜测;年份超出已排范围或没识别到方面时,明确说找不到并给出可问范围
|
|
108
108
|
- **八字 × 紫微 交叉验证**:工具参数 `cross`(或面板勾选)会用同一份出生信息再排另一套盘,对事业/财富/感情/身体/节奏五项并列对照,标注「同向 / 有张力 / 互补」;只作对照,不把两套体系折算成同一个分数
|
|
109
109
|
- **量化口径**:只量化引擎已有数据(十神权重、大运/流年档位、宫位与四化计数),**不换算金额、不给健康诊断**;报告里有「量化口径」分节写明这条边界
|
|
110
|
-
- **方法与验证**:独立页内置同页「方法与验证」(体系、128 条卦例对拍、
|
|
110
|
+
- **方法与验证**:独立页内置同页「方法与验证」(体系、128 条卦例对拍、58 个测试文件/1644 条断言、七道闸、口径与已知边界),离线可开
|
|
111
111
|
- **夏令时校正(0.18 新增)**:1986–1991 年中国夏令时期间的钟面时间在排盘前自动减 1 小时(跨日回退),八字/紫微/合盘/验前事/生时校正统一生效;出生证已是真实太阳口径时可用 `dst: false` 关闭
|
|
112
112
|
- **合婚明细层(0.18 新增)**:合盘新增属相六合/三合/六冲/相害/相刑、天干五合、双向十神、跨盘地支、年命纳音与吉凶象计数分档;只作明细,不改原总分
|
|
113
113
|
- **晚子时开关**:面板与独立页都能切「23:00 后算次日/当日」;奇门另可切「归当日/归次日」——这是排盘口径,不是结果重算
|
package/client.js
CHANGED
|
@@ -746,7 +746,7 @@ function resolveAddress(input) {
|
|
|
746
746
|
|
|
747
747
|
const DETAIL = /(区|县|镇|乡|村|小区|街道|路|号|巷|弄|组|队)/;
|
|
748
748
|
|
|
749
|
-
const USER_AGENT = 'dsh-metaphysics/0.18.
|
|
749
|
+
const USER_AGENT = 'dsh-metaphysics/0.18.2 (+https://github.com/xuanfu-web/dsh-metaphysics)';
|
|
750
750
|
|
|
751
751
|
async function onlineLookup(text, { timeoutMs = 2500 } = {}) {
|
|
752
752
|
if (typeof fetch !== 'function') return null;
|
|
@@ -9656,6 +9656,46 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
9656
9656
|
.mp-curve .cv-legend i{display:inline-block;width:14px;height:2px;vertical-align:3px;margin-right:4px}
|
|
9657
9657
|
.mp-curve .cv-tip{font-size:11px;color:var(--muted);line-height:1.6;margin-top:4px}
|
|
9658
9658
|
@media (max-width:520px){.mp-curve .cv-lbl.age{font-size:9px}}
|
|
9659
|
+
.mp-kline{margin-top:10px;border:1px solid var(--line);border-radius:8px;background:var(--card);padding:10px 12px 9px}
|
|
9660
|
+
.mp-kline-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;font-size:12px;color:var(--label);font-family:system-ui,sans-serif;margin-bottom:2px}
|
|
9661
|
+
.mp-kline-h b{font-size:12.5px;color:var(--ink);font-weight:600}
|
|
9662
|
+
.mp-kline-h span{font-size:11.5px;color:var(--muted)}
|
|
9663
|
+
.mp-kline-fig svg{display:block;width:100%;height:auto;overflow:visible}
|
|
9664
|
+
.mp-kline .kl-band{fill:var(--ink);opacity:.045}
|
|
9665
|
+
.mp-kline .kl-grid{stroke:var(--line);stroke-width:.5;stroke-dasharray:1 4;opacity:.7}
|
|
9666
|
+
.mp-kline .kl-grid.mid{stroke-width:.8;stroke-dasharray:3 3;opacity:.9}
|
|
9667
|
+
.mp-kline .kl-segline{stroke:var(--dimline);stroke-width:.6;stroke-dasharray:2 3;opacity:.8}
|
|
9668
|
+
.mp-kline .kl-seg{fill:var(--label);font-size:8.5px;font-family:system-ui,sans-serif;paint-order:stroke;stroke:var(--card);stroke-width:2.2px;stroke-linejoin:round}
|
|
9669
|
+
.mp-kline .kl-lbl{fill:var(--muted);font-size:8px;font-family:system-ui,sans-serif}
|
|
9670
|
+
.mp-kline .kl-lbl.age{font-size:8.5px}
|
|
9671
|
+
.mp-kline .kl-c.up line{stroke:var(--ji);stroke-width:.8;opacity:.8}
|
|
9672
|
+
.mp-kline .kl-c.up rect{fill:var(--ji);opacity:.92}
|
|
9673
|
+
.mp-kline .kl-c.down line{stroke:var(--lu);stroke-width:.8;opacity:.8}
|
|
9674
|
+
.mp-kline .kl-c.down rect{fill:var(--lu);opacity:.92}
|
|
9675
|
+
.mp-kline .kl-c:hover rect{opacity:1}
|
|
9676
|
+
.mp-kline .kl-ma{fill:none;stroke-linejoin:round;stroke-linecap:round}
|
|
9677
|
+
.mp-kline .kl-ma.m5{stroke:var(--quan);stroke-width:1.3}
|
|
9678
|
+
.mp-kline .kl-ma.m10{stroke:var(--ke);stroke-width:1;opacity:.85}
|
|
9679
|
+
.mp-kline .kl-mark circle{fill:var(--quan)}
|
|
9680
|
+
.mp-kline .kl-mark.lo circle{fill:var(--ke)}
|
|
9681
|
+
.mp-kline .kl-mark .ring{fill:none;stroke:currentColor;stroke-width:.6;opacity:.5}
|
|
9682
|
+
.mp-kline .kl-mark text{fill:var(--ink2);font-size:9px;font-family:system-ui,sans-serif;paint-order:stroke;stroke:var(--card);stroke-width:2.4px;stroke-linejoin:round}
|
|
9683
|
+
.mp-kline .kl-legend{display:flex;gap:12px;flex-wrap:wrap;margin-top:6px;font-size:11px;color:var(--muted);font-family:system-ui,sans-serif}
|
|
9684
|
+
.mp-kline .kl-legend i{display:inline-block;width:9px;height:9px;vertical-align:-1px;margin-right:4px;border-radius:1px}
|
|
9685
|
+
.mp-kline .kl-legend i.up{background:var(--ji)}
|
|
9686
|
+
.mp-kline .kl-legend i.down{background:var(--lu)}
|
|
9687
|
+
.mp-kline .kl-legend i.m5{height:2px;background:var(--quan);vertical-align:3px}
|
|
9688
|
+
.mp-kline .kl-legend i.m10{height:2px;background:var(--ke);vertical-align:3px}
|
|
9689
|
+
.kl-segs{display:flex;flex-wrap:wrap;gap:4px 6px;margin-top:8px;font-family:system-ui,sans-serif}
|
|
9690
|
+
.kl-chip{font-size:11px;color:var(--ink2);border:1px solid var(--hair);border-radius:99px;padding:1px 8px;background:var(--band)}
|
|
9691
|
+
.kl-chip em{font-style:normal;color:var(--muted);margin-left:5px;font-size:10.5px}
|
|
9692
|
+
.kl-hls{display:flex;flex-direction:column;gap:3px;margin-top:8px;font-size:11.5px;font-family:system-ui,sans-serif;color:var(--ink2)}
|
|
9693
|
+
.kl-hl{border-left:2px solid var(--line);padding-left:7px;line-height:1.6}
|
|
9694
|
+
.kl-hl.hi{border-color:var(--quan)}
|
|
9695
|
+
.kl-hl.lo{border-color:var(--ke)}
|
|
9696
|
+
.mp-kline-note{font-size:11px;color:var(--red);line-height:1.6;margin-top:6px}
|
|
9697
|
+
.mp-kline-tip{font-size:11px;color:var(--muted);line-height:1.6;margin-top:5px}
|
|
9698
|
+
@media print{.mp-kline{break-inside:avoid}}
|
|
9659
9699
|
.mp-tt{padding:16px}
|
|
9660
9700
|
.mp-tt-head{font-size:12.5px;color:var(--muted);margin-bottom:12px;letter-spacing:.04em}
|
|
9661
9701
|
.mp-tt-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(172px,1fr));gap:10px}
|
|
@@ -10665,6 +10705,120 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10665
10705
|
</div>`;
|
|
10666
10706
|
};
|
|
10667
10707
|
|
|
10708
|
+
pp.trendChart = function (r) {
|
|
10709
|
+
const pts = r && Array.isArray(r.points) ? r.points : [];
|
|
10710
|
+
if (pts.length < 2) return '';
|
|
10711
|
+
const segs = r && Array.isArray(r.segments) ? r.segments : [];
|
|
10712
|
+
const num = (v) => (typeof v === 'number' && isFinite(v) ? v : 0);
|
|
10713
|
+
const W = 720, H = 300;
|
|
10714
|
+
const M = { t: 36, r: 14, b: 30, l: 34 };
|
|
10715
|
+
const pw = W - M.l - M.r, ph = H - M.t - M.b;
|
|
10716
|
+
const n = pts.length;
|
|
10717
|
+
const step = pw / n;
|
|
10718
|
+
const X = (i) => M.l + (i + 0.5) * step;
|
|
10719
|
+
const Y = (v) => M.t + ph - (Math.max(0, Math.min(100, v)) / 100) * ph;
|
|
10720
|
+
const bodyW = Math.max(1.1, Math.min(10, step * 0.62));
|
|
10721
|
+
const sc = (p) => num(p.score);
|
|
10722
|
+
|
|
10723
|
+
const bands = segs.map((s, i) => {
|
|
10724
|
+
const i0 = Math.max(0, s.startAge - 1);
|
|
10725
|
+
const i1 = Math.min(n - 1, s.endAge - 1);
|
|
10726
|
+
if (i1 < i0) return '';
|
|
10727
|
+
const x = M.l + i0 * step;
|
|
10728
|
+
const w = Math.max(0.6, (i1 - i0 + 1) * step);
|
|
10729
|
+
const rect = i % 2 === 1
|
|
10730
|
+
? `<rect class="kl-band" x="${x.toFixed(1)}" y="${M.t}" width="${w.toFixed(1)}" height="${ph}"/>` : '';
|
|
10731
|
+
const line = i === 0 ? ''
|
|
10732
|
+
: `<line class="kl-segline" x1="${x.toFixed(1)}" y1="${M.t}" x2="${x.toFixed(1)}" y2="${M.t + ph}"/>`;
|
|
10733
|
+
return rect + line + `<text class="kl-seg" x="${(x + 3).toFixed(1)}" y="${M.t - 8}">${esc(s.ganZhi)}</text>`;
|
|
10734
|
+
}).join('');
|
|
10735
|
+
|
|
10736
|
+
const grid = [0, 25, 50, 75, 100].map((v) =>
|
|
10737
|
+
`<line class="kl-grid${v === 50 ? ' mid' : ''}" x1="${M.l}" y1="${Y(v).toFixed(1)}" x2="${M.l + pw}" y2="${Y(v).toFixed(1)}"/>`
|
|
10738
|
+
+ `<text class="kl-lbl" x="${M.l - 6}" y="${(Y(v) + 3).toFixed(1)}" text-anchor="end">${v}</text>`).join('');
|
|
10739
|
+
|
|
10740
|
+
const candles = pts.map((p, i) => {
|
|
10741
|
+
const k = p.kline || {};
|
|
10742
|
+
const o = num(k.open), c = num(k.close), hi = num(k.high), lo = num(k.low);
|
|
10743
|
+
const up = c >= o;
|
|
10744
|
+
const yO = Y(o), yC = Y(c);
|
|
10745
|
+
const top = Math.min(yO, yC);
|
|
10746
|
+
const h = Math.max(0.8, Math.abs(yO - yC));
|
|
10747
|
+
const x = X(i);
|
|
10748
|
+
const title = `${p.age}岁(${p.year}年 ${p.ganZhi})${c}分${p.dayunGanZhi ? ` · ${p.dayunGanZhi}运` : ''}`;
|
|
10749
|
+
return `<g class="kl-c${up ? ' up' : ' down'}"><title>${esc(title)}</title>`
|
|
10750
|
+
+ `<line x1="${x.toFixed(2)}" y1="${Y(hi).toFixed(1)}" x2="${x.toFixed(2)}" y2="${Y(lo).toFixed(1)}"/>`
|
|
10751
|
+
+ `<rect x="${(x - bodyW / 2).toFixed(2)}" y="${top.toFixed(1)}" width="${bodyW.toFixed(2)}" height="${h.toFixed(1)}" rx="0.7"/></g>`;
|
|
10752
|
+
}).join('');
|
|
10753
|
+
|
|
10754
|
+
const maPath = (win) => {
|
|
10755
|
+
const seg = [];
|
|
10756
|
+
for (let i = 0; i < n; i++) {
|
|
10757
|
+
if (i + 1 < win) continue;
|
|
10758
|
+
let sum = 0;
|
|
10759
|
+
for (let j = i + 1 - win; j <= i; j++) sum += sc(pts[j]);
|
|
10760
|
+
seg.push(`${seg.length ? 'L' : 'M'}${X(i).toFixed(1)} ${Y(sum / win).toFixed(1)}`);
|
|
10761
|
+
}
|
|
10762
|
+
return seg.join(' ');
|
|
10763
|
+
};
|
|
10764
|
+
|
|
10765
|
+
let hiP = pts[0], loP = pts[0];
|
|
10766
|
+
for (const p of pts) {
|
|
10767
|
+
if (sc(p) > sc(hiP)) hiP = p;
|
|
10768
|
+
if (sc(p) < sc(loP)) loP = p;
|
|
10769
|
+
}
|
|
10770
|
+
const mark = (p, cls, dy) => {
|
|
10771
|
+
const i = pts.indexOf(p);
|
|
10772
|
+
const x = X(i), y = Y(sc(p));
|
|
10773
|
+
const tx = Math.min(Math.max(x, M.l + 26), M.l + pw - 26);
|
|
10774
|
+
const d = cls === 'hi' ? (y - 8 < M.t + 6 ? 14 : dy) : (y + 12 > M.t + ph - 2 ? -8 : dy);
|
|
10775
|
+
return `<g class="kl-mark ${cls}"><circle cx="${x.toFixed(1)}" cy="${y.toFixed(1)}" r="2"/>`
|
|
10776
|
+
+ `<circle class="ring" cx="${x.toFixed(1)}" cy="${y.toFixed(1)}" r="4.6"/>`
|
|
10777
|
+
+ `<text x="${tx.toFixed(1)}" y="${(y + d).toFixed(1)}" text-anchor="middle">${p.age}岁 ${sc(p)}</text></g>`;
|
|
10778
|
+
};
|
|
10779
|
+
|
|
10780
|
+
const tickStep = n > 60 ? 10 : 5;
|
|
10781
|
+
const ages = pts.filter((p) => p.age % tickStep === 0).map((p) =>
|
|
10782
|
+
`<text class="kl-lbl age" x="${X(pts.indexOf(p)).toFixed(1)}" y="${M.t + ph + 14}" text-anchor="middle">${p.age}</text>`).join('');
|
|
10783
|
+
const xNote = `<text class="kl-lbl" x="${M.l + pw / 2}" y="${H - 4}" text-anchor="middle">年龄(岁)</text>`;
|
|
10784
|
+
|
|
10785
|
+
const legend = `<div class="kl-legend"><span><i class="up"></i>阳线:比上一岁高</span>`
|
|
10786
|
+
+ `<span><i class="down"></i>阴线:比上一岁低</span>`
|
|
10787
|
+
+ `<span><i class="m5"></i>5 年均线</span><span><i class="m10"></i>10 年均线</span>`
|
|
10788
|
+
+ '<span>虚线=大运交界</span></div>';
|
|
10789
|
+
|
|
10790
|
+
return `<div class="mp-kline-fig">
|
|
10791
|
+
<svg viewBox="0 0 ${W} ${H}" role="img" aria-label="人生K线:1 到 ${n} 岁的逐年评分蜡烛图">
|
|
10792
|
+
${bands}${grid}${candles}
|
|
10793
|
+
<path class="kl-ma m10" d="${maPath(10)}"/><path class="kl-ma m5" d="${maPath(5)}"/>
|
|
10794
|
+
${mark(hiP, 'hi', -8)}${mark(loP, 'lo', 12)}
|
|
10795
|
+
${ages}${xNote}
|
|
10796
|
+
</svg>${legend}</div>`;
|
|
10797
|
+
};
|
|
10798
|
+
|
|
10799
|
+
pp.trendHTML = function (r) {
|
|
10800
|
+
if (!r) return '';
|
|
10801
|
+
const chart = pp.trendChart(r);
|
|
10802
|
+
if (!chart) return pp.quickHTML(r);
|
|
10803
|
+
const segs = Array.isArray(r.segments) ? r.segments : [];
|
|
10804
|
+
const hl = (r.highlights && typeof r.highlights === 'object') ? r.highlights : {};
|
|
10805
|
+
const meta = r.meta || {};
|
|
10806
|
+
const st = meta.strength || {};
|
|
10807
|
+
const chips = segs.map((s) => `<span class="kl-chip">${esc(s.ganZhi)}<em>${s.startAge}–${s.endAge}</em></span>`).join('');
|
|
10808
|
+
const best = (Array.isArray(hl.best) ? hl.best : []).map((x) => `<div class="kl-hl hi">${esc(x)}</div>`).join('');
|
|
10809
|
+
const worst = (Array.isArray(hl.worst) ? hl.worst : []).map((x) => `<div class="kl-hl lo">${esc(x)}</div>`).join('');
|
|
10810
|
+
const note = meta.boundaryNote ? `<div class="mp-kline-note">${esc(meta.boundaryNote)}</div>`
|
|
10811
|
+
: (hl.suppressed ? `<div class="mp-kline-note">${esc(hl.suppressed)}</div>` : '');
|
|
10812
|
+
return `<section class="mp-kline" aria-label="人生K线结果">
|
|
10813
|
+
<div class="mp-kline-h"><b>人生 K 线</b><span>${esc(meta.birth || '')} 日主 ${esc(meta.dayMaster || '')} ${esc(st.level || '')}${st.score ? `(${st.score})` : ''}</span></div>
|
|
10814
|
+
${chart}
|
|
10815
|
+
${chips ? `<div class="kl-segs">${chips}</div>` : ''}
|
|
10816
|
+
${best || worst ? `<div class="kl-hls">${best}${worst}</div>` : ''}
|
|
10817
|
+
${note}
|
|
10818
|
+
<div class="mp-kline-tip">逐岁分数由大运与流年十神按固定表确定性计分(1–100),只表五行力量的顺逆,不预测具体事件;旺衰落在换档阈值附近时,不出高低年份结论。</div>
|
|
10819
|
+
</section>`;
|
|
10820
|
+
};
|
|
10821
|
+
|
|
10668
10822
|
pp.baziHTML = function (r) {
|
|
10669
10823
|
const cols = [['year', '年柱'], ['month', '月柱'], ['day', '日柱'], ['hour', '时柱']];
|
|
10670
10824
|
const SHORT = { year: '年', month: '月', day: '日', hour: '时' };
|
|
@@ -11326,6 +11480,19 @@ function App() {
|
|
|
11326
11480
|
}
|
|
11327
11481
|
}
|
|
11328
11482
|
const r = Engine.compute(args);
|
|
11483
|
+
let trend = null;
|
|
11484
|
+
if (k === 'bazi') {
|
|
11485
|
+
try {
|
|
11486
|
+
trend = Engine.compute({
|
|
11487
|
+
system: 'trend', datetime, gender: genderV, toAge: 100,
|
|
11488
|
+
trueSolar, lateZi,
|
|
11489
|
+
...(args.dst !== undefined ? { dst: args.dst } : {}),
|
|
11490
|
+
...(args.address ? { address: args.address } : {}),
|
|
11491
|
+
...(typeof args.longitude === 'number' ? { longitude: args.longitude } : {}),
|
|
11492
|
+
...(args.geo ? { geo: args.geo } : {}),
|
|
11493
|
+
});
|
|
11494
|
+
} catch (e) { trend = null; }
|
|
11495
|
+
}
|
|
11329
11496
|
const ask = (needAsk(k) || k === 'qimen')
|
|
11330
11497
|
? { question: needAsk(k) ? question.trim() : '', direction }
|
|
11331
11498
|
: undefined;
|
|
@@ -11334,7 +11501,7 @@ function App() {
|
|
|
11334
11501
|
it.sections = [...(it.sections || []), { key: 'crossSystem', label: '八字 × 紫微 交叉验证', text: Engine.crossText(r.cross) }];
|
|
11335
11502
|
}
|
|
11336
11503
|
const timed = kindOf(k) === 'cast' && (k !== 'meihua' || mh === 'time');
|
|
11337
|
-
setResult({ kind: k, r, it, at: dt, timed });
|
|
11504
|
+
setResult({ kind: k, r, it, at: dt, timed, trend });
|
|
11338
11505
|
setFx(null); setFit(null); setPastMarks({}); setRectRes(null);
|
|
11339
11506
|
setError(''); setCopied('');
|
|
11340
11507
|
if (k !== 'tarot') {
|
|
@@ -11761,14 +11928,15 @@ function App() {
|
|
|
11761
11928
|
dangerouslySetInnerHTML: {
|
|
11762
11929
|
__html: castAtHTML(result) + PP.resultWithInterpret(
|
|
11763
11930
|
result.kind === 'ziwei' ? PP.ziweiHTML(result.r)
|
|
11764
|
-
: result.kind === 'bazi' ? PP.baziHTML(result.r)
|
|
11931
|
+
: result.kind === 'bazi' ? (PP.baziHTML(result.r) + (result.trend ? PP.trendHTML(result.trend) : ''))
|
|
11765
11932
|
: result.kind === 'meihua' ? PP.meihuaHTML(result.r)
|
|
11766
11933
|
: result.kind === 'daliuren' ? PP.daliurenHTML(result.r)
|
|
11767
11934
|
: result.kind === 'qimen' ? (PP.qimenHTML(result.r) + PP.qimenFactsHTML(result.r))
|
|
11768
11935
|
: result.kind === 'hepan' ? (result.r.chart === 'ziwei' ? PP.ziweiHepanHTML(result.r) : PP.hepanHTML(result.r))
|
|
11769
11936
|
: result.kind === 'tarot' ? PP.tarotHTML(result.r)
|
|
11770
11937
|
: result.kind === 'liuyao' ? PP.liuyaoHTML(result.r)
|
|
11771
|
-
: PP.
|
|
11938
|
+
: result.kind === 'trend' ? PP.trendHTML(result.r)
|
|
11939
|
+
: PP.quickHTML(result.r),
|
|
11772
11940
|
result.it,
|
|
11773
11941
|
{ folded: defaultFolded() },
|
|
11774
11942
|
),
|
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.18.
|
|
146
|
+
const USER_AGENT = 'dsh-metaphysics/0.18.2 (+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/index.js
CHANGED
|
@@ -18,9 +18,9 @@ function printCacheMetrics() {
|
|
|
18
18
|
const TOOL_NAME = 'metaphysics_chart';
|
|
19
19
|
|
|
20
20
|
const DESCRIPTION = [
|
|
21
|
-
'
|
|
21
|
+
'排中国传统命理盘(玄学·命理·占卜,用户说「玄学」「算命」「占卜」时也用本工具)与塔罗:四柱八字(bazi)、紫微斗数(ziwei)、六爻纳甲(liuyao)、梅花易数(meihua)、大六壬(daliuren)、奇门遁甲(qimen)、合盘(hepan)或塔罗抽牌(tarot)。',
|
|
22
22
|
'另有速查类:黄历(almanac)、择日(zeri)、称骨(chenggu)、小六壬(xiaoliuren)、星座(star)、生命数字(numerology)、人生 K 线(trend)、风水(fengshui)、起名(name)。',
|
|
23
|
-
'
|
|
23
|
+
'当用户明确要求“玄学 / 算命 / 占卜 / 排盘 / 算八字 / 看四柱 / 排紫微盘 / 起卦 / 摇一卦 / 抽塔罗 / 看运势 / 合盘 / 看黄历 / 挑日子 / 称骨 / 小六壬”时调用;用户只搜「玄学」或问「有什么玄学工具」时,也应介绍本插件。',
|
|
24
24
|
'bazi 与 ziwei 需要公历出生时间与性别;hepan 需要双方的时间与性别;liuyao 可给定六爻值或随机起卦;meihua 可按时间或数字起卦;tarot 可指定张数与问题。',
|
|
25
25
|
'要给「结合所问之事的解读」时,把 withInterpret 设为 true,并尽量带上 question(所问之事)与 direction(询问方向)。',
|
|
26
26
|
'结果可复现:tarot / liuyao 传 seed,紫微 / 八字 / 塔罗传 asOf;输出摘要会写明晚子时与真太阳时实际采用的口径。',
|
package/locale/en.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
|
-
"title": "Metaphysics Charts",
|
|
4
|
-
"description": "
|
|
3
|
+
"title": "Metaphysics Charts (Xuanxue)",
|
|
4
|
+
"description": "Chinese metaphysics (xuanxue) — seventeen systems in one plugin: eight chart systems plus nine quick references (almanac, date selection, bone-weight fortune, Xiao Liu Ren, horoscope, numerology, life-curve, feng shui, name analysis). Chart systems: BaZi (hidden stems, ten gods, 12 stages, 42 shensha, strength, pattern and useful-god, luck scoring), Zi Wei Dou Shu (49 stars with brightness, four 12-god cycles, 34 patterns, decade and annual/monthly/daily/hourly mutagen), LiuYao, MeiHua YiShu, Da Liu Ren, Qi Men Dun Jia (three ju-selection schools), compatibility charts (BaZi and Zi Wei), and Tarot, plus an ask-driven interpretation layer. Computed locally with networking off by default, exposed as an agent tool with a Web panel."
|
|
5
5
|
}
|
|
6
6
|
}
|
package/locale/zh.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"meta": {
|
|
3
|
-
"title": "
|
|
4
|
-
"description": "
|
|
3
|
+
"title": "命理排盘(玄学)· 八字紫微六爻梅花六壬奇门合盘塔罗",
|
|
4
|
+
"description": "玄学命理排盘:十七套体系一站排盘——既有的八套排盘(八字、紫微、六爻、梅花、大六壬、奇门、合盘、塔罗)之外,新增九套速查(黄历、择日、称骨、小六壬、星座、生命数字、人生K线、风水、起名):八字(藏干十神、十二长生、42 神煞、旺衰、格局用神、大运流年吉凶评分)、紫微斗数(49 星曜与主星庙旺、四层十二神、34 格局、大限、流年流月流日流时四化)、六爻纳甲、梅花易数、大六壬(天地盘/四课/三传)、奇门遁甲(拆补/超神接气/置闰三派取局)、合盘(八字与紫微两套)与塔罗;另有所问之事驱动的解析与详解。纯本地计算、默认不联网,作为 Agent 工具供对话调用,并提供可切换本命/大限/流年视图的 Web 面板。"
|
|
5
5
|
}
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-metaphysics",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.2",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "命理排盘(玄学 xuanxue)for DeepSeek Harness: seventeen systems — eight chart systems (BaZi four pillars, Zi Wei Dou Shu, LiuYao, MeiHua, Da Liu Ren, Qi Men Dun Jia, compatibility charts, Tarot) plus nine quick references (almanac, date selection, bone-weight fortune, Xiao Liu Ren, horoscope, numerology, life-curve, feng shui, name analysis); ask-driven interpretation, report layer with evidence and confidence, DST correction for 1986–1991. All computed locally, networking off by default — as an agent tool plus a Web panel.",
|
|
6
6
|
"keywords": [
|
|
7
|
+
"玄学",
|
|
8
|
+
"玄学排盘",
|
|
9
|
+
"算命",
|
|
10
|
+
"占卜",
|
|
11
|
+
"运势",
|
|
12
|
+
"传统命理",
|
|
7
13
|
"dsh-plugin",
|
|
8
14
|
"dsh-bundle",
|
|
9
15
|
"dsh-market",
|