dsh-metaphysics 0.18.2 → 0.18.4
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 +29 -0
- package/README.md +4 -4
- package/client.js +203 -24
- package/engine/chenggu.js +74 -4
- package/engine/geo.js +1 -1
- package/engine/index.js +8 -4
- package/index.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
版本按「一组可感知的改动」发,README 与市场条目描述随能力同步。
|
|
4
4
|
|
|
5
|
+
## 0.18.4(已发布)
|
|
6
|
+
|
|
7
|
+
称骨补上**称骨歌原文**与白话释义(此前只有自撰的分档批语):
|
|
8
|
+
|
|
9
|
+
- 新增通行本《称骨歌》52 首(二两一钱 … 七两二钱),`CHENGGU_SONG` 按骨重(钱)索引,原文照录;
|
|
10
|
+
各版本有异文,断句标点统一为「,;,。」
|
|
11
|
+
- `buildChenggu` 新增 `song` 字段:`{ text, plain, title, source }`;`plain` 是白话释义(自撰,明确不是原文),
|
|
12
|
+
超出 21–72 钱时给出「未见通行本歌诀」而不是编一首
|
|
13
|
+
- 文本摘要把「歌诀」与「释义」分两段;口径里写明歌诀为通行本、释义为白话自撰
|
|
14
|
+
- 新增 `PP.chengguHTML`:四项骨重表格 + 合计与分档徽标 + 歌诀(两行竖排大字)+ 释义 + 口径;
|
|
15
|
+
面板与独立页的称骨 tab 改用它(原先落到通用文本块)
|
|
16
|
+
- 新增 `test/chenggu.test.mjs`(18 条):52 档齐全且都是四句、关键档位不串行、白话不是原文、
|
|
17
|
+
summary 两段、渲染器四项与口径、两处界面接线
|
|
18
|
+
- 统计:59 个测试文件 / 1668 条断言
|
|
19
|
+
|
|
20
|
+
## 0.18.3(已发布)
|
|
21
|
+
|
|
22
|
+
K 线的第二轮打磨(0.18.2 之后的可读性修正):
|
|
23
|
+
|
|
24
|
+
- 大运段名从图顶挪到图下的条纹带里,不再和「最高/最低岁」标记抢位置;段名居中,条带随大运交替着色
|
|
25
|
+
- 5 年 / 10 年均线在右缘标出末端数值,两条贴太近时自动上下错开
|
|
26
|
+
- 纵轴补 0/25/50/75/100 刻度,横轴补「年龄(岁)」与「每岁一分 · 满分 100」;影线用 `clipPath`
|
|
27
|
+
夹在绘图区内,贴边的影线不再溢出
|
|
28
|
+
- 新增统计条:全段均值、最好大运、最差大运、波动幅度。旺衰落在换档阈值附近时只给均值与波动,不给
|
|
29
|
+
「最好/最差大运」的顺位
|
|
30
|
+
- 图高由 300 提到 322,给刻度与段名条留位
|
|
31
|
+
- `test/kline.test.mjs` 增到 29 条(段名条、均线末端值、纵轴刻度、统计条、最好/最差大运)
|
|
32
|
+
- 统计:58 个测试文件 / 1650 条断言
|
|
33
|
+
|
|
5
34
|
## 0.18.2(已发布)
|
|
6
35
|
|
|
7
36
|
人生 K 线从「等宽文本 + ASCII」升级成真正的蜡烛图,并嵌进八字结果:
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Chinese metaphysics (玄学 / xuanxue) for [DeepSeek Harness](https://github.com
|
|
|
18
18
|
- **奇门遁甲**:时家转盘,拆补 / 超神接气 / 置闰三流派取局;九宫、值符值使、空亡驿马、门迫与宫制门严格区分
|
|
19
19
|
- **合盘**:八字或紫微双盘对照(日主、夫妻宫、五行互补 / 互落宫、四化引动)
|
|
20
20
|
- **塔罗**:78 张全牌、1/3/5 张牌阵,逐牌牌位义 + 整体解读,体系与逆位口径写明
|
|
21
|
-
- **速查九件**:黄历(四柱/建除/宜忌/冲煞/节气)、择日(13
|
|
21
|
+
- **速查九件**:黄历(四柱/建除/宜忌/冲煞/节气)、择日(13 类事项排序,冲属相排除)、称骨(骨重 + 称骨歌原文 + 释义)、
|
|
22
22
|
小六壬(时间/报数起课)、星座(档案 + 当日基调)、生命数字(生命路径/生日/态度数)、人生 K 线(逐年分与形态)、
|
|
23
23
|
风水(八宅命卦/大游年/流年紫白/门主灶)、起名(喜用五行匹配,未收录如实标注)——口径与边界各自写明
|
|
24
24
|
- 全部本地计算,不收集数据;结果供文化娱乐参考,不作医疗、投资、法律或生死判断
|
|
@@ -87,11 +87,11 @@ Chinese metaphysics (玄学 / xuanxue) for [DeepSeek Harness](https://github.com
|
|
|
87
87
|
|
|
88
88
|
- **黄历 `almanac`**:农历、四柱干支(年柱按立春、月柱按节)、建除十二神、宜忌简表、冲煞、财神/喜神方位、上一/下一节气、每日一卦。`scope` 明写未收录的神煞、二十八宿与彭祖百忌
|
|
89
89
|
- **择日 `zeri`**:13 类事项(嫁娶/订婚/开业/入宅/搬家/动土/装修/安葬/出行/祭祀/签约/求医/纳财)× 建除适配逐日打分,分「推荐 / 可用 / 回避」,当事人属相冲煞日直接排除且每条回避带理由;这是**排序引导**,不是吉凶断语
|
|
90
|
-
- **称骨 `chenggu
|
|
90
|
+
- **称骨 `chenggu`**:年/月/日/时四项骨重求和,按总重查**通行本《称骨歌》原文**(二两一钱…七两二钱共 52 首),并给白话释义与分档批语(如 1990-08-15 巳时 = 五两六钱,歌诀「此格推来礼义通…」);骨重表对拍公开黄历页,不采信其他插件的表
|
|
91
91
|
- **小六壬 `xiaoliuren`**:时间起课(农历月/日/时三掐)与报数起课(三个 1–99),六宫吉凶与白话断语;缺时辰会明确要求补,不默认某个时辰
|
|
92
92
|
- **星座 `star`**:太阳星座档案(四象、守护星、关键词、契合星座)+ 当日四维基调;基调由日期哈希确定性生成,明写「不是随机数」,纯娱乐向
|
|
93
93
|
- **生命数字 `numerology`**:生命路径数 / 生日数 / 态度数,11/22/33 主数保留;与八字口径不同,混问时会说明两套不可互相印证
|
|
94
|
-
- **人生 K 线 `trend`**:复用八字的旺衰、大运与流年十神,按固定计分表给出 1–100 岁逐年分与最佳/最差年份;面板与独立页画的是**蜡烛图**(实体=相对上一岁的涨跌、影线=±4 分,叠 5/10
|
|
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 (玄学 / xuanxue) for [DeepSeek Harness](https://github.com
|
|
|
107
107
|
- **追问**:工具参数 `ask`、面板与独立页的追问输入框——围绕**已算好的盘**回答「2027 年事业怎么样」「财运如何」这类问题;只取盘面已有字段(流年/大运/宫位/分节),不重排、不猜测;年份超出已排范围或没识别到方面时,明确说找不到并给出可问范围
|
|
108
108
|
- **八字 × 紫微 交叉验证**:工具参数 `cross`(或面板勾选)会用同一份出生信息再排另一套盘,对事业/财富/感情/身体/节奏五项并列对照,标注「同向 / 有张力 / 互补」;只作对照,不把两套体系折算成同一个分数
|
|
109
109
|
- **量化口径**:只量化引擎已有数据(十神权重、大运/流年档位、宫位与四化计数),**不换算金额、不给健康诊断**;报告里有「量化口径」分节写明这条边界
|
|
110
|
-
- **方法与验证**:独立页内置同页「方法与验证」(体系、128 条卦例对拍、
|
|
110
|
+
- **方法与验证**:独立页内置同页「方法与验证」(体系、128 条卦例对拍、59 个测试文件/1668 条断言、七道闸、口径与已知边界),离线可开
|
|
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.4 (+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;
|
|
@@ -6108,6 +6108,65 @@ function lunarMonthText(month, isLeap = false) {
|
|
|
6108
6108
|
return `${isLeap ? '闰' : ''}${MONTH_TEXT[month - 1] || month}月`;
|
|
6109
6109
|
}
|
|
6110
6110
|
|
|
6111
|
+
const CHENGGU_SONG = {
|
|
6112
|
+
21: { text: '短命非业谓大空,平生灾难事重重;凶祸频临陷逆境,终世困苦事不成。', plain: '起点低、阻力大,凡事难一气呵成;宜守稳借力,不宜孤注一掷。' },
|
|
6113
|
+
22: { text: '身寒骨冷苦伶仃,此命推来行乞人;劳劳碌碌无度日,终年打拱过平生。', plain: '早年资源薄、亲缘淡,靠勤苦与人缘翻身,最忌自弃。' },
|
|
6114
|
+
23: { text: '此命推来骨格轻,求谋作事事难成;妻儿兄弟应难许,别处他乡作散人。', plain: '独自谋事难成,宜合伙或依附平台;离乡发展反有出路。' },
|
|
6115
|
+
24: { text: '此命推来福禄无,门庭困苦总难荣;六亲骨肉皆无靠,流浪他乡作老翁。', plain: '六亲助力少,别指望祖业,早做打算、靠双手积累。' },
|
|
6116
|
+
25: { text: '此命推来祖业微,门庭营度似稀奇;六亲骨肉如冰炭,一世勤劳自把持。', plain: '家底薄、亲缘冷,一生靠自己操持,勤俭则安。' },
|
|
6117
|
+
26: { text: '平生衣禄苦中求,独自营谋事不休;离祖出门宜早计,晚来衣禄自无休。', plain: '白手起家之格:早离乡、晚渐稳,不必怕慢。' },
|
|
6118
|
+
27: { text: '一生作事少商量,难靠祖宗作主张;独马单枪空做去,早年晚岁总无长。', plain: '主意要自己拿,靠人不如靠己;早定方向才不空忙。' },
|
|
6119
|
+
28: { text: '一生行事似飘蓬,祖宗产业在梦中;若不过房改名姓,也当移徒二三通。', plain: '祖业难守,适合外出或改换环境,动中求安。' },
|
|
6120
|
+
29: { text: '初年运限未曾亨,纵有功名在后成;须过四旬才可立,移居改姓始为良。', plain: '功名在后,四十前后才立得住,忌中途频繁换道。' },
|
|
6121
|
+
30: { text: '劳劳碌碌苦中求,东奔西走何日休;若使终身勤与俭,老来稍可免忧愁。', plain: '东奔西走的劳碌格,靠勤俭积攒,晚年才得清闲。' },
|
|
6122
|
+
31: { text: '忙忙碌碌苦中求,何日云开见日头;难得祖基家可立,中年衣食渐无忧。', plain: '先难后易:祖基难得,中年衣食转宽,守住本业即可。' },
|
|
6123
|
+
32: { text: '初年运蹇事难谋,渐有财源如水流;到得中年衣食旺,那时名利一齐收。', plain: '幼年蹇滞,中年后财源渐旺,名利可期。' },
|
|
6124
|
+
33: { text: '早年做事事难成,百年勤劳枉费心;半世自如流水去,后来运到始得金。', plain: '前半程多试错,后半程才见成果,急不得。' },
|
|
6125
|
+
34: { text: '此命福气果如何,僧道门中衣禄多;离祖出家方为妙,朝晚拜佛念弥陀。', plain: '与清静行当、宗教或专门技艺有缘,离祖发展更顺。' },
|
|
6126
|
+
35: { text: '生平福量不周全,祖业根基觉少传;营事生涯宜守旧,时来衣食胜从前。', plain: '福量不齐,宜守旧业、少折腾;时运到了自然宽裕。' },
|
|
6127
|
+
36: { text: '不须劳碌过平生,独自成家福不轻;早有福星常照命,任君行去百般成。', plain: '不必太劳碌,福气随身,行事多能成。' },
|
|
6128
|
+
37: { text: '此命般般事不成,弟兄少力自孤行;虽然祖业须微有,来得明时去不明。', plain: '单打独斗吃力、兄弟少力;宜合作,钱财要明算账。' },
|
|
6129
|
+
38: { text: '一身骨肉最清高,早入簧门姓氏标;待到年将三十六,蓝衫脱去换红袍。', plain: '读书与专业路线见长,三十六前后有转机与体面。' },
|
|
6130
|
+
39: { text: '此命终身运不通,劳劳作事尽皆空;苦心竭力成家计,到得那时在梦中。', plain: '早年空忙,成家立业偏晚;重在坚持,不宜频繁改行。' },
|
|
6131
|
+
40: { text: '平生衣禄是绵长,件件心中自主张;前面风霜多受过,后来必定享安康。', plain: '先苦后甜:衣食渐稳,事在自主,晚景安康。' },
|
|
6132
|
+
41: { text: '此命推来自不同,为人能干异凡庸;中年还有逍遥福,不比前时运来通。', plain: '能干出众,早年只是运会未到;中年有逍遥之福。' },
|
|
6133
|
+
42: { text: '得宽怀处且宽怀,何用双眉皱不开;若使中年命运济,那时名利一起来。', plain: '心宽则顺;中年运济,名利自来,不必过虑。' },
|
|
6134
|
+
43: { text: '为人心性最聪明,作事轩昂近贵人;衣禄一生天注定,不须劳碌是丰亨。', plain: '聪明近贵,易得贵人提携,衣禄有天定之说。' },
|
|
6135
|
+
44: { text: '万事由天莫苦求,须知福碌赖人修;当年财帛难如意,晚景欣然便不优。', plain: '少壮难如意,晚景反安;福禄也靠人修,不必强求。' },
|
|
6136
|
+
45: { text: '名利推求竟若何,前番辛苦后奔波;命中难养男和女,骨肉扶持也不多。', plain: '中年前后仍奔波,子女缘与骨肉助力偏薄,凡事多自扛。' },
|
|
6137
|
+
46: { text: '东西南北尽皆通,出姓移居更觉隆;衣禄无穷无数定,中年晚景一般同。', plain: '外出、迁居更旺;衣禄不愁,中晚年境况相近。' },
|
|
6138
|
+
47: { text: '此命推求旺末年,妻荣子贵自怡然;平生原有滔滔福,可卜财源若水泉。', plain: '晚运佳:妻荣子贵,福厚财源长。' },
|
|
6139
|
+
48: { text: '初年运道未曾通,几许蹉跎命亦穷;兄弟六亲无依靠,一生事业晚来整。', plain: '早年蹉跎、六亲少靠,事业晚成,忌半途而废。' },
|
|
6140
|
+
49: { text: '此命推来福不轻,自成自立显门庭;从来富贵人钦敬,使婢差奴过一生。', plain: '自立门户、显耀门庭,中年后受人敬重。' },
|
|
6141
|
+
50: { text: '为利为名终日劳,中年福禄也多遭;老来自有财星照,不比前番目下高。', plain: '为名利终日奔忙,中年多波折;老来财星照,压力渐轻。' },
|
|
6142
|
+
51: { text: '一世荣华事事通,不须劳碌自亨通;兄弟叔侄皆如意,家业成时福禄宏。', plain: '事多顺遂,兄弟叔侄得力,家业易成。' },
|
|
6143
|
+
52: { text: '一世亨通事事能,不须劳苦自然宁;宗族有光欣喜甚,家产丰盈自称心。', plain: '诸事能干、少劳而宁;宗族有光,家产丰盈。' },
|
|
6144
|
+
53: { text: '此格推来福泽宏,兴家立业在其中;一生衣食安排定,却是人间一福翁。', plain: '兴家立业之格,衣食安稳,是人间有福之人。' },
|
|
6145
|
+
54: { text: '此格详采福泽宏,诗书满腹看功成;丰衣足食多安稳,正是人间有福人。', plain: '读书人格局:功名可期,衣食安稳。' },
|
|
6146
|
+
55: { text: '策马扬鞭争名利,少年作事费筹论;一朝福禄源源至,富贵荣华显六亲。', plain: '少年费筹谋,一朝福至;富贵显亲,属于厚积薄发。' },
|
|
6147
|
+
56: { text: '此格推来礼义通,一身福禄用无穷;甜酸苦辣皆尝过,滚滚财源盈而丰。', plain: '福禄厚:人生百味都经过,之后财源稳而丰。' },
|
|
6148
|
+
57: { text: '福禄丰盈万事全,一身荣耀乐天年;名扬威震人争羡,此世逍遥宛似仙。', plain: '万事较全,名望与荣耀随行,晚运逍遥。' },
|
|
6149
|
+
58: { text: '平生衣食自然来,名利双全富贵偕;金榜题名登甲第,紫袍玉带走金阶。', plain: '衣食自来、名利双全;有科第与体面之象。' },
|
|
6150
|
+
59: { text: '细推此格秀而清,必定才高学业成;甲第之中应有分,扬鞭走马显威荣。', plain: '才高学业成,有科第之份,前程显达。' },
|
|
6151
|
+
60: { text: '一朝金榜快题名,显祖荣宗大器成;衣禄定然无欠缺,田园财帛更丰盈。', plain: '金榜题名、显祖荣宗;衣禄丰足,田园财帛皆旺。' },
|
|
6152
|
+
61: { text: '不作朝中金榜客,定为世上大财翁;聪明天付经书熟,名显高褂自是荣。', plain: '不入仕途也能成富;聪明博学,自有显名之荣。' },
|
|
6153
|
+
62: { text: '此命生来福不穷,读书必定显亲宗;紫衣玉带为卿相,富贵荣华孰与同。', plain: '福泽不穷;读书可显亲,有卿相之象。' },
|
|
6154
|
+
63: { text: '命主为官福禄长,得来富贵实非常;名题雁塔传金榜,大显门庭天下扬。', plain: '仕途顺、福禄长;富贵非常,门庭显扬。' },
|
|
6155
|
+
64: { text: '此格威权不可当,紫袍金带尘高堂;荣华富贵谁能及,万古留名姓氏扬。', plain: '掌权之格:富贵与声名俱隆,留名后世。' },
|
|
6156
|
+
65: { text: '细推此命福非轻,富贵荣华孰与争;定国安邦人极品,威声显赫震寰瀛。', plain: '贵重之命;有定国安邦之器,声威远震。' },
|
|
6157
|
+
66: { text: '此格人间一福人,堆金积玉满堂春;从来富贵有天定,金榜题名更显亲。', plain: '堆金积玉、富贵天定;又有金榜显亲之象。' },
|
|
6158
|
+
67: { text: '此命生来福自宏,田园家业最高隆;平生衣禄盈丰足,一路荣华万事通。', plain: '福厚家隆:田园家业兴旺,衣禄丰足,一路荣华。' },
|
|
6159
|
+
68: { text: '富贵由天莫苦求,万事家计不须谋;十年不比前番事,祖业根基千古留。', plain: '家计不必苦谋;祖业根基可留,运势比前十年更好。' },
|
|
6160
|
+
69: { text: '君是人间福禄星,一生富贵众人钦;总然衣禄由天定,安享荣华过一生。', plain: '人间福禄星:富贵受人钦敬,安享荣华。' },
|
|
6161
|
+
70: { text: '此命推来福不轻,何须愁虑苦劳心;荣华富贵已天定,正笏垂绅拜紫宸。', plain: '不必愁虑劳心;荣华富贵已定,有朝堂之象。' },
|
|
6162
|
+
71: { text: '此命生成大不同,公侯卿相在其中;一生自有逍遥福,富贵荣华极品隆。', plain: '公侯卿相之格:福厚逍遥,富贵极品。' },
|
|
6163
|
+
72: { text: '此命推来天下隆,必定人间一主公;富贵荣华数不尽,定为乾坤一蛟龙。', plain: '极贵之格;但四表上限为七两一钱,此档基本不可达,仅备档。' },
|
|
6164
|
+
};
|
|
6165
|
+
|
|
6166
|
+
function songOf(qian) {
|
|
6167
|
+
return CHENGGU_SONG[qian] || null;
|
|
6168
|
+
}
|
|
6169
|
+
|
|
6111
6170
|
function bandVerdict(qian) {
|
|
6112
6171
|
if (qian >= 55) return { band: '上上', text: '骨重沉实,根基深厚,一生多逢贵人,谋事易成;守正持重,福泽可久。' };
|
|
6113
6172
|
if (qian >= 45) return { band: '上', text: '骨重充实,中年前后渐入佳境,事业家宅两旺;忌骄忌躁,善守即善成。' };
|
|
@@ -6139,6 +6198,7 @@ function buildChenggu(input) {
|
|
|
6139
6198
|
}
|
|
6140
6199
|
const total = wYear + wMonth + wDay + wHour;
|
|
6141
6200
|
const verdict = bandVerdict(total);
|
|
6201
|
+
const song = songOf(total);
|
|
6142
6202
|
const jdn = toJDN(year, month, day);
|
|
6143
6203
|
|
|
6144
6204
|
return {
|
|
@@ -6161,15 +6221,19 @@ function buildChenggu(input) {
|
|
|
6161
6221
|
},
|
|
6162
6222
|
total: { qian: total, label: formatWeight(total) },
|
|
6163
6223
|
verdict,
|
|
6224
|
+
song: song
|
|
6225
|
+
? { qian: total, label: formatWeight(total), title: `称骨歌·${formatWeight(total)}`, text: song.text, plain: song.plain, source: '通行本《称骨歌》' }
|
|
6226
|
+
: { qian: total, label: formatWeight(total), title: `称骨歌·${formatWeight(total)}`, text: '', plain: '该骨重未见通行本歌诀(表内应落在二两一钱至七两二钱之间)。', source: '通行本《称骨歌》' },
|
|
6164
6227
|
sources: [
|
|
6165
6228
|
'骨重表:通行本袁天罡称骨(六十甲子年 / 十二月 / 三十日 / 十二时辰)',
|
|
6166
|
-
'
|
|
6229
|
+
'歌诀:通行本《称骨歌》原文照录(各版本有异文,断句标点已统一)',
|
|
6230
|
+
'释义:白话自撰,非歌诀原文,只作字面直解',
|
|
6167
6231
|
],
|
|
6168
|
-
disclaimer: '
|
|
6232
|
+
disclaimer: '骨重与歌诀均为通行本口径,属民俗娱乐参考;释义为白话解释,不构成命运断言。',
|
|
6169
6233
|
};
|
|
6170
6234
|
}
|
|
6171
6235
|
|
|
6172
|
-
return { YEAR_WEIGHT, MONTH_WEIGHT, DAY_WEIGHT, HOUR_WEIGHT, formatWeight, lunarDayText, lunarMonthText, buildChenggu };
|
|
6236
|
+
return { YEAR_WEIGHT, MONTH_WEIGHT, DAY_WEIGHT, HOUR_WEIGHT, formatWeight, lunarDayText, lunarMonthText, CHENGGU_SONG, songOf, buildChenggu };
|
|
6173
6237
|
})();
|
|
6174
6238
|
|
|
6175
6239
|
__mods.xiaoliuren = (function () {
|
|
@@ -9200,13 +9264,17 @@ function zeriText(r) {
|
|
|
9200
9264
|
}
|
|
9201
9265
|
|
|
9202
9266
|
function chengguText(r) {
|
|
9203
|
-
|
|
9267
|
+
const s = r.song || {};
|
|
9268
|
+
const lines = [
|
|
9204
9269
|
`【称骨】${r.input.solar} ${r.lunar.text}`,
|
|
9205
9270
|
`四项:${r.weights.year.label} ${r.weights.month.label} ${r.weights.day.label} ${r.weights.hour.label}`,
|
|
9206
9271
|
`合计:${r.total.label}(${r.verdict.band})`,
|
|
9207
|
-
|
|
9208
|
-
'
|
|
9209
|
-
|
|
9272
|
+
`歌诀(${r.total.label}):${s.text || '—'}`,
|
|
9273
|
+
`释义:${s.plain || '—'}`,
|
|
9274
|
+
`分档白话:${r.verdict.text}`,
|
|
9275
|
+
'口径:骨重与歌诀为通行本口径(各版本歌诀有异文),释义为白话自撰,属民俗娱乐参考。',
|
|
9276
|
+
];
|
|
9277
|
+
return lines.join('\n');
|
|
9210
9278
|
}
|
|
9211
9279
|
|
|
9212
9280
|
function xiaoliurenText(r) {
|
|
@@ -9668,6 +9736,17 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
9668
9736
|
.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
9737
|
.mp-kline .kl-lbl{fill:var(--muted);font-size:8px;font-family:system-ui,sans-serif}
|
|
9670
9738
|
.mp-kline .kl-lbl.age{font-size:8.5px}
|
|
9739
|
+
.mp-kline .kl-lbl.axis{font-size:8px;letter-spacing:.02em;opacity:.85}
|
|
9740
|
+
.mp-kline .kl-stripband{fill:var(--ink);opacity:.06;rx:2}
|
|
9741
|
+
.mp-kline .kl-ma-lbl{font-size:8.5px;font-family:system-ui,sans-serif;paint-order:stroke;stroke:var(--card);stroke-width:2.4px;stroke-linejoin:round;fill:var(--muted)}
|
|
9742
|
+
.mp-kline .kl-ma-lbl.m5{fill:var(--quan)}
|
|
9743
|
+
.mp-kline .kl-ma-lbl.m10{fill:var(--ke);opacity:.9}
|
|
9744
|
+
.mp-kline .kl-stats{display:flex;gap:14px;flex-wrap:wrap;margin-top:6px;font-size:11px;color:var(--muted);font-family:system-ui,sans-serif}
|
|
9745
|
+
.mp-kline .kl-stats span{display:inline-flex;align-items:baseline;gap:5px}
|
|
9746
|
+
.mp-kline .kl-stats em{font-style:normal;font-size:10.5px;color:var(--dim)}
|
|
9747
|
+
.mp-kline .kl-stats b{font-size:12px;font-weight:600;color:var(--ink2);font-variant-numeric:tabular-nums}
|
|
9748
|
+
.mp-kline .kl-stats b.hi{color:var(--ji)}
|
|
9749
|
+
.mp-kline .kl-stats b.lo{color:var(--lu)}
|
|
9671
9750
|
.mp-kline .kl-c.up line{stroke:var(--ji);stroke-width:.8;opacity:.8}
|
|
9672
9751
|
.mp-kline .kl-c.up rect{fill:var(--ji);opacity:.92}
|
|
9673
9752
|
.mp-kline .kl-c.down line{stroke:var(--lu);stroke-width:.8;opacity:.8}
|
|
@@ -9818,6 +9897,29 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
9818
9897
|
.mp-fu.miss .mp-fu-h{color:var(--red)}
|
|
9819
9898
|
.mp-fu-ev{margin-top:5px;font-size:12px;color:var(--muted);font-family:system-ui,sans-serif}
|
|
9820
9899
|
.mp-quick{margin:12px 16px;border:1px solid var(--line);border-radius:8px;background:var(--card);padding:12px 14px}
|
|
9900
|
+
.mp-cg{margin:12px 16px;border:1px solid var(--line);border-radius:8px;background:var(--card);padding:12px 14px;font-family:system-ui,sans-serif}
|
|
9901
|
+
.mp-cg-h{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap;margin-bottom:9px}
|
|
9902
|
+
.mp-cg-h b{font-size:13px;color:var(--ink);font-weight:600}
|
|
9903
|
+
.mp-cg-h span{font-size:11.5px;color:var(--muted)}
|
|
9904
|
+
.mp-cg-w{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:var(--line);border:1px solid var(--line);border-radius:6px;overflow:hidden}
|
|
9905
|
+
.mp-cg .cg-cell{background:var(--card);padding:7px 9px}
|
|
9906
|
+
.mp-cg .cg-cell em{display:block;font-style:normal;font-size:10.5px;color:var(--muted);margin-bottom:2px}
|
|
9907
|
+
.mp-cg .cg-cell b{font-size:13.5px;color:var(--ink);font-weight:600;font-variant-numeric:tabular-nums}
|
|
9908
|
+
.mp-cg-tot{display:flex;align-items:baseline;gap:8px;margin:10px 0 4px}
|
|
9909
|
+
.mp-cg-tot em{font-style:normal;font-size:11px;color:var(--muted)}
|
|
9910
|
+
.mp-cg-tot b{font-size:19px;color:var(--lu);font-weight:700;letter-spacing:.02em}
|
|
9911
|
+
.mp-cg-tot i{font-style:normal;font-size:10.5px;color:var(--muted);border:1px solid var(--line);border-radius:999px;padding:1px 7px}
|
|
9912
|
+
.mp-cg-song{margin-top:8px;padding:10px 12px;border-left:3px solid var(--quan);background:var(--band);border-radius:0 6px 6px 0}
|
|
9913
|
+
.mp-cg-song-h{font-size:11px;color:var(--muted);margin-bottom:5px}
|
|
9914
|
+
.mp-cg-verse{font-family:var(--kai,system-ui),serif;font-size:15px;line-height:2;color:var(--ink);letter-spacing:.03em}
|
|
9915
|
+
.mp-cg-verse span{display:block}
|
|
9916
|
+
.mp-cg-miss{color:var(--muted);font-size:12.5px}
|
|
9917
|
+
.mp-cg-plain{margin-top:7px;font-size:12.5px;line-height:1.85;color:var(--ink2)}
|
|
9918
|
+
.mp-cg-plain em,.mp-cg-band em{font-style:normal;font-size:10.5px;color:var(--muted);border:1px solid var(--line);border-radius:3px;padding:0 4px;margin-right:6px;vertical-align:1px}
|
|
9919
|
+
.mp-cg-band{margin-top:8px;font-size:12.5px;line-height:1.8;color:var(--ink2)}
|
|
9920
|
+
.mp-cg-note{margin-top:9px;padding-top:8px;border-top:1px dashed var(--line);font-size:11px;line-height:1.7;color:var(--muted)}
|
|
9921
|
+
@media print{.mp-cg{break-inside:avoid}}
|
|
9922
|
+
@media (max-width:640px){.mp-cg-w{grid-template-columns:repeat(2,minmax(0,1fr))}}
|
|
9821
9923
|
.mp-quick-h{font-size:13px;color:var(--lu);margin-bottom:6px;font-family:system-ui,sans-serif}
|
|
9822
9924
|
.mp-quick-pre{margin:0;white-space:pre-wrap;word-break:break-word;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:1.9;color:var(--ink2)}
|
|
9823
9925
|
.mp-it-dis{padding:11px 16px;border-top:1px solid var(--line);background:var(--band);font-size:12px;line-height:1.75;color:var(--muted);font-family:system-ui,sans-serif}
|
|
@@ -10705,13 +10807,14 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10705
10807
|
</div>`;
|
|
10706
10808
|
};
|
|
10707
10809
|
|
|
10810
|
+
let klineSeq = 0;
|
|
10708
10811
|
pp.trendChart = function (r) {
|
|
10709
10812
|
const pts = r && Array.isArray(r.points) ? r.points : [];
|
|
10710
10813
|
if (pts.length < 2) return '';
|
|
10711
10814
|
const segs = r && Array.isArray(r.segments) ? r.segments : [];
|
|
10712
10815
|
const num = (v) => (typeof v === 'number' && isFinite(v) ? v : 0);
|
|
10713
|
-
const W = 720, H =
|
|
10714
|
-
const M = { t:
|
|
10816
|
+
const W = 720, H = 322;
|
|
10817
|
+
const M = { t: 34, r: 46, b: 66, l: 36 };
|
|
10715
10818
|
const pw = W - M.l - M.r, ph = H - M.t - M.b;
|
|
10716
10819
|
const n = pts.length;
|
|
10717
10820
|
const step = pw / n;
|
|
@@ -10719,6 +10822,9 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10719
10822
|
const Y = (v) => M.t + ph - (Math.max(0, Math.min(100, v)) / 100) * ph;
|
|
10720
10823
|
const bodyW = Math.max(1.1, Math.min(10, step * 0.62));
|
|
10721
10824
|
const sc = (p) => num(p.score);
|
|
10825
|
+
const yb = M.t + ph;
|
|
10826
|
+
const stripTop = yb + 20, stripH = 22;
|
|
10827
|
+
const clipId = `klclip${(klineSeq += 1)}`;
|
|
10722
10828
|
|
|
10723
10829
|
const bands = segs.map((s, i) => {
|
|
10724
10830
|
const i0 = Math.max(0, s.startAge - 1);
|
|
@@ -10726,11 +10832,15 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10726
10832
|
if (i1 < i0) return '';
|
|
10727
10833
|
const x = M.l + i0 * step;
|
|
10728
10834
|
const w = Math.max(0.6, (i1 - i0 + 1) * step);
|
|
10729
|
-
const
|
|
10730
|
-
|
|
10835
|
+
const tint = i % 2 === 1;
|
|
10836
|
+
const rect = tint
|
|
10837
|
+
? `<rect class="kl-band" x="${x.toFixed(1)}" y="${M.t}" width="${w.toFixed(1)}" height="${ph}"/>`
|
|
10838
|
+
+ `<rect class="kl-stripband" x="${x.toFixed(1)}" y="${stripTop}" width="${w.toFixed(1)}" height="${stripH}"/>` : '';
|
|
10731
10839
|
const line = i === 0 ? ''
|
|
10732
|
-
: `<line class="kl-segline" x1="${x.toFixed(1)}" y1="${M.t}" x2="${x.toFixed(1)}" y2="${
|
|
10733
|
-
|
|
10840
|
+
: `<line class="kl-segline" x1="${x.toFixed(1)}" y1="${M.t}" x2="${x.toFixed(1)}" y2="${yb}"/>`;
|
|
10841
|
+
const cx = Math.min(Math.max(M.l + ((i0 + i1 + 1) / 2) * step, M.l + 22), M.l + pw - 22);
|
|
10842
|
+
return rect + line
|
|
10843
|
+
+ `<text class="kl-seg" x="${cx.toFixed(1)}" y="${(stripTop + 15).toFixed(1)}" text-anchor="middle">${esc(s.ganZhi)}</text>`;
|
|
10734
10844
|
}).join('');
|
|
10735
10845
|
|
|
10736
10846
|
const grid = [0, 25, 50, 75, 100].map((v) =>
|
|
@@ -10739,7 +10849,7 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10739
10849
|
|
|
10740
10850
|
const candles = pts.map((p, i) => {
|
|
10741
10851
|
const k = p.kline || {};
|
|
10742
|
-
const o = num(k.open), c = num(k.close), hi = num(k.high), lo = num(k.low);
|
|
10852
|
+
const o = num(k.open), c = num(k.close), hi = Math.min(100, num(k.high)), lo = Math.max(0, num(k.low));
|
|
10743
10853
|
const up = c >= o;
|
|
10744
10854
|
const yO = Y(o), yC = Y(c);
|
|
10745
10855
|
const top = Math.min(yO, yC);
|
|
@@ -10751,16 +10861,35 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10751
10861
|
+ `<rect x="${(x - bodyW / 2).toFixed(2)}" y="${top.toFixed(1)}" width="${bodyW.toFixed(2)}" height="${h.toFixed(1)}" rx="0.7"/></g>`;
|
|
10752
10862
|
}).join('');
|
|
10753
10863
|
|
|
10754
|
-
const
|
|
10755
|
-
const
|
|
10864
|
+
const maSeries = (win) => {
|
|
10865
|
+
const out = [];
|
|
10756
10866
|
for (let i = 0; i < n; i++) {
|
|
10757
10867
|
if (i + 1 < win) continue;
|
|
10758
10868
|
let sum = 0;
|
|
10759
10869
|
for (let j = i + 1 - win; j <= i; j++) sum += sc(pts[j]);
|
|
10760
|
-
|
|
10870
|
+
out.push({ i, v: sum / win });
|
|
10761
10871
|
}
|
|
10762
|
-
return
|
|
10872
|
+
return out;
|
|
10873
|
+
};
|
|
10874
|
+
const maPath = (win) => maSeries(win)
|
|
10875
|
+
.map((q, k) => `${k ? 'L' : 'M'}${X(q.i).toFixed(1)} ${Y(q.v).toFixed(1)}`).join(' ');
|
|
10876
|
+
const maLabel = (win, cls) => {
|
|
10877
|
+
const s = maSeries(win);
|
|
10878
|
+
if (!s.length) return '';
|
|
10879
|
+
const last = s[s.length - 1];
|
|
10880
|
+
return { cls, y: Y(last.v), text: `<text class="kl-ma-lbl ${cls}" x="${M.l + pw + 5}" y="${Y(last.v).toFixed(1)}" text-anchor="start">${last.v.toFixed(0)}</text>` };
|
|
10763
10881
|
};
|
|
10882
|
+
const lab10 = maLabel(10, 'm10'), lab5 = maLabel(5, 'm5');
|
|
10883
|
+
const maLabels = (() => {
|
|
10884
|
+
if (!lab5 || !lab10) return `${lab10 ? lab10.text : ''}${lab5 ? lab5.text : ''}`;
|
|
10885
|
+
let y5 = lab5.y, y10 = lab10.y;
|
|
10886
|
+
if (Math.abs(y5 - y10) < 10) {
|
|
10887
|
+
const top = Math.min(y5, y10), bot = Math.max(y5, y10);
|
|
10888
|
+
y5 = top - 6; y10 = bot + 6;
|
|
10889
|
+
}
|
|
10890
|
+
return `<text class="kl-ma-lbl m10" x="${M.l + pw + 5}" y="${y10.toFixed(1)}" text-anchor="start">${maSeries(10).slice(-1)[0].v.toFixed(0)}</text>`
|
|
10891
|
+
+ `<text class="kl-ma-lbl m5" x="${M.l + pw + 5}" y="${y5.toFixed(1)}" text-anchor="start">${maSeries(5).slice(-1)[0].v.toFixed(0)}</text>`;
|
|
10892
|
+
})();
|
|
10764
10893
|
|
|
10765
10894
|
let hiP = pts[0], loP = pts[0];
|
|
10766
10895
|
for (const p of pts) {
|
|
@@ -10779,8 +10908,9 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10779
10908
|
|
|
10780
10909
|
const tickStep = n > 60 ? 10 : 5;
|
|
10781
10910
|
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="${
|
|
10783
|
-
const xNote = `<text class="kl-lbl" x="${M.l
|
|
10911
|
+
`<text class="kl-lbl age" x="${X(pts.indexOf(p)).toFixed(1)}" y="${(yb + 14).toFixed(1)}" text-anchor="middle">${p.age}</text>`).join('');
|
|
10912
|
+
const xNote = `<text class="kl-lbl axis" x="${M.l}" y="${(H - 6).toFixed(1)}">年龄(岁)</text>`
|
|
10913
|
+
+ `<text class="kl-lbl axis" x="${M.l + pw}" y="${(H - 6).toFixed(1)}" text-anchor="end">每岁一分 · 满分 100</text>`;
|
|
10784
10914
|
|
|
10785
10915
|
const legend = `<div class="kl-legend"><span><i class="up"></i>阳线:比上一岁高</span>`
|
|
10786
10916
|
+ `<span><i class="down"></i>阴线:比上一岁低</span>`
|
|
@@ -10789,8 +10919,13 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10789
10919
|
|
|
10790
10920
|
return `<div class="mp-kline-fig">
|
|
10791
10921
|
<svg viewBox="0 0 ${W} ${H}" role="img" aria-label="人生K线:1 到 ${n} 岁的逐年评分蜡烛图">
|
|
10792
|
-
${
|
|
10793
|
-
|
|
10922
|
+
<defs><clipPath id="${clipId}"><rect x="${M.l}" y="${M.t}" width="${pw}" height="${ph}"/></clipPath></defs>
|
|
10923
|
+
${bands}${grid}
|
|
10924
|
+
<g clip-path="url(#${clipId})">
|
|
10925
|
+
${candles}
|
|
10926
|
+
<path class="kl-ma m10" d="${maPath(10)}"/><path class="kl-ma m5" d="${maPath(5)}"/>
|
|
10927
|
+
</g>
|
|
10928
|
+
${maLabels}
|
|
10794
10929
|
${mark(hiP, 'hi', -8)}${mark(loP, 'lo', 12)}
|
|
10795
10930
|
${ages}${xNote}
|
|
10796
10931
|
</svg>${legend}</div>`;
|
|
@@ -10809,9 +10944,27 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10809
10944
|
const worst = (Array.isArray(hl.worst) ? hl.worst : []).map((x) => `<div class="kl-hl lo">${esc(x)}</div>`).join('');
|
|
10810
10945
|
const note = meta.boundaryNote ? `<div class="mp-kline-note">${esc(meta.boundaryNote)}</div>`
|
|
10811
10946
|
: (hl.suppressed ? `<div class="mp-kline-note">${esc(hl.suppressed)}</div>` : '');
|
|
10947
|
+
const pts = Array.isArray(r.points) ? r.points : [];
|
|
10948
|
+
const scoreOf = (p) => (typeof p.score === 'number' && isFinite(p.score) ? p.score : 0);
|
|
10949
|
+
const scores = pts.map(scoreOf);
|
|
10950
|
+
const mean = scores.length ? scores.reduce((a, b) => a + b, 0) / scores.length : 0;
|
|
10951
|
+
const span = scores.length ? Math.max(...scores) - Math.min(...scores) : 0;
|
|
10952
|
+
const segAvg = segs.map((s) => {
|
|
10953
|
+
const inside = pts.filter((p) => p.age >= s.startAge && p.age <= s.endAge).map(scoreOf);
|
|
10954
|
+
return { ganZhi: s.ganZhi, v: inside.length ? inside.reduce((a, b) => a + b, 0) / inside.length : 0 };
|
|
10955
|
+
}).filter((x) => x.v > 0).sort((a, b) => b.v - a.v);
|
|
10956
|
+
const blocked = !!(st.boundary || hl.suppressed);
|
|
10957
|
+
const statCells = [`<span><em>全段均值</em><b>${mean.toFixed(0)}</b></span>`];
|
|
10958
|
+
if (!blocked && segAvg.length) {
|
|
10959
|
+
statCells.push(`<span><em>最好大运</em><b class="hi">${esc(segAvg[0].ganZhi)} ${segAvg[0].v.toFixed(0)}</b></span>`);
|
|
10960
|
+
statCells.push(`<span><em>最差大运</em><b class="lo">${esc(segAvg[segAvg.length - 1].ganZhi)} ${segAvg[segAvg.length - 1].v.toFixed(0)}</b></span>`);
|
|
10961
|
+
}
|
|
10962
|
+
statCells.push(`<span><em>波动幅度</em><b>${span.toFixed(0)}</b></span>`);
|
|
10963
|
+
const stats = `<div class="kl-stats">${statCells.join('')}</div>`;
|
|
10812
10964
|
return `<section class="mp-kline" aria-label="人生K线结果">
|
|
10813
10965
|
<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
10966
|
${chart}
|
|
10967
|
+
${stats}
|
|
10815
10968
|
${chips ? `<div class="kl-segs">${chips}</div>` : ''}
|
|
10816
10969
|
${best || worst ? `<div class="kl-hls">${best}${worst}</div>` : ''}
|
|
10817
10970
|
${note}
|
|
@@ -10819,6 +10972,31 @@ return { interpret, DIRECTIONS, DIRECTION_DEFAULT, BRIGHTNESS, flowOf, geocodeAd
|
|
|
10819
10972
|
</section>`;
|
|
10820
10973
|
};
|
|
10821
10974
|
|
|
10975
|
+
pp.chengguHTML = function (r) {
|
|
10976
|
+
if (!r) return '';
|
|
10977
|
+
const w = r.weights || {};
|
|
10978
|
+
const song = r.song || {};
|
|
10979
|
+
const cells = ['year', 'month', 'day', 'hour'].map((k) => {
|
|
10980
|
+
const x = w[k] || { label: '', qian: 0 };
|
|
10981
|
+
const name = String(x.label || '').split(' ')[0] || '';
|
|
10982
|
+
const val = String(x.label || '').split(' ')[1] || '';
|
|
10983
|
+
return `<div class="cg-cell"><em>${esc(name)}</em><b>${esc(val)}</b></div>`;
|
|
10984
|
+
}).join('');
|
|
10985
|
+
const verse = String(song.text || '');
|
|
10986
|
+
const lines = verse ? verse.replace(/[。]$/, '').split(';').map((s, i) => `<span>${esc(s)}${i === 0 ? ';' : '。'}</span>`).join('') : '';
|
|
10987
|
+
const band = r.verdict && r.verdict.band ? r.verdict.band : '';
|
|
10988
|
+
return `<section class="mp-cg" aria-label="称骨结果">
|
|
10989
|
+
<div class="mp-cg-h"><b>称骨</b><span>${esc(r.lunar && r.lunar.text ? r.lunar.text : '')}</span></div>
|
|
10990
|
+
<div class="mp-cg-w">${cells}</div>
|
|
10991
|
+
<div class="mp-cg-tot"><em>骨重合计</em><b>${esc(r.total && r.total.label ? r.total.label : '')}</b>${band ? `<i>${esc(band)}</i>` : ''}</div>
|
|
10992
|
+
<div class="mp-cg-song"><div class="mp-cg-song-h">称骨歌 · ${esc(r.total && r.total.label ? r.total.label : '')}</div>
|
|
10993
|
+
<div class="mp-cg-verse">${lines || '<span class="mp-cg-miss">该骨重未见通行本歌诀</span>'}</div>
|
|
10994
|
+
<div class="mp-cg-plain"><em>释义</em>${esc(song.plain || '')}</div></div>
|
|
10995
|
+
${r.verdict && r.verdict.text ? `<div class="mp-cg-band"><em>分档</em>${esc(r.verdict.text)}</div>` : ''}
|
|
10996
|
+
<div class="mp-cg-note">骨重与歌诀为通行本口径(各版本歌诀有异文,断句标点已统一);释义为白话自撰,只作字面直解,属民俗娱乐参考,不构成命运断言。</div>
|
|
10997
|
+
</section>`;
|
|
10998
|
+
};
|
|
10999
|
+
|
|
10822
11000
|
pp.baziHTML = function (r) {
|
|
10823
11001
|
const cols = [['year', '年柱'], ['month', '月柱'], ['day', '日柱'], ['hour', '时柱']];
|
|
10824
11002
|
const SHORT = { year: '年', month: '月', day: '日', hour: '时' };
|
|
@@ -11935,7 +12113,8 @@ function App() {
|
|
|
11935
12113
|
: result.kind === 'hepan' ? (result.r.chart === 'ziwei' ? PP.ziweiHepanHTML(result.r) : PP.hepanHTML(result.r))
|
|
11936
12114
|
: result.kind === 'tarot' ? PP.tarotHTML(result.r)
|
|
11937
12115
|
: result.kind === 'liuyao' ? PP.liuyaoHTML(result.r)
|
|
11938
|
-
: result.kind === '
|
|
12116
|
+
: result.kind === 'chenggu' ? PP.chengguHTML(result.r)
|
|
12117
|
+
: result.kind === 'trend' ? PP.trendHTML(result.r)
|
|
11939
12118
|
: PP.quickHTML(result.r),
|
|
11940
12119
|
result.it,
|
|
11941
12120
|
{ folded: defaultFolded() },
|
package/engine/chenggu.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// 袁天罡称骨:按农历年/月/日/时辰四柱骨重求和,查通行本《称骨歌》原文,附白话释义。
|
|
2
|
+
// 骨重表与歌诀均为通行本口径(各版本有异文,此处照录通行本);释义是白话自撰,不是原文。
|
|
3
3
|
import { solarToLunar } from './lunar.js';
|
|
4
4
|
import { ganzhiName, toJDN, dayGanzhiIndex } from './calendar.js';
|
|
5
5
|
import { assertCivil } from './validate.js';
|
|
@@ -58,6 +58,71 @@ export function lunarMonthText(month, isLeap = false) {
|
|
|
58
58
|
return `${isLeap ? '闰' : ''}${MONTH_TEXT[month - 1] || month}月`;
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* 通行本《称骨歌》五十二首:键 = 骨重(钱),21 = 二两一钱 … 72 = 七两二钱。
|
|
63
|
+
* text 为歌诀原文照录(各版本有异文,此处取通行本,标点统一为「,;,。」);
|
|
64
|
+
* plain 为白话释义,是自撰,不是原文。
|
|
65
|
+
*/
|
|
66
|
+
export const CHENGGU_SONG = {
|
|
67
|
+
21: { text: '短命非业谓大空,平生灾难事重重;凶祸频临陷逆境,终世困苦事不成。', plain: '起点低、阻力大,凡事难一气呵成;宜守稳借力,不宜孤注一掷。' },
|
|
68
|
+
22: { text: '身寒骨冷苦伶仃,此命推来行乞人;劳劳碌碌无度日,终年打拱过平生。', plain: '早年资源薄、亲缘淡,靠勤苦与人缘翻身,最忌自弃。' },
|
|
69
|
+
23: { text: '此命推来骨格轻,求谋作事事难成;妻儿兄弟应难许,别处他乡作散人。', plain: '独自谋事难成,宜合伙或依附平台;离乡发展反有出路。' },
|
|
70
|
+
24: { text: '此命推来福禄无,门庭困苦总难荣;六亲骨肉皆无靠,流浪他乡作老翁。', plain: '六亲助力少,别指望祖业,早做打算、靠双手积累。' },
|
|
71
|
+
25: { text: '此命推来祖业微,门庭营度似稀奇;六亲骨肉如冰炭,一世勤劳自把持。', plain: '家底薄、亲缘冷,一生靠自己操持,勤俭则安。' },
|
|
72
|
+
26: { text: '平生衣禄苦中求,独自营谋事不休;离祖出门宜早计,晚来衣禄自无休。', plain: '白手起家之格:早离乡、晚渐稳,不必怕慢。' },
|
|
73
|
+
27: { text: '一生作事少商量,难靠祖宗作主张;独马单枪空做去,早年晚岁总无长。', plain: '主意要自己拿,靠人不如靠己;早定方向才不空忙。' },
|
|
74
|
+
28: { text: '一生行事似飘蓬,祖宗产业在梦中;若不过房改名姓,也当移徒二三通。', plain: '祖业难守,适合外出或改换环境,动中求安。' },
|
|
75
|
+
29: { text: '初年运限未曾亨,纵有功名在后成;须过四旬才可立,移居改姓始为良。', plain: '功名在后,四十前后才立得住,忌中途频繁换道。' },
|
|
76
|
+
30: { text: '劳劳碌碌苦中求,东奔西走何日休;若使终身勤与俭,老来稍可免忧愁。', plain: '东奔西走的劳碌格,靠勤俭积攒,晚年才得清闲。' },
|
|
77
|
+
31: { text: '忙忙碌碌苦中求,何日云开见日头;难得祖基家可立,中年衣食渐无忧。', plain: '先难后易:祖基难得,中年衣食转宽,守住本业即可。' },
|
|
78
|
+
32: { text: '初年运蹇事难谋,渐有财源如水流;到得中年衣食旺,那时名利一齐收。', plain: '幼年蹇滞,中年后财源渐旺,名利可期。' },
|
|
79
|
+
33: { text: '早年做事事难成,百年勤劳枉费心;半世自如流水去,后来运到始得金。', plain: '前半程多试错,后半程才见成果,急不得。' },
|
|
80
|
+
34: { text: '此命福气果如何,僧道门中衣禄多;离祖出家方为妙,朝晚拜佛念弥陀。', plain: '与清静行当、宗教或专门技艺有缘,离祖发展更顺。' },
|
|
81
|
+
35: { text: '生平福量不周全,祖业根基觉少传;营事生涯宜守旧,时来衣食胜从前。', plain: '福量不齐,宜守旧业、少折腾;时运到了自然宽裕。' },
|
|
82
|
+
36: { text: '不须劳碌过平生,独自成家福不轻;早有福星常照命,任君行去百般成。', plain: '不必太劳碌,福气随身,行事多能成。' },
|
|
83
|
+
37: { text: '此命般般事不成,弟兄少力自孤行;虽然祖业须微有,来得明时去不明。', plain: '单打独斗吃力、兄弟少力;宜合作,钱财要明算账。' },
|
|
84
|
+
38: { text: '一身骨肉最清高,早入簧门姓氏标;待到年将三十六,蓝衫脱去换红袍。', plain: '读书与专业路线见长,三十六前后有转机与体面。' },
|
|
85
|
+
39: { text: '此命终身运不通,劳劳作事尽皆空;苦心竭力成家计,到得那时在梦中。', plain: '早年空忙,成家立业偏晚;重在坚持,不宜频繁改行。' },
|
|
86
|
+
40: { text: '平生衣禄是绵长,件件心中自主张;前面风霜多受过,后来必定享安康。', plain: '先苦后甜:衣食渐稳,事在自主,晚景安康。' },
|
|
87
|
+
41: { text: '此命推来自不同,为人能干异凡庸;中年还有逍遥福,不比前时运来通。', plain: '能干出众,早年只是运会未到;中年有逍遥之福。' },
|
|
88
|
+
42: { text: '得宽怀处且宽怀,何用双眉皱不开;若使中年命运济,那时名利一起来。', plain: '心宽则顺;中年运济,名利自来,不必过虑。' },
|
|
89
|
+
43: { text: '为人心性最聪明,作事轩昂近贵人;衣禄一生天注定,不须劳碌是丰亨。', plain: '聪明近贵,易得贵人提携,衣禄有天定之说。' },
|
|
90
|
+
44: { text: '万事由天莫苦求,须知福碌赖人修;当年财帛难如意,晚景欣然便不优。', plain: '少壮难如意,晚景反安;福禄也靠人修,不必强求。' },
|
|
91
|
+
45: { text: '名利推求竟若何,前番辛苦后奔波;命中难养男和女,骨肉扶持也不多。', plain: '中年前后仍奔波,子女缘与骨肉助力偏薄,凡事多自扛。' },
|
|
92
|
+
46: { text: '东西南北尽皆通,出姓移居更觉隆;衣禄无穷无数定,中年晚景一般同。', plain: '外出、迁居更旺;衣禄不愁,中晚年境况相近。' },
|
|
93
|
+
47: { text: '此命推求旺末年,妻荣子贵自怡然;平生原有滔滔福,可卜财源若水泉。', plain: '晚运佳:妻荣子贵,福厚财源长。' },
|
|
94
|
+
48: { text: '初年运道未曾通,几许蹉跎命亦穷;兄弟六亲无依靠,一生事业晚来整。', plain: '早年蹉跎、六亲少靠,事业晚成,忌半途而废。' },
|
|
95
|
+
49: { text: '此命推来福不轻,自成自立显门庭;从来富贵人钦敬,使婢差奴过一生。', plain: '自立门户、显耀门庭,中年后受人敬重。' },
|
|
96
|
+
50: { text: '为利为名终日劳,中年福禄也多遭;老来自有财星照,不比前番目下高。', plain: '为名利终日奔忙,中年多波折;老来财星照,压力渐轻。' },
|
|
97
|
+
51: { text: '一世荣华事事通,不须劳碌自亨通;兄弟叔侄皆如意,家业成时福禄宏。', plain: '事多顺遂,兄弟叔侄得力,家业易成。' },
|
|
98
|
+
52: { text: '一世亨通事事能,不须劳苦自然宁;宗族有光欣喜甚,家产丰盈自称心。', plain: '诸事能干、少劳而宁;宗族有光,家产丰盈。' },
|
|
99
|
+
53: { text: '此格推来福泽宏,兴家立业在其中;一生衣食安排定,却是人间一福翁。', plain: '兴家立业之格,衣食安稳,是人间有福之人。' },
|
|
100
|
+
54: { text: '此格详采福泽宏,诗书满腹看功成;丰衣足食多安稳,正是人间有福人。', plain: '读书人格局:功名可期,衣食安稳。' },
|
|
101
|
+
55: { text: '策马扬鞭争名利,少年作事费筹论;一朝福禄源源至,富贵荣华显六亲。', plain: '少年费筹谋,一朝福至;富贵显亲,属于厚积薄发。' },
|
|
102
|
+
56: { text: '此格推来礼义通,一身福禄用无穷;甜酸苦辣皆尝过,滚滚财源盈而丰。', plain: '福禄厚:人生百味都经过,之后财源稳而丰。' },
|
|
103
|
+
57: { text: '福禄丰盈万事全,一身荣耀乐天年;名扬威震人争羡,此世逍遥宛似仙。', plain: '万事较全,名望与荣耀随行,晚运逍遥。' },
|
|
104
|
+
58: { text: '平生衣食自然来,名利双全富贵偕;金榜题名登甲第,紫袍玉带走金阶。', plain: '衣食自来、名利双全;有科第与体面之象。' },
|
|
105
|
+
59: { text: '细推此格秀而清,必定才高学业成;甲第之中应有分,扬鞭走马显威荣。', plain: '才高学业成,有科第之份,前程显达。' },
|
|
106
|
+
60: { text: '一朝金榜快题名,显祖荣宗大器成;衣禄定然无欠缺,田园财帛更丰盈。', plain: '金榜题名、显祖荣宗;衣禄丰足,田园财帛皆旺。' },
|
|
107
|
+
61: { text: '不作朝中金榜客,定为世上大财翁;聪明天付经书熟,名显高褂自是荣。', plain: '不入仕途也能成富;聪明博学,自有显名之荣。' },
|
|
108
|
+
62: { text: '此命生来福不穷,读书必定显亲宗;紫衣玉带为卿相,富贵荣华孰与同。', plain: '福泽不穷;读书可显亲,有卿相之象。' },
|
|
109
|
+
63: { text: '命主为官福禄长,得来富贵实非常;名题雁塔传金榜,大显门庭天下扬。', plain: '仕途顺、福禄长;富贵非常,门庭显扬。' },
|
|
110
|
+
64: { text: '此格威权不可当,紫袍金带尘高堂;荣华富贵谁能及,万古留名姓氏扬。', plain: '掌权之格:富贵与声名俱隆,留名后世。' },
|
|
111
|
+
65: { text: '细推此命福非轻,富贵荣华孰与争;定国安邦人极品,威声显赫震寰瀛。', plain: '贵重之命;有定国安邦之器,声威远震。' },
|
|
112
|
+
66: { text: '此格人间一福人,堆金积玉满堂春;从来富贵有天定,金榜题名更显亲。', plain: '堆金积玉、富贵天定;又有金榜显亲之象。' },
|
|
113
|
+
67: { text: '此命生来福自宏,田园家业最高隆;平生衣禄盈丰足,一路荣华万事通。', plain: '福厚家隆:田园家业兴旺,衣禄丰足,一路荣华。' },
|
|
114
|
+
68: { text: '富贵由天莫苦求,万事家计不须谋;十年不比前番事,祖业根基千古留。', plain: '家计不必苦谋;祖业根基可留,运势比前十年更好。' },
|
|
115
|
+
69: { text: '君是人间福禄星,一生富贵众人钦;总然衣禄由天定,安享荣华过一生。', plain: '人间福禄星:富贵受人钦敬,安享荣华。' },
|
|
116
|
+
70: { text: '此命推来福不轻,何须愁虑苦劳心;荣华富贵已天定,正笏垂绅拜紫宸。', plain: '不必愁虑劳心;荣华富贵已定,有朝堂之象。' },
|
|
117
|
+
71: { text: '此命生成大不同,公侯卿相在其中;一生自有逍遥福,富贵荣华极品隆。', plain: '公侯卿相之格:福厚逍遥,富贵极品。' },
|
|
118
|
+
72: { text: '此命推来天下隆,必定人间一主公;富贵荣华数不尽,定为乾坤一蛟龙。', plain: '极贵之格;但四表上限为七两一钱,此档基本不可达,仅备档。' },
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/** 按骨重取歌诀(超出 21–72 钱返回 null)。 */
|
|
122
|
+
export function songOf(qian) {
|
|
123
|
+
return CHENGGU_SONG[qian] || null;
|
|
124
|
+
}
|
|
125
|
+
|
|
61
126
|
/** 骨重分档(白话自撰)。 */
|
|
62
127
|
function bandVerdict(qian) {
|
|
63
128
|
if (qian >= 55) return { band: '上上', text: '骨重沉实,根基深厚,一生多逢贵人,谋事易成;守正持重,福泽可久。' };
|
|
@@ -95,6 +160,7 @@ export function buildChenggu(input) {
|
|
|
95
160
|
}
|
|
96
161
|
const total = wYear + wMonth + wDay + wHour;
|
|
97
162
|
const verdict = bandVerdict(total);
|
|
163
|
+
const song = songOf(total);
|
|
98
164
|
const jdn = toJDN(year, month, day);
|
|
99
165
|
|
|
100
166
|
return {
|
|
@@ -117,10 +183,14 @@ export function buildChenggu(input) {
|
|
|
117
183
|
},
|
|
118
184
|
total: { qian: total, label: formatWeight(total) },
|
|
119
185
|
verdict,
|
|
186
|
+
song: song
|
|
187
|
+
? { qian: total, label: formatWeight(total), title: `称骨歌·${formatWeight(total)}`, text: song.text, plain: song.plain, source: '通行本《称骨歌》' }
|
|
188
|
+
: { qian: total, label: formatWeight(total), title: `称骨歌·${formatWeight(total)}`, text: '', plain: '该骨重未见通行本歌诀(表内应落在二两一钱至七两二钱之间)。', source: '通行本《称骨歌》' },
|
|
120
189
|
sources: [
|
|
121
190
|
'骨重表:通行本袁天罡称骨(六十甲子年 / 十二月 / 三十日 / 十二时辰)',
|
|
122
|
-
'
|
|
191
|
+
'歌诀:通行本《称骨歌》原文照录(各版本有异文,断句标点已统一)',
|
|
192
|
+
'释义:白话自撰,非歌诀原文,只作字面直解',
|
|
123
193
|
],
|
|
124
|
-
disclaimer: '
|
|
194
|
+
disclaimer: '骨重与歌诀均为通行本口径,属民俗娱乐参考;释义为白话解释,不构成命运断言。',
|
|
125
195
|
};
|
|
126
196
|
}
|
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.4 (+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
|
@@ -740,13 +740,17 @@ function zeriText(r) {
|
|
|
740
740
|
|
|
741
741
|
/** 称骨文本 */
|
|
742
742
|
function chengguText(r) {
|
|
743
|
-
|
|
743
|
+
const s = r.song || {};
|
|
744
|
+
const lines = [
|
|
744
745
|
`【称骨】${r.input.solar} ${r.lunar.text}`,
|
|
745
746
|
`四项:${r.weights.year.label} ${r.weights.month.label} ${r.weights.day.label} ${r.weights.hour.label}`,
|
|
746
747
|
`合计:${r.total.label}(${r.verdict.band})`,
|
|
747
|
-
|
|
748
|
-
'
|
|
749
|
-
|
|
748
|
+
`歌诀(${r.total.label}):${s.text || '—'}`,
|
|
749
|
+
`释义:${s.plain || '—'}`,
|
|
750
|
+
`分档白话:${r.verdict.text}`,
|
|
751
|
+
'口径:骨重与歌诀为通行本口径(各版本歌诀有异文),释义为白话自撰,属民俗娱乐参考。',
|
|
752
|
+
];
|
|
753
|
+
return lines.join('\n');
|
|
750
754
|
}
|
|
751
755
|
|
|
752
756
|
/** 小六壬文本 */
|
package/index.js
CHANGED
|
@@ -107,7 +107,7 @@ export function apply(ctx) {
|
|
|
107
107
|
system: {
|
|
108
108
|
type: 'string',
|
|
109
109
|
enum: ['bazi', 'ziwei', 'liuyao', 'tarot', 'meihua', 'daliuren', 'hepan', 'qimen', 'almanac', 'zeri', 'chenggu', 'xiaoliuren', 'star', 'numerology', 'trend', 'fengshui', 'name'],
|
|
110
|
-
description: 'bazi = 四柱八字;ziwei = 紫微斗数;liuyao = 六爻;tarot = 塔罗;meihua = 梅花易数;daliuren = 大六壬;hepan = 合盘(合婚),需同时给 partner;qimen = 奇门遁甲(时家转盘,拆补法);almanac = 黄历(某日宜忌/冲煞/建除/节气);zeri = 择日(某事项在日期区间内逐日打分排序);chenggu =
|
|
110
|
+
description: 'bazi = 四柱八字;ziwei = 紫微斗数;liuyao = 六爻;tarot = 塔罗;meihua = 梅花易数;daliuren = 大六壬;hepan = 合盘(合婚),需同时给 partner;qimen = 奇门遁甲(时家转盘,拆补法);almanac = 黄历(某日宜忌/冲煞/建除/节气);zeri = 择日(某事项在日期区间内逐日打分排序);chenggu = 袁天罡称骨(骨重 + 通行本称骨歌原文 + 白话释义);xiaoliuren = 小六壬(时间或报数起课);star = 星座当日基调;numerology = 生命数字;trend = 人生 K 线(大运/流年走势可视化);fengshui = 风水(八宅命卦/流年飞星/门主灶布局);name = 起名(用字五行评估与候选生成)。',
|
|
111
111
|
},
|
|
112
112
|
datetime: {
|
|
113
113
|
type: 'string',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-metaphysics",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.4",
|
|
4
4
|
"type": "module",
|
|
5
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": [
|