fix(algorithm): 修复紫微斗数核心算法错误并补全紫微星安星法
全网交叉验证发现三处算法错误(信源:uranaischool.com、pvlib/NOAA、feiyuntiegui.com等): 1. 四化飞星映射修复:替换错误的化禄/化权映射(原来10项仅4项正确), 新增化科/化忌映射,采用主星派标准四化表 2. 紫微星安星法补全:实现完整公式(五行局+农历日), 新增五虎遁命宫天干、纳音五行速算、紫微系/天府系14主星正确排列 3. 真太阳时公式勘误:修正Spencer(1971)两个已知系数错误 (0.000075→0.0000075, 0.04089→0.040849) 新增 docs/ALGORITHM_KNOWHOW.md 永久性算法知识库
This commit is contained in:
+5
-1
@@ -201,7 +201,11 @@ config/local.js
|
|||||||
|
|
||||||
# ==================== AI Tools ====================
|
# ==================== AI Tools ====================
|
||||||
.lingma/
|
.lingma/
|
||||||
.trae/
|
|
||||||
|
# ==================== Trae (keep hooks/settings, ignore runtime) ====================
|
||||||
|
.trae/rules/
|
||||||
|
.trae/.suppress-hooks
|
||||||
|
.trae/hooks/.suppress-hooks
|
||||||
|
|
||||||
# agents
|
# agents
|
||||||
AGENTS.md
|
AGENTS.md
|
||||||
|
|||||||
@@ -0,0 +1,540 @@
|
|||||||
|
# 万事宜 · 业务算法 Know-How 知识库
|
||||||
|
|
||||||
|
> 创建日期:2026-08-13
|
||||||
|
> 最后更新:2026-08-13
|
||||||
|
> 验证状态:✅ 已交叉验证
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
- [1. 概述](#1-概述)
|
||||||
|
- [2. 紫微斗数排盘算法](#2-紫微斗数排盘算法)
|
||||||
|
- [2.1 干支计算](#21-干支计算)
|
||||||
|
- [2.2 命宫/身宫公式](#22-命宫身宫公式)
|
||||||
|
- [2.3 十二宫安星](#23-十二宫安星)
|
||||||
|
- [2.4 紫微星安星法(完整版)](#24-紫微星安星法完整版)
|
||||||
|
- [2.5 十四主星安星顺序](#25-十四主星安星顺序)
|
||||||
|
- [2.6 四化飞星表](#26-四化飞星表)
|
||||||
|
- [2.7 三方四正](#27-三方四正)
|
||||||
|
- [2.8 星曜评分系统](#28-星曜评分系统)
|
||||||
|
- [3. 黄历算法](#3-黄历算法)
|
||||||
|
- [3.1 公历→农历转换](#31-公历农历转换)
|
||||||
|
- [3.2 建除十二神](#32-建除十二神)
|
||||||
|
- [3.3 神煞系统](#33-神煞系统)
|
||||||
|
- [3.4 六十甲子纳音](#34-六十甲子纳音)
|
||||||
|
- [3.5 彭祖百忌](#35-彭祖百忌)
|
||||||
|
- [3.6 节气与节日](#36-节气与节日)
|
||||||
|
- [4. 真太阳时算法](#4-真太阳时算法)
|
||||||
|
- [5. 运势分析算法](#5-运势分析算法)
|
||||||
|
- [6. 辅助算法](#6-辅助算法)
|
||||||
|
- [7. 交叉验证结论](#7-交叉验证结论)
|
||||||
|
- [8. 代码库已知问题](#8-代码库已知问题)
|
||||||
|
- [9. 引用信源](#9-引用信源)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1. 概述
|
||||||
|
|
||||||
|
万事宜(Everything Is Suitable)是一款中国传统文化研究工具,核心业务覆盖三大领域:
|
||||||
|
|
||||||
|
| 领域 | 核心算法模块 | 代码文件 |
|
||||||
|
|------|-------------|---------|
|
||||||
|
| 紫微斗数 | 排盘引擎、星曜评分、三方四正 | `ziweiService.ts`, `ziweiAlgorithm.ts`, `sanFangSiZheng.ts` |
|
||||||
|
| 黄历 | 农历转换、每日宜忌、神煞 | `almanac.ts`, `calendar.ts`, `lunar.ts` |
|
||||||
|
| 运势分析 | 宫位运势、综合维度 | `fortuneStrategy.ts`, `fortune.ts`, `fortuneService.ts` |
|
||||||
|
|
||||||
|
**架构特性**:纯客户端执行(UniApp Vue3 + TypeScript),零网络依赖,LRU 缓存加速,完整的交叉验证测试体系。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2. 紫微斗数排盘算法
|
||||||
|
|
||||||
|
### 2.1 干支计算
|
||||||
|
|
||||||
|
**年干**:
|
||||||
|
```
|
||||||
|
年干索引 = ((year - 4) % 10 + 10) % 10 + 1
|
||||||
|
```
|
||||||
|
以 1984 年(甲子年)为基准,因 1984-4=1980 可被 60 整除。
|
||||||
|
|
||||||
|
**年支**:
|
||||||
|
```
|
||||||
|
年支索引 = ((year - 4) % 12 + 12) % 12 + 1
|
||||||
|
```
|
||||||
|
|
||||||
|
**月支映射**:正月寅(3)、二月卯(4)、三月辰(5)...十二月丑(2)
|
||||||
|
|
||||||
|
**时支映射**:每两小时一个时辰
|
||||||
|
| 时段 | 地支 |
|
||||||
|
|------|------|
|
||||||
|
| 23:00-00:59 | 子 |
|
||||||
|
| 01:00-02:59 | 丑 |
|
||||||
|
| 03:00-04:59 | 寅 |
|
||||||
|
| 05:00-06:59 | 卯 |
|
||||||
|
| 07:00-08:59 | 辰 |
|
||||||
|
| 09:00-10:59 | 巳 |
|
||||||
|
| 11:00-12:59 | 午 |
|
||||||
|
| 13:00-14:59 | 未 |
|
||||||
|
| 15:00-16:59 | 申 |
|
||||||
|
| 17:00-18:59 | 酉 |
|
||||||
|
| 19:00-20:59 | 戌 |
|
||||||
|
| 21:00-22:59 | 亥 |
|
||||||
|
|
||||||
|
### 2.2 命宫/身宫公式
|
||||||
|
|
||||||
|
**公式**(已验证 ✅ 与所有权威来源一致):
|
||||||
|
```
|
||||||
|
命宫索引 = 14 - 月支索引 - 时支索引
|
||||||
|
身宫索引 = 2 + 月支索引 + 时支索引
|
||||||
|
```
|
||||||
|
- 若结果 ≤0 则 +12,若 >12 则 -12
|
||||||
|
- 信源:算算123安星诀、starnum.com.tw、GitHub Fortel_xjs、feiyuntiegui.com
|
||||||
|
|
||||||
|
**传统口诀**:
|
||||||
|
- 命宫:"寅起正月,顺数至生月,逆数生时为命宫"
|
||||||
|
- 身宫:"寅起正月,顺数至生月,顺数生时为身宫"
|
||||||
|
|
||||||
|
### 2.3 十二宫安星
|
||||||
|
|
||||||
|
以命宫地支为起点,逆时针排列 12 宫:
|
||||||
|
```
|
||||||
|
命宫 → 兄弟 → 夫妻 → 子女 → 财帛 → 疾厄 → 迁移 → 交友 → 官禄 → 田宅 → 福德 → 父母
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 紫微星安星法(完整版)
|
||||||
|
|
||||||
|
**⚠️ 代码库当前为简化版,仅将紫微星定于命宫。完整公式如下:**
|
||||||
|
|
||||||
|
**口诀法**:
|
||||||
|
```
|
||||||
|
六五四三二,酉午亥辰丑,
|
||||||
|
局数除日数,商数宫前走;
|
||||||
|
若见数无余,便要起虎口,
|
||||||
|
日数小于局,还直宫中守。
|
||||||
|
```
|
||||||
|
|
||||||
|
**公式法**(推荐实现方式):
|
||||||
|
```
|
||||||
|
设: D = 农历日, M = 五行局数 (2/3/4/5/6)
|
||||||
|
求: 最小的 x (0 ≤ x < M),使 (D + x) 能被 M 整除
|
||||||
|
商数 y = (D + x) / M
|
||||||
|
若 x 为偶数 → 紫微宫 = 寅宫(索引3) + y(顺时针)
|
||||||
|
若 x 为奇数 → 紫微宫 = 寅宫(索引3) - y(逆时针)
|
||||||
|
若 x = 0(整除)→ 紫微宫 = 寅宫(索引3) + y - 1(从寅宫起算)
|
||||||
|
```
|
||||||
|
|
||||||
|
**五行局确定**:
|
||||||
|
```
|
||||||
|
根据命宫天干地支的纳音五行:
|
||||||
|
- 甲乙金四局(4)
|
||||||
|
- 丙丁水二局(2)
|
||||||
|
- 戊己火六局(6)
|
||||||
|
- 庚辛土五局(5)
|
||||||
|
- 壬癸木三局(3)
|
||||||
|
地支通过纳音表确定具体五行局
|
||||||
|
```
|
||||||
|
|
||||||
|
**示例**:
|
||||||
|
- 27日生、木三局:27÷3=9 整除 → 紫微在寅+9-1=戌宫
|
||||||
|
- 13日生、火六局:13+5=18÷6=3, x=5(奇数) → 紫微在寅-3=亥宫
|
||||||
|
- 6日生、土五局:6+4=10÷5=2, x=4(偶数) → 紫微在寅+2=辰宫
|
||||||
|
|
||||||
|
### 2.5 十四主星安星顺序
|
||||||
|
|
||||||
|
**紫微系**(逆时针排列):
|
||||||
|
```
|
||||||
|
紫微 → 天机(隔一宫)→ 太阳(隔一宫)→ 武曲 → 天同 → 廉贞(空二宫)
|
||||||
|
```
|
||||||
|
|
||||||
|
**天府系**(顺时针排列):
|
||||||
|
```
|
||||||
|
紫微定位后,天府在紫微的对宫(寅申相对、卯未相对...)
|
||||||
|
天府 → 太阴 → 贪狼 → 巨门 → 天相 → 天梁 → 七杀 → 破军(空三宫)
|
||||||
|
```
|
||||||
|
|
||||||
|
**公式**:
|
||||||
|
```
|
||||||
|
天府偏移 = (12 - (紫微宫索引 - 1)) % 12
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.6 四化飞星表
|
||||||
|
|
||||||
|
**⚠️ 代码库当前实现化禄/化权映射大部分错误,且缺少化科/化忌。以下为正确标准表。**
|
||||||
|
|
||||||
|
#### 主星派四化表(已验证 ✅ 推荐使用)
|
||||||
|
|
||||||
|
| 年干 | 化禄 | 化权 | 化科 | 化忌 |
|
||||||
|
|------|------|------|------|------|
|
||||||
|
| 甲 | 廉贞 | 破军 | 武曲 | 太阳 |
|
||||||
|
| 乙 | 天机 | 天梁 | 紫微 | 太阴 |
|
||||||
|
| 丙 | 天同 | 天机 | 文昌 | 廉贞 |
|
||||||
|
| 丁 | 太阴 | 天同 | 天机 | 巨门 |
|
||||||
|
| 戊 | 贪狼 | 太阴 | 太阳 | 天机 |
|
||||||
|
| 己 | 武曲 | 贪狼 | 天梁 | 文曲 |
|
||||||
|
| 庚 | 太阳 | 武曲 | 太阴 | 天同 |
|
||||||
|
| 辛 | 巨门 | 太阳 | 文曲 | 文昌 |
|
||||||
|
| 壬 | 天梁 | 紫微 | 天府 | 武曲 |
|
||||||
|
| 癸 | 破军 | 巨门 | 太阴 | 贪狼 |
|
||||||
|
|
||||||
|
**口诀**:甲廉破武阳,乙机梁紫阴,丙同机昌廉,丁阴同机巨,戊贪阴阳机,己武贪梁曲,庚阳武阴同,辛巨阳曲昌,壬梁紫府武,癸破巨阴贪。
|
||||||
|
|
||||||
|
#### 飞星派差异(仅戊年/壬年化科不同)
|
||||||
|
|
||||||
|
| 年干 | 化科 |
|
||||||
|
|------|------|
|
||||||
|
| 戊 | 右弼(非太阳) |
|
||||||
|
| 壬 | 左辅(非天府) |
|
||||||
|
|
||||||
|
**信源**:uranaischool.com 自力開運クラブ教材、starnum.com.tw、shen88.cn、feiyuntiegui.com
|
||||||
|
|
||||||
|
### 2.7 三方四正
|
||||||
|
|
||||||
|
**公式**(已验证 ✅):
|
||||||
|
```
|
||||||
|
财帛宫索引 = (命宫索引 + 5) % 12 // 逆时针第5宫
|
||||||
|
官禄宫索引 = (命宫索引 + 10) % 12 // 逆时针第10宫
|
||||||
|
迁移宫索引 = (命宫索引 + 6) % 12 // 对宫
|
||||||
|
```
|
||||||
|
|
||||||
|
- **三方**:命宫 + 财帛宫 + 官禄宫
|
||||||
|
- **四正**:命宫 + 财帛宫 + 官禄宫 + 迁移宫
|
||||||
|
|
||||||
|
### 2.8 星曜评分系统
|
||||||
|
|
||||||
|
**14 主星基础分**(自定义策略,非传统标准):
|
||||||
|
|
||||||
|
| 星曜 | 基础分 | 吉凶属性 |
|
||||||
|
|------|--------|---------|
|
||||||
|
| 紫微 | 85 | 吉 |
|
||||||
|
| 天机 | 75 | 吉 |
|
||||||
|
| 太阳 | 80 | 吉 |
|
||||||
|
| 武曲 | 75 | 凶 |
|
||||||
|
| 天同 | 70 | 吉 |
|
||||||
|
| 廉贞 | 55 | 凶 |
|
||||||
|
| 天府 | 85 | 吉 |
|
||||||
|
| 太阴 | 75 | 中和 |
|
||||||
|
| 贪狼 | 60 | 凶 |
|
||||||
|
| 巨门 | 55 | 凶 |
|
||||||
|
| 天相 | 75 | 吉 |
|
||||||
|
| 天梁 | 75 | 中和 |
|
||||||
|
| 七杀 | 60 | 凶 |
|
||||||
|
| 破军 | 55 | 凶 |
|
||||||
|
|
||||||
|
**四化修正**:化禄+15、化权+10、化科+8、化忌-15
|
||||||
|
|
||||||
|
**亮度修正**:`score = floor(baseScore × brightness / 100)`
|
||||||
|
|
||||||
|
**吉凶判定**:
|
||||||
|
```
|
||||||
|
≥90 → 大吉 ≥80 → 吉 ≥70 → 中吉 ≥60 → 平
|
||||||
|
≥50 → 中平 ≥40 → 小凶 <40 → 凶
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3. 黄历算法
|
||||||
|
|
||||||
|
### 3.1 公历→农历转换
|
||||||
|
|
||||||
|
**算法来源**:农历数据表(1900-2100 年编码表)
|
||||||
|
**信源**:腾讯云开发者、CSDN 微信小程序实现、GitHub LunarCore-Swift
|
||||||
|
|
||||||
|
**数据表编码**:
|
||||||
|
```
|
||||||
|
LUNAR_INFO[yearIndex] 为 16 位二进制编码:
|
||||||
|
- 高 4 位 (bit 19-16):闰月大小月(1=大月30天,0=小月29天)
|
||||||
|
- 中间 12 位 (bit 15-4):1-12 月大小月标记
|
||||||
|
- 低 4 位 (bit 3-0):闰月月份(0=无闰月)
|
||||||
|
```
|
||||||
|
|
||||||
|
**核心公式**:
|
||||||
|
```
|
||||||
|
offset = (公历日期 - 1900-01-31) 的天数差
|
||||||
|
lunarYear = 1900 + 累减 getLunarYearDays 直到 offset < 年总天数
|
||||||
|
lunarMonth = 逐月搜索,累减 getLunarMonthDays 直到 offset < 月总天数
|
||||||
|
lunarDay = offset + 1
|
||||||
|
```
|
||||||
|
|
||||||
|
**限制**:仅支持 1900-2100 年,2100 年后无数据覆盖。
|
||||||
|
|
||||||
|
### 3.2 建除十二神
|
||||||
|
|
||||||
|
**公式**(已验证 ✅):
|
||||||
|
```
|
||||||
|
jianChuIndex = (monthBranch + lunarDay - 1) % 12
|
||||||
|
```
|
||||||
|
- `monthBranch`:正月寅(3)、二月卯(4)...十二月丑(2)
|
||||||
|
- 结果映射到 12 神:建、除、满、平、定、执、破、危、成、收、开、闭
|
||||||
|
|
||||||
|
**信源**:搜狐姜群、fourpillars.pro
|
||||||
|
|
||||||
|
**宜忌查表**:每个建除神对应 6 项宜/忌活动,硬编码查表。
|
||||||
|
|
||||||
|
### 3.3 神煞系统
|
||||||
|
|
||||||
|
| 计算项 | 公式 | 验证 |
|
||||||
|
|--------|------|------|
|
||||||
|
| 日天干 | `(totalDays + 3) % 10` | ✅ |
|
||||||
|
| 日地支(公历) | `(totalDays + 1) % 12` | ✅ |
|
||||||
|
| 日地支(农历) | `(lunarDay + 2) % 12` | ✅ |
|
||||||
|
| 岁德神方向 | 天干 1-2→东北, 3-4→正西, 5-6→正北, 7-8→正东, 9-10→正南 | ✅ |
|
||||||
|
| 喜神方向 | 奇→正北, 偶→东北 | ✅ |
|
||||||
|
| 财神方向 | 1-2→正北, 5/7/8→西南, 6→正南, 9-10→东南 | ✅ |
|
||||||
|
| 六冲 | 子午冲、丑未冲、寅申冲、卯酉冲、辰戌冲、巳亥冲 | ✅ 双向对称性验证 |
|
||||||
|
| 煞方 | 南东北西循环 | ✅ |
|
||||||
|
| 十二星神 | 青龙、明堂、天刑、朱雀、金匮、天德、白虎、玉堂、天牢、玄武、司命、勾陈 | ✅ |
|
||||||
|
| 胎神 | 12 日周期查表 | ✅ |
|
||||||
|
| 纳音五行 | 见下节 | ✅ |
|
||||||
|
|
||||||
|
### 3.4 六十甲子纳音
|
||||||
|
|
||||||
|
**数据**:30 组硬编码查表,与百度百科、释玄斋等权威来源完全一致。
|
||||||
|
|
||||||
|
**速算公式**(可用于验证):
|
||||||
|
```
|
||||||
|
天干取数:甲乙=1, 丙丁=2, 戊己=3, 庚辛=4, 壬癸=5
|
||||||
|
地支取数:子丑午未=1, 寅卯申酉=2, 辰巳戌亥=3
|
||||||
|
纳音五行 = (天干数 + 地支数) % 5
|
||||||
|
→ 1=木, 2=金, 3=水, 4=火, 5=土
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.5 彭祖百忌
|
||||||
|
|
||||||
|
**数据**:10 条天干禁忌 + 12 条地支禁忌,共 22 条。
|
||||||
|
**信源**:百度百科彭祖百忌
|
||||||
|
|
||||||
|
天干百忌示例:
|
||||||
|
```
|
||||||
|
甲不开仓财物耗散 乙不纳植千株不长
|
||||||
|
丙不修灶必见灾殃 丁不剃头头必生疮
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
地支百忌示例:
|
||||||
|
```
|
||||||
|
子不问卜自惹祸殃 丑不冠带主不还乡
|
||||||
|
寅不祭祀神鬼不尝 卯不穿井水泉不香
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.6 节气与节日
|
||||||
|
|
||||||
|
**节气**:近似公式 `dayAdjust = (year % 4 + floor(year/100) - 20) % 3`
|
||||||
|
|
||||||
|
**节日**:19 个公历节日 + 9 个农历节日(春节、元宵、端午、七夕、中元、中秋、重阳、腊八、除夕)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. 真太阳时算法
|
||||||
|
|
||||||
|
### 4.1 公式
|
||||||
|
|
||||||
|
```
|
||||||
|
真太阳时 = 平太阳时 + 经度修正 + 时差方程修正
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.2 经度修正
|
||||||
|
|
||||||
|
```
|
||||||
|
经度修正 = (本地经度 - 时区中央经度) × 4 分钟
|
||||||
|
中国标准时间 (UTC+8) 中央经线 = 120°E
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.3 时差方程(Spencer 1971)
|
||||||
|
|
||||||
|
```
|
||||||
|
γ = 2π/365 × (dayOfYear - 1 + (hour - 12) / 24)
|
||||||
|
|
||||||
|
EoT = 229.2 × (
|
||||||
|
0.0000075 + // 注意:非 0.000075(已知勘误)
|
||||||
|
+ 0.001868 × cos(γ)
|
||||||
|
- 0.032077 × sin(γ)
|
||||||
|
- 0.014615 × cos(2γ)
|
||||||
|
- 0.040849 × sin(2γ) // 注意:非 0.04089(已知勘误)
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4.4 已知勘误
|
||||||
|
|
||||||
|
| 系数 | 代码库当前值 | 正确值 | 影响 |
|
||||||
|
|------|------------|--------|------|
|
||||||
|
| 常数项 c0 | 0.000075 | 0.0000075 | 约 0.017 分钟,可忽略 |
|
||||||
|
| sin(2γ) 系数 | 0.04089 | 0.040849 | 约 0.000041,可忽略 |
|
||||||
|
|
||||||
|
**信源**:
|
||||||
|
- Spencer (1971) "Fourier series representation of the position of the sun"
|
||||||
|
- pvlib-python 官方文档(Spencer 本人确认的勘误)
|
||||||
|
- pvlib GitHub Issue #847
|
||||||
|
|
||||||
|
**结论**:两个勘误对紫微斗数排盘结果无实质影响(误差 < 0.02 分钟),但建议更新为正确值以保持学术严谨性。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5. 运势分析算法
|
||||||
|
|
||||||
|
### 5.1 宫位运势策略
|
||||||
|
|
||||||
|
**策略模式**:分层设计,日/月/年三级调整。
|
||||||
|
|
||||||
|
**日运势调整**:
|
||||||
|
```
|
||||||
|
每日调整值 = Σ(四化修正 + 吉凶星月相修正)
|
||||||
|
四化修正:化禄→日%3==0:+5 else:+2
|
||||||
|
化权→日%7==0:+5 else:+2
|
||||||
|
化科→日%5==0:+3 else:+1
|
||||||
|
化忌→日%4==0:-8 else:-3
|
||||||
|
吉星修正:1/4/7/10月:+3 else:+1
|
||||||
|
凶星修正:2/5/8/11月:-3 else:-1
|
||||||
|
```
|
||||||
|
|
||||||
|
**月/年运势调整**:类似日调整,但基准值不同。
|
||||||
|
|
||||||
|
### 5.2 综合运势维度
|
||||||
|
|
||||||
|
| 维度 | 关联宫位 | 关键星曜 | 加分规则 |
|
||||||
|
|------|----------|----------|----------|
|
||||||
|
| 感情 | 夫妻宫 | 红鸾、天喜、贪狼 | 每颗桃花星+5分 |
|
||||||
|
| 学业 | 官禄宫 | 文昌、文曲 | 每颗+6分 |
|
||||||
|
| 社交 | 兄弟宫 | 左辅、右弼、天魁、天钺 | 每颗贵人星+5分 |
|
||||||
|
| 出行 | 迁移宫 | 天马 | 每颗+5分 |
|
||||||
|
|
||||||
|
**注意**:运势评分策略为自定义算法,非传统命理标准,无需与传统权威比对。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6. 辅助算法
|
||||||
|
|
||||||
|
### 6.1 LRU 缓存
|
||||||
|
|
||||||
|
- 紫微盘:50 个缓存条目
|
||||||
|
- 缓存键:`${birthTime}_${gender}_${timezone}`
|
||||||
|
|
||||||
|
### 6.2 持久化
|
||||||
|
|
||||||
|
- 使用 `uni.getStorageSync/setStorageSync`
|
||||||
|
- 存储内容:用户出生信息 + 排盘结果
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7. 交叉验证结论
|
||||||
|
|
||||||
|
### 评分矩阵
|
||||||
|
|
||||||
|
| 算法模块 | 一致性 | 可信度 | 说明 |
|
||||||
|
|---------|--------|--------|------|
|
||||||
|
| 命宫/身宫公式 | ✅ | 高 | 三源独立验证一致 |
|
||||||
|
| 十二宫安星 | ✅ | 高 | 传统逆时针排列 |
|
||||||
|
| 紫微星安星法(完整版) | ✅ | 高 | 五行局+农历日公式 |
|
||||||
|
| 四化飞星表(主星派) | ✅ | 高 | 三源验证一致 |
|
||||||
|
| 建除十二神 | ✅ | 高 | 公式与查表均正确 |
|
||||||
|
| 六十甲子纳音 | ✅ | 高 | 30组完整、正确 |
|
||||||
|
| 农历转换 | ✅ | 高 | 行业标准数据表 |
|
||||||
|
| 真太阳时 (Spencer) | ✅ | 高 | 两个勘误已确认 |
|
||||||
|
| 三方四正 | ✅ | 高 | 公式正确 |
|
||||||
|
| 彭祖百忌 | ✅ | 高 | 内容完整正确 |
|
||||||
|
| 紫微星安星法(当前实现) | ⚠️ | 低 | 简化版,非完整公式 |
|
||||||
|
| 四化飞星表(当前代码) | ❌ | 低 | 映射大部分错误 |
|
||||||
|
|
||||||
|
### 信源分布
|
||||||
|
|
||||||
|
```
|
||||||
|
信源层级分布:
|
||||||
|
├── 第一信源(权威文献/官方文档/行业标准)— 10 个
|
||||||
|
│ ├── Spencer (1971) 原始论文
|
||||||
|
│ ├── pvlib-python 官方文档 (NOAA)
|
||||||
|
│ ├── uranaischool.com 紫微斗数教材
|
||||||
|
│ ├── starnum.com.tw 紫微斗数教学
|
||||||
|
│ ├── 百度百科(六十甲子纳音、彭祖百忌)
|
||||||
|
│ ├── feiyuntiegui.com 安星诀
|
||||||
|
│ ├── shen88.cn 四化星
|
||||||
|
│ ├── 搜狐/姜群 建除十二神
|
||||||
|
│ ├── fourpillars.pro 建除十二神
|
||||||
|
│ └── 腾讯云开发者 农历数据表
|
||||||
|
│
|
||||||
|
├── 第二信源(开源实现/社区验证)— 6 个
|
||||||
|
│ ├── GitHub Fortel_xjs (Go 安星诀)
|
||||||
|
│ ├── GitHub LunarCore-Swift (农历天文算法)
|
||||||
|
│ ├── CSDN 微信小程序 (农历数据表)
|
||||||
|
│ ├── zhanbugua.com 手工排盘教程
|
||||||
|
│ ├── ziweiyun.com 在线排盘
|
||||||
|
│ └── m.dushu.com 四化详解
|
||||||
|
│
|
||||||
|
└── 实证测试(交叉验证测试套件)— 2 个
|
||||||
|
├── almanac-cross-validation.test.ts (12 维度)
|
||||||
|
└── ziwei-cross-validation.test.ts (5 组数据)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 8. 代码库已知问题
|
||||||
|
|
||||||
|
### 问题 1:四化飞星映射错误(严重)
|
||||||
|
|
||||||
|
**位置**:`ziweiService.ts` 第 215-231 行
|
||||||
|
|
||||||
|
**现状**:
|
||||||
|
- 仅实现了化禄 (`luMap`) 和化权 (`quanMap`),缺少化科、化忌
|
||||||
|
- 化禄映射:10 项中仅 4 项正确(乙、庚、辛、壬正确,其余 6 项错误)
|
||||||
|
- 化权映射:10 项中仅 1 项正确(乙正确,其余 9 项错误)
|
||||||
|
|
||||||
|
**建议修复**:按主星派四化表完整实现 4 化映射。
|
||||||
|
|
||||||
|
### 问题 2:紫微星安星法不完整(中等)
|
||||||
|
|
||||||
|
**位置**:`ziweiService.ts` 第 183-184 行
|
||||||
|
|
||||||
|
**现状**:紫微星始终定于命宫(`palaceOffset === 0`)
|
||||||
|
|
||||||
|
**建议修复**:按完整公式(五行局+农历日)实现紫微星定位。
|
||||||
|
|
||||||
|
### 问题 3:真太阳时公式系数(轻微)
|
||||||
|
|
||||||
|
**位置**:`solarTime.ts` 第 109-115 行
|
||||||
|
|
||||||
|
**现状**:使用 0.000075 和 0.04089(已知勘误值)
|
||||||
|
|
||||||
|
**建议修复**:更新为 0.0000075 和 0.040849,并添加勘误注释说明。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 9. 引用信源
|
||||||
|
|
||||||
|
### 9.1 紫微斗数
|
||||||
|
|
||||||
|
| 信源 | 类型 | URL |
|
||||||
|
|------|------|-----|
|
||||||
|
| 算算123 安星诀 | 在线教学 | https://www.suansuan123.com/base-lib/12%20%E7%B4%AB%E5%BE%AE%E6%96%97%E6%95%B0%E5%AE%89%E6%98%9F%E8%AF%80 |
|
||||||
|
| starnum.com.tw 四化指南 | 在线教学 | https://starnum.com.tw/blog/zh-TW/zwds-basics-sihua-pillar |
|
||||||
|
| uranaischool.com 四化表 | 教材 PDF | https://uranaischool.com/wp-content/uploads/2020/05/自力開運用-運気の見方ー十干配置と四化星表.pdf |
|
||||||
|
| feiyuntiegui.com 安星诀 | 技术博客 | http://feiyuntiegui.com/?id=2525 |
|
||||||
|
| shen88.cn 四化星 | 在线教学 | https://services.shen88.cn/ziweidoushu/sihuaxing.html |
|
||||||
|
| Fortel_xjs (Go) | 开源实现 | https://github.com/hustxjs/Fortel_xjs |
|
||||||
|
| 大德山人 紫微斗数精成 | 教材 | https://m.doc88.com/p-506830740853.html |
|
||||||
|
| zhanbugua.com 手工排盘 | 在线教学 | https://zhanbugua.com/wen/9f1f0b332c8919ac.html |
|
||||||
|
| ziweiyun.com 在线排盘 | 在线工具 | https://www.ziweiyun.com/ |
|
||||||
|
|
||||||
|
### 9.2 黄历/农历
|
||||||
|
|
||||||
|
| 信源 | 类型 | URL |
|
||||||
|
|------|------|-----|
|
||||||
|
| 腾讯云开发者 农历转换 | 技术博客 | https://cloud.tencent.cn/developer/article/2704217 |
|
||||||
|
| CSDN 农历数据表 | 技术博客 | https://blog.csdn.net/weixin_52803316/article/details/130250288 |
|
||||||
|
| GitHub LunarCore-Swift | 开源实现 | https://github.com/babywbx/LunarCore-Swift |
|
||||||
|
| 搜狐/姜群 建除十二神 | 技术博客 | https://www.sohu.com/a/905466581_99946359 |
|
||||||
|
| fourpillars.pro 建除十二神 | 英文教程 | https://fourpillars.pro/articles/46 |
|
||||||
|
| 百度百科 六十甲子纳音 | 百科 | https://m.baike.com/wiki/六十甲子纳音 |
|
||||||
|
| 释玄斋 纳音速算 | 技术博客 | https://m.fjzyi.com/h-nd-3311.html |
|
||||||
|
| 百度百科 彭祖百忌 | 百科 | https://m.baike.com/wiki/彭祖百忌 |
|
||||||
|
| shen88.cn 三方四正 | 在线教学 | https://services.shen88.cn/ziweidoushu/sanfang.html |
|
||||||
|
|
||||||
|
### 9.3 真太阳时
|
||||||
|
|
||||||
|
| 信源 | 类型 | URL |
|
||||||
|
|------|------|-----|
|
||||||
|
| pvlib solarposition 源码 | 官方文档 | https://pvlib-python.readthedocs.io/en/stable/_modules/pvlib/solarposition.html |
|
||||||
|
| pvlib 时差方程文档 | 官方文档 | https://pvlib-python.readthedocs.io/en/v0.11.2/reference/generated/pvlib.solarposition.equation_of_time_spencer71.html |
|
||||||
|
| pvlib Issue #847 勘误 | GitHub Issue | https://github.com/pvlib/pvlib-python/issues/847 |
|
||||||
|
| Spencer (1971) 原始论文 | 学术论文 | "Fourier Series Representation of the Position of the Sun" Search 2(5), p.172 |
|
||||||
|
| Duffie & Beckman 教材 | 学术教材 | "Solar Engineering of Thermal Processes" 3rd Ed., pp.9-11 |
|
||||||
|
| NOAA 太阳位置计算器 | 官方工具 | https://www.esrl.noaa.gov/gmd/grad/solcalc/ |
|
||||||
@@ -97,8 +97,13 @@ function getDayOfYear(date: Date): number {
|
|||||||
* 计算时差方程(分钟)
|
* 计算时差方程(分钟)
|
||||||
*
|
*
|
||||||
* 基于 Spencer (1971) 傅里叶级数近似:
|
* 基于 Spencer (1971) 傅里叶级数近似:
|
||||||
* EoT = 229.2 × (0.000075 + 0.001868×cos(γ) - 0.032077×sin(γ)
|
* EoT = 229.2 × (0.0000075 + 0.001868×cos(γ) - 0.032077×sin(γ)
|
||||||
* - 0.014615×cos(2γ) - 0.04089×sin(2γ))
|
* - 0.014615×cos(2γ) - 0.040849×sin(2γ))
|
||||||
|
*
|
||||||
|
* 注意:原始 Spencer (1971) 论文有两个已知勘误:
|
||||||
|
* 1. 常数项 0.000075 → 应为 0.0000075(Spencer 本人确认)
|
||||||
|
* 2. sin(2γ) 系数 0.04089 → 应为 0.040849(Bird Clear Sky 模型值)
|
||||||
|
* 参考:pvlib-python 官方文档 equation_of_time_spencer71
|
||||||
*
|
*
|
||||||
* 其中 γ = 2π/365 × (N - 1 + (t - 12) / 24),N 为一年中的第几天
|
* 其中 γ = 2π/365 × (N - 1 + (t - 12) / 24),N 为一年中的第几天
|
||||||
*
|
*
|
||||||
@@ -106,12 +111,16 @@ function getDayOfYear(date: Date): number {
|
|||||||
*/
|
*/
|
||||||
function calculateEquationOfTime(fractionalYear: number): number {
|
function calculateEquationOfTime(fractionalYear: number): number {
|
||||||
const coeff = 229.2
|
const coeff = 229.2
|
||||||
|
// 修正值说明:Spencer (1971) 原始论文有两个已知勘误
|
||||||
|
// 1. 常数项: 0.000075 → 0.0000075(Spencer 本人确认的排版错误)
|
||||||
|
// 2. sin(2γ) 系数: 0.04089 → 0.040849(Bird Clear Sky 模型值)
|
||||||
|
// 参考: pvlib-python equation_of_time_spencer71
|
||||||
const eot = coeff * (
|
const eot = coeff * (
|
||||||
0.000075 +
|
0.0000075 +
|
||||||
0.001868 * Math.cos(fractionalYear) -
|
0.001868 * Math.cos(fractionalYear) -
|
||||||
0.032077 * Math.sin(fractionalYear) -
|
0.032077 * Math.sin(fractionalYear) -
|
||||||
0.014615 * Math.cos(2 * fractionalYear) -
|
0.014615 * Math.cos(2 * fractionalYear) -
|
||||||
0.04089 * Math.sin(2 * fractionalYear)
|
0.040849 * Math.sin(2 * fractionalYear)
|
||||||
)
|
)
|
||||||
return eot
|
return eot
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ import { HeavenlyStem, EarthlyBranch, PalaceType, MajorStar, StarNature } from '
|
|||||||
import { calculatePalaceScore } from '../algorithms/ziweiAlgorithm'
|
import { calculatePalaceScore } from '../algorithms/ziweiAlgorithm'
|
||||||
import { calculateSanFangSiZheng } from '../algorithms/sanFangSiZheng'
|
import { calculateSanFangSiZheng } from '../algorithms/sanFangSiZheng'
|
||||||
import { calculateTrueSolarTime } from '../algorithms/solarTime'
|
import { calculateTrueSolarTime } from '../algorithms/solarTime'
|
||||||
|
import { solarToLunar } from '../utils/lunar'
|
||||||
import { LRUCache } from '../utils/lruCache'
|
import { LRUCache } from '../utils/lruCache'
|
||||||
import { storage, STORAGE_KEYS } from '../utils/storage'
|
import { storage, STORAGE_KEYS } from '../utils/storage'
|
||||||
|
|
||||||
@@ -57,26 +58,6 @@ const MONTH_BRANCHES: EarthlyBranch[] = [
|
|||||||
EarthlyBranch.CHOU,
|
EarthlyBranch.CHOU,
|
||||||
]
|
]
|
||||||
|
|
||||||
const MAJOR_STAR_SEQUENCE: MajorStar[] = [
|
|
||||||
MajorStar.ZIWEI,
|
|
||||||
MajorStar.TIANJI,
|
|
||||||
MajorStar.TAIYANG,
|
|
||||||
MajorStar.WUQU,
|
|
||||||
MajorStar.TIANTONG,
|
|
||||||
MajorStar.LIANCHEN,
|
|
||||||
]
|
|
||||||
|
|
||||||
const MAJOR_STAR_SEQUENCE2: MajorStar[] = [
|
|
||||||
MajorStar.TIANFU,
|
|
||||||
MajorStar.TAIYIN,
|
|
||||||
MajorStar.TANLANG,
|
|
||||||
MajorStar.JUMEN,
|
|
||||||
MajorStar.TIANXIANG,
|
|
||||||
MajorStar.TIANLIANG,
|
|
||||||
MajorStar.QISHA,
|
|
||||||
MajorStar.POJUN,
|
|
||||||
]
|
|
||||||
|
|
||||||
export class ZiweiService {
|
export class ZiweiService {
|
||||||
private cache = new LRUCache<ZiweiChart>({ maxSize: 50 })
|
private cache = new LRUCache<ZiweiChart>({ maxSize: 50 })
|
||||||
|
|
||||||
@@ -110,6 +91,9 @@ export class ZiweiService {
|
|||||||
trueSolarTime = `${datePart}T${solarResult.trueSolarTime}`
|
trueSolarTime = `${datePart}T${solarResult.trueSolarTime}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 计算农历日期(用于紫微星安星法)
|
||||||
|
const lunarDate = solarToLunar(birthDate)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
birthTime: params.birthTime,
|
birthTime: params.birthTime,
|
||||||
yearStem,
|
yearStem,
|
||||||
@@ -126,6 +110,7 @@ export class ZiweiService {
|
|||||||
latitude: params.latitude,
|
latitude: params.latitude,
|
||||||
birthPlace: params.birthPlace,
|
birthPlace: params.birthPlace,
|
||||||
trueSolarTime,
|
trueSolarTime,
|
||||||
|
lunarDate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,13 +137,64 @@ export class ZiweiService {
|
|||||||
const mingGongIndex = EarthlyBranch.index(mingGongBranch)
|
const mingGongIndex = EarthlyBranch.index(mingGongBranch)
|
||||||
const mingBranchArrayIndex = branches.indexOf(mingGongBranch)
|
const mingBranchArrayIndex = branches.indexOf(mingGongBranch)
|
||||||
|
|
||||||
|
// 计算紫微星位置(完整安星法)
|
||||||
|
const ziweiBranchIndex = this.calculateZiweiBranchIndex(birthInfo, mingGongBranch)
|
||||||
|
const tianfuBranchIndex = 13 - ziweiBranchIndex // 天府在紫微对宫
|
||||||
|
|
||||||
|
// 计算紫微系星曜位置(逆时针排列)
|
||||||
|
const ziwiXiPositions: Record<number, MajorStar> = {}
|
||||||
|
ziwiXiPositions[ziweiBranchIndex] = MajorStar.ZIWEI
|
||||||
|
// 天机隔一宫(逆时针2位)
|
||||||
|
const tianjiPos = ((ziweiBranchIndex - 2 + 12) % 12) || 12
|
||||||
|
ziwiXiPositions[tianjiPos] = MajorStar.TIANJI
|
||||||
|
// 太阳再隔一宫(逆时针4位)
|
||||||
|
const taiyangPos = ((ziweiBranchIndex - 4 + 12) % 12) || 12
|
||||||
|
ziwiXiPositions[taiyangPos] = MajorStar.TAIYANG
|
||||||
|
// 武曲(逆时针5位)
|
||||||
|
const wuquPos = ((ziweiBranchIndex - 5 + 12) % 12) || 12
|
||||||
|
ziwiXiPositions[wuquPos] = MajorStar.WUQU
|
||||||
|
// 天同(逆时针6位)
|
||||||
|
const tiantongPos = ((ziweiBranchIndex - 6 + 12) % 12) || 12
|
||||||
|
ziwiXiPositions[tiantongPos] = MajorStar.TIANTONG
|
||||||
|
// 廉贞空二宫(逆时针8位)
|
||||||
|
const lianchenPos = ((ziweiBranchIndex - 8 + 12) % 12) || 12
|
||||||
|
ziwiXiPositions[lianchenPos] = MajorStar.LIANCHEN
|
||||||
|
|
||||||
|
// 计算天府系星曜位置(顺时针排列)
|
||||||
|
const tianfuXiPositions: Record<number, MajorStar> = {}
|
||||||
|
tianfuXiPositions[tianfuBranchIndex] = MajorStar.TIANFU
|
||||||
|
// 天府系顺时针:太阴(+1)、贪狼(+2)、巨门(+3)、天相(+4)、天梁(+5)、七杀(+6)、破军空三宫(+8)
|
||||||
|
const tianfuSequence = [
|
||||||
|
MajorStar.TAIYIN, MajorStar.TANLANG, MajorStar.JUMEN,
|
||||||
|
MajorStar.TIANXIANG, MajorStar.TIANLIANG, MajorStar.QISHA,
|
||||||
|
]
|
||||||
|
for (let i = 0; i < tianfuSequence.length; i++) {
|
||||||
|
const pos = ((tianfuBranchIndex + (i + 1) - 1) % 12) + 1
|
||||||
|
tianfuXiPositions[pos] = tianfuSequence[i]
|
||||||
|
}
|
||||||
|
// 破军空三宫(顺时针+8)
|
||||||
|
const pojunPos = ((tianfuBranchIndex + 8 - 1) % 12) + 1
|
||||||
|
tianfuXiPositions[pojunPos] = MajorStar.POJUN
|
||||||
|
|
||||||
const palaces: Palace[] = []
|
const palaces: Palace[] = []
|
||||||
for (let i = 0; i < 12; i++) {
|
for (let i = 0; i < 12; i++) {
|
||||||
const branchArrayIndex = (mingBranchArrayIndex + i) % 12
|
const branchArrayIndex = (mingBranchArrayIndex + i) % 12
|
||||||
const earthlyBranch = branches[branchArrayIndex]
|
const earthlyBranch = branches[branchArrayIndex]
|
||||||
const palaceType = palaceTypes[i] ?? PalaceType.MING
|
const palaceType = palaceTypes[i] ?? PalaceType.MING
|
||||||
|
const branchIndex = EarthlyBranch.index(earthlyBranch)
|
||||||
|
|
||||||
const majorStars = this.assignStarsToPalace(i, mingGongIndex, birthInfo)
|
// 收集当前宫位的星曜
|
||||||
|
const majorStars: StarInfo[] = []
|
||||||
|
const yearStemIndex = HeavenlyStem.index(birthInfo.yearStem)
|
||||||
|
|
||||||
|
// 紫微系星曜
|
||||||
|
if (ziwiXiPositions[branchIndex]) {
|
||||||
|
majorStars.push(this.createStarInfo(ziwiXiPositions[branchIndex], yearStemIndex))
|
||||||
|
}
|
||||||
|
// 天府系星曜
|
||||||
|
if (tianfuXiPositions[branchIndex]) {
|
||||||
|
majorStars.push(this.createStarInfo(tianfuXiPositions[branchIndex], yearStemIndex))
|
||||||
|
}
|
||||||
|
|
||||||
const palace: Palace = {
|
const palace: Palace = {
|
||||||
palaceType,
|
palaceType,
|
||||||
@@ -176,29 +212,98 @@ export class ZiweiService {
|
|||||||
return palaces
|
return palaces
|
||||||
}
|
}
|
||||||
|
|
||||||
private assignStarsToPalace(palaceOffset: number, mingGongIndex: number, birthInfo: BirthInfo): StarInfo[] {
|
/**
|
||||||
const stars: StarInfo[] = []
|
* 计算紫微星所在的地支索引(1-12)
|
||||||
const yearStemIndex = HeavenlyStem.index(birthInfo.yearStem)
|
*
|
||||||
|
* 紫微星安星法(完整公式):
|
||||||
if (palaceOffset === 0) {
|
* 公式:(农历日 + x) / 五行局 = y (整除)
|
||||||
stars.push(this.createStarInfo(MajorStar.ZIWEI, yearStemIndex))
|
* - x=0(整除) → 紫微宫 = 寅宫(3) + y - 1
|
||||||
} else if (palaceOffset <= 5) {
|
* - x为偶数 → 紫微宫 = 寅宫(3) + y
|
||||||
stars.push(this.createStarInfo(MAJOR_STAR_SEQUENCE[palaceOffset], yearStemIndex))
|
* - x为奇数 → 紫微宫 = 寅宫(3) - y
|
||||||
|
*
|
||||||
|
* 信源:feiyuntiegui.com 安星诀、zhanbugua.com 手工排盘教程
|
||||||
|
*/
|
||||||
|
private calculateZiweiBranchIndex(birthInfo: BirthInfo, mingGongBranch: EarthlyBranch): number {
|
||||||
|
// 1. 获取农历日
|
||||||
|
let lunarDay = 15 // 默认值
|
||||||
|
if (birthInfo.lunarDate?.lunarDay) {
|
||||||
|
lunarDay = parseInt(birthInfo.lunarDate.lunarDay, 10) || 15
|
||||||
}
|
}
|
||||||
|
|
||||||
const fuOffset = (12 - (mingGongIndex - 1)) % 12
|
// 2. 计算五行局
|
||||||
if (palaceOffset === fuOffset) {
|
const mingGongBranchIndex = EarthlyBranch.index(mingGongBranch)
|
||||||
stars.push(this.createStarInfo(MajorStar.TIANFU, yearStemIndex))
|
const mingGongStemIndex = this.calculateMingGongStem(
|
||||||
|
HeavenlyStem.index(birthInfo.yearStem),
|
||||||
|
mingGongBranchIndex,
|
||||||
|
)
|
||||||
|
const fiveBureau = this.calculateFiveBureau(mingGongStemIndex, mingGongBranchIndex)
|
||||||
|
|
||||||
|
// 3. 紫微星安星公式
|
||||||
|
let x = 0
|
||||||
|
while ((lunarDay + x) % fiveBureau !== 0) {
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
const y = (lunarDay + x) / fiveBureau
|
||||||
|
|
||||||
|
let ziweiIndex: number
|
||||||
|
if (x === 0) {
|
||||||
|
// 整除:寅宫(3) + y - 1
|
||||||
|
ziweiIndex = 3 + y - 1
|
||||||
|
} else if (x % 2 === 0) {
|
||||||
|
// x为偶数:寅宫(3) + y
|
||||||
|
ziweiIndex = 3 + y
|
||||||
|
} else {
|
||||||
|
// x为奇数:寅宫(3) - y
|
||||||
|
ziweiIndex = 3 - y
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < MAJOR_STAR_SEQUENCE2.length; i++) {
|
// 调整到1-12范围
|
||||||
const targetOffset = (fuOffset + i) % 12
|
while (ziweiIndex <= 0) ziweiIndex += 12
|
||||||
if (palaceOffset === targetOffset && palaceOffset !== fuOffset) {
|
while (ziweiIndex > 12) ziweiIndex -= 12
|
||||||
stars.push(this.createStarInfo(MAJOR_STAR_SEQUENCE2[i], yearStemIndex))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stars
|
return ziweiIndex
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算命宫天干索引(五虎遁)
|
||||||
|
*
|
||||||
|
* 五虎遁口诀:
|
||||||
|
* 甲己之年丙作首,乙庚之岁戊为头,
|
||||||
|
* 丙辛之年寻庚上,丁壬壬寅顺水流,
|
||||||
|
* 若问戊癸何处起,甲寅之上好追求。
|
||||||
|
*/
|
||||||
|
private calculateMingGongStem(yearStemIndex: number, mingGongBranchIndex: number): number {
|
||||||
|
// 寅宫天干 = ((yearStemIndex - 1) * 2 + 3) % 10
|
||||||
|
let yinStem = ((yearStemIndex - 1) * 2 + 3) % 10
|
||||||
|
if (yinStem === 0) yinStem = 10
|
||||||
|
// 命宫天干 = (寅宫天干 + (mingGongBranchIndex - 3)) % 10
|
||||||
|
let mingStem = (yinStem + (mingGongBranchIndex - 3)) % 10
|
||||||
|
if (mingStem <= 0) mingStem += 10
|
||||||
|
return mingStem
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算五行局数
|
||||||
|
*
|
||||||
|
* 纳音五行 → 五行局映射:
|
||||||
|
* 木(1)→木三局(3), 金(2)→金四局(4), 水(3)→水二局(2),
|
||||||
|
* 火(4)→火六局(6), 土(5)→土五局(5)
|
||||||
|
*/
|
||||||
|
private calculateFiveBureau(stemIndex: number, branchIndex: number): number {
|
||||||
|
// 纳音五行速算:天干取数甲乙=1,丙丁=2,戊己=3,庚辛=4,壬癸=5
|
||||||
|
const stemNum = Math.ceil(stemIndex / 2)
|
||||||
|
// 地支取数:子丑午未=1, 寅卯申酉=2, 辰巳戌亥=3
|
||||||
|
const branchNumMap: Record<number, number> = {
|
||||||
|
1: 1, 2: 1, 3: 2, 4: 2, 5: 3, 6: 3,
|
||||||
|
7: 1, 8: 1, 9: 2, 10: 2, 11: 3, 12: 3,
|
||||||
|
}
|
||||||
|
const branchNum = branchNumMap[branchIndex] ?? 1
|
||||||
|
// 纳音五行 = (天干数 + 地支数) % 5 → 1木2金3水4火5土
|
||||||
|
let nayinElement = (stemNum + branchNum) % 5
|
||||||
|
if (nayinElement === 0) nayinElement = 5
|
||||||
|
// 五行局映射:1木→3, 2金→4, 3水→2, 4火→6, 5土→5
|
||||||
|
const bureauMap: Record<number, number> = { 1: 3, 2: 4, 3: 2, 4: 6, 5: 5 }
|
||||||
|
return bureauMap[nayinElement] ?? 5
|
||||||
}
|
}
|
||||||
|
|
||||||
private createStarInfo(star: MajorStar, yearStemIndex: number): StarInfo {
|
private createStarInfo(star: MajorStar, yearStemIndex: number): StarInfo {
|
||||||
@@ -211,22 +316,42 @@ export class ZiweiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private getTransformation(star: MajorStar, yearStemIndex: number): StarInfo['transformation'] {
|
/**
|
||||||
const luMap: Record<number, MajorStar> = {
|
* 获取四化飞星(主星派标准表)
|
||||||
1: MajorStar.POJUN, 2: MajorStar.TIANJI, 3: MajorStar.TAIYANG,
|
*
|
||||||
4: MajorStar.WUQU, 5: MajorStar.LIANCHEN, 6: MajorStar.TIANFU,
|
* 信源:uranaischool.com 自力開運クラブ教材、starnum.com.tw、shen88.cn
|
||||||
7: MajorStar.TAIYANG, 8: MajorStar.JUMEN, 9: MajorStar.TIANLIANG,
|
* 口诀:甲廉破武阳,乙机梁紫阴,丙同机昌廉,丁阴同机巨,
|
||||||
10: MajorStar.ZIWEI,
|
* 戊贪阴阳机,己武贪梁曲,庚阳武阴同,辛巨阳曲昌,
|
||||||
}
|
* 壬梁紫府武,癸破巨阴贪。
|
||||||
const quanMap: Record<number, MajorStar> = {
|
*
|
||||||
1: MajorStar.TIANLIANG, 2: MajorStar.TIANLIANG, 3: MajorStar.WUQU,
|
* 年干索引:1=甲, 2=乙, 3=丙, 4=丁, 5=戊, 6=己, 7=庚, 8=辛, 9=壬, 10=癸
|
||||||
4: MajorStar.ZIWEI, 5: MajorStar.POJUN, 6: MajorStar.TIANXIANG,
|
*/
|
||||||
7: MajorStar.TIANJI, 8: MajorStar.TANLANG, 9: MajorStar.QISHA,
|
private static readonly TRANSFORMATION_TABLE: Record<number, {
|
||||||
10: MajorStar.LIANCHEN,
|
lu: MajorStar
|
||||||
}
|
quan: MajorStar
|
||||||
|
ke: MajorStar
|
||||||
|
ji: MajorStar
|
||||||
|
}> = {
|
||||||
|
1: { lu: MajorStar.LIANCHEN, quan: MajorStar.POJUN, ke: MajorStar.WUQU, ji: MajorStar.TAIYANG },
|
||||||
|
2: { lu: MajorStar.TIANJI, quan: MajorStar.TIANLIANG, ke: MajorStar.ZIWEI, ji: MajorStar.TAIYIN },
|
||||||
|
3: { lu: MajorStar.TIANTONG, quan: MajorStar.TIANJI, ke: MajorStar.WENCHANG, ji: MajorStar.LIANCHEN },
|
||||||
|
4: { lu: MajorStar.TAIYIN, quan: MajorStar.TIANTONG, ke: MajorStar.TIANJI, ji: MajorStar.JUMEN },
|
||||||
|
5: { lu: MajorStar.TANLANG, quan: MajorStar.TAIYIN, ke: MajorStar.TAIYANG, ji: MajorStar.TIANJI },
|
||||||
|
6: { lu: MajorStar.WUQU, quan: MajorStar.TANLANG, ke: MajorStar.TIANLIANG, ji: MajorStar.WENQU },
|
||||||
|
7: { lu: MajorStar.TAIYANG, quan: MajorStar.WUQU, ke: MajorStar.TAIYIN, ji: MajorStar.TIANTONG },
|
||||||
|
8: { lu: MajorStar.JUMEN, quan: MajorStar.TAIYANG, ke: MajorStar.WENQU, ji: MajorStar.WENCHANG },
|
||||||
|
9: { lu: MajorStar.TIANLIANG, quan: MajorStar.ZIWEI, ke: MajorStar.TIANFU, ji: MajorStar.WUQU },
|
||||||
|
10: { lu: MajorStar.POJUN, quan: MajorStar.JUMEN, ke: MajorStar.TAIYIN, ji: MajorStar.TANLANG },
|
||||||
|
}
|
||||||
|
|
||||||
if (luMap[yearStemIndex] === star) return 'LU' as any
|
private getTransformation(star: MajorStar, yearStemIndex: number): StarInfo['transformation'] {
|
||||||
if (quanMap[yearStemIndex] === star) return 'QUAN' as any
|
const entry = ZiweiService.TRANSFORMATION_TABLE[yearStemIndex]
|
||||||
|
if (!entry) return null
|
||||||
|
|
||||||
|
if (entry.lu === star) return 'LU' as any
|
||||||
|
if (entry.quan === star) return 'QUAN' as any
|
||||||
|
if (entry.ke === star) return 'KE' as any
|
||||||
|
if (entry.ji === star) return 'JI' as any
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user