fatebridge 0.1.0__py3-none-any.whl

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.
Files changed (241) hide show
  1. fatebridge/__init__.py +25 -0
  2. fatebridge/analysis/__init__.py +1 -0
  3. fatebridge/analysis/career.py +606 -0
  4. fatebridge/analysis/children.py +286 -0
  5. fatebridge/analysis/compatibility.py +1024 -0
  6. fatebridge/analysis/education.py +297 -0
  7. fatebridge/analysis/health.py +318 -0
  8. fatebridge/analysis/life_dimensions.py +202 -0
  9. fatebridge/analysis/marriage.py +784 -0
  10. fatebridge/analysis/personality.py +184 -0
  11. fatebridge/analysis/relatives.py +151 -0
  12. fatebridge/analysis/romance.py +252 -0
  13. fatebridge/analysis/timing_effects.py +754 -0
  14. fatebridge/analysis/wealth.py +413 -0
  15. fatebridge/api.py +678 -0
  16. fatebridge/application/__init__.py +1 -0
  17. fatebridge/application/bindings.py +219 -0
  18. fatebridge/application/description.py +186 -0
  19. fatebridge/application/discovery.py +159 -0
  20. fatebridge/application/examples.py +40 -0
  21. fatebridge/application/execution.py +166 -0
  22. fatebridge/application/projection.py +101 -0
  23. fatebridge/application/result_delivery.py +499 -0
  24. fatebridge/application/scenarios.py +157 -0
  25. fatebridge/application/tool_spec.py +72 -0
  26. fatebridge/cli.py +1115 -0
  27. fatebridge/core/__init__.py +1 -0
  28. fatebridge/core/almanac.py +712 -0
  29. fatebridge/core/astro/__init__.py +1 -0
  30. fatebridge/core/astro/aspects.py +320 -0
  31. fatebridge/core/astro/birth.py +89 -0
  32. fatebridge/core/astro/chart.py +323 -0
  33. fatebridge/core/astro/classical.py +347 -0
  34. fatebridge/core/astro/ephemeris.py +179 -0
  35. fatebridge/core/astro/geometry.py +200 -0
  36. fatebridge/core/astro/layout.py +102 -0
  37. fatebridge/core/astro/orbits.py +195 -0
  38. fatebridge/core/astro/parts.py +183 -0
  39. fatebridge/core/astro/profiles.py +262 -0
  40. fatebridge/core/astro/reference.py +408 -0
  41. fatebridge/core/astro/relationship.py +423 -0
  42. fatebridge/core/astro/relationship_charts.py +525 -0
  43. fatebridge/core/astro/runtime.py +36 -0
  44. fatebridge/core/astrology_election.py +420 -0
  45. fatebridge/core/astrology_events.py +221 -0
  46. fatebridge/core/astrology_horary.py +535 -0
  47. fatebridge/core/astrology_lifespan.py +1282 -0
  48. fatebridge/core/astrology_tables.py +197 -0
  49. fatebridge/core/calendar.py +307 -0
  50. fatebridge/core/canping.py +370 -0
  51. fatebridge/core/classical.py +388 -0
  52. fatebridge/core/classical_western.py +1204 -0
  53. fatebridge/core/divination.py +867 -0
  54. fatebridge/core/element_relations.py +320 -0
  55. fatebridge/core/elements.py +340 -0
  56. fatebridge/core/ephemeris_runtime.py +139 -0
  57. fatebridge/core/execution_context.py +105 -0
  58. fatebridge/core/export_contracts.py +405 -0
  59. fatebridge/core/export_parser.py +197 -0
  60. fatebridge/core/fengshui/__init__.py +1 -0
  61. fatebridge/core/fengshui/actions.py +145 -0
  62. fatebridge/core/fengshui/annual.py +80 -0
  63. fatebridge/core/fengshui/bazhai.py +240 -0
  64. fatebridge/core/fengshui/calendar.py +116 -0
  65. fatebridge/core/fengshui/context.py +445 -0
  66. fatebridge/core/fengshui/context_inputs.py +512 -0
  67. fatebridge/core/fengshui/directions.py +68 -0
  68. fatebridge/core/fengshui/interior_inputs.py +137 -0
  69. fatebridge/core/fengshui/interior_rules.py +234 -0
  70. fatebridge/core/fengshui/jinsuo.py +56 -0
  71. fatebridge/core/fengshui/layout.py +789 -0
  72. fatebridge/core/fengshui/layout_inputs.py +148 -0
  73. fatebridge/core/fengshui/layout_supplements.py +483 -0
  74. fatebridge/core/fengshui/material_application.py +128 -0
  75. fatebridge/core/fengshui/material_inputs.py +112 -0
  76. fatebridge/core/fengshui/materials.py +242 -0
  77. fatebridge/core/fengshui/method_details.py +179 -0
  78. fatebridge/core/fengshui/method_policy.py +446 -0
  79. fatebridge/core/fengshui/models.py +1261 -0
  80. fatebridge/core/fengshui/natal_interpretation.py +316 -0
  81. fatebridge/core/fengshui/output.py +317 -0
  82. fatebridge/core/fengshui/planning.py +473 -0
  83. fatebridge/core/fengshui/snapshot.py +316 -0
  84. fatebridge/core/fengshui/surface.py +387 -0
  85. fatebridge/core/fengshui/surface_inputs.py +124 -0
  86. fatebridge/core/fengshui/workstation.py +374 -0
  87. fatebridge/core/fengshui/workstation_inputs.py +160 -0
  88. fatebridge/core/fengshui/workstation_sources.py +42 -0
  89. fatebridge/core/fengshui/xuankong.py +275 -0
  90. fatebridge/core/gua_meanings.py +666 -0
  91. fatebridge/core/guolao_moira.py +499 -0
  92. fatebridge/core/heluo.py +789 -0
  93. fatebridge/core/knowledge_store.py +699 -0
  94. fatebridge/core/local_techniques/__init__.py +1 -0
  95. fatebridge/core/local_techniques/canping.py +120 -0
  96. fatebridge/core/local_techniques/chart.py +773 -0
  97. fatebridge/core/local_techniques/heluo.py +111 -0
  98. fatebridge/core/local_techniques/otherbu.py +340 -0
  99. fatebridge/core/local_techniques/qimen.py +268 -0
  100. fatebridge/core/local_techniques/sanshi.py +369 -0
  101. fatebridge/core/local_techniques/sixyao.py +796 -0
  102. fatebridge/core/local_techniques/suzhan.py +149 -0
  103. fatebridge/core/local_techniques/tongshefa.py +188 -0
  104. fatebridge/core/metaphysics/__init__.py +5 -0
  105. fatebridge/core/metaphysics/common.py +275 -0
  106. fatebridge/core/metaphysics/jinkou.py +227 -0
  107. fatebridge/core/metaphysics/liureng.py +367 -0
  108. fatebridge/core/metaphysics/liureng_transmissions.py +205 -0
  109. fatebridge/core/metaphysics/qimen.py +1005 -0
  110. fatebridge/core/metaphysics/taiyi.py +876 -0
  111. fatebridge/core/metaphysics/ziwei.py +853 -0
  112. fatebridge/core/output_base.py +15 -0
  113. fatebridge/core/output_bazi.py +446 -0
  114. fatebridge/core/output_charts.py +432 -0
  115. fatebridge/core/output_chinese.py +722 -0
  116. fatebridge/core/output_reference.py +166 -0
  117. fatebridge/core/output_western.py +732 -0
  118. fatebridge/core/predictive/__init__.py +1 -0
  119. fatebridge/core/predictive/_common.py +652 -0
  120. fatebridge/core/predictive/decennials.py +604 -0
  121. fatebridge/core/predictive/firdaria.py +109 -0
  122. fatebridge/core/predictive/primary_directions.py +1340 -0
  123. fatebridge/core/predictive/profections.py +209 -0
  124. fatebridge/core/predictive/progressions.py +58 -0
  125. fatebridge/core/predictive/returns.py +118 -0
  126. fatebridge/core/predictive/solar_arc.py +45 -0
  127. fatebridge/core/predictive/transit.py +84 -0
  128. fatebridge/core/predictive/western_timing.py +603 -0
  129. fatebridge/core/predictive/zodiacal_releasing.py +318 -0
  130. fatebridge/core/reproducibility.py +79 -0
  131. fatebridge/core/requests/__init__.py +1 -0
  132. fatebridge/core/requests/astrology.py +220 -0
  133. fatebridge/core/requests/base.py +50 -0
  134. fatebridge/core/requests/bazi.py +86 -0
  135. fatebridge/core/requests/birth.py +73 -0
  136. fatebridge/core/requests/calendar.py +62 -0
  137. fatebridge/core/requests/compatibility.py +128 -0
  138. fatebridge/core/requests/divination.py +272 -0
  139. fatebridge/core/requests/metaphysics.py +175 -0
  140. fatebridge/core/requests/reference.py +88 -0
  141. fatebridge/core/requests/timing.py +136 -0
  142. fatebridge/core/requests/western_events.py +170 -0
  143. fatebridge/core/requests/western_lifespan.py +236 -0
  144. fatebridge/core/requests/western_timing.py +93 -0
  145. fatebridge/core/response_models.py +439 -0
  146. fatebridge/core/rules.py +1753 -0
  147. fatebridge/core/schema_cache.py +105 -0
  148. fatebridge/core/sukuyo.py +134 -0
  149. fatebridge/core/timing.py +971 -0
  150. fatebridge/core/ziwei_tables.py +81 -0
  151. fatebridge/data/agent_examples.json +515 -0
  152. fatebridge/data/agent_scenarios.json +1996 -0
  153. fatebridge/data/canping/__init__.py +0 -0
  154. fatebridge/data/canping/canpingTiaowen.json +1 -0
  155. fatebridge/data/fengshui/desktop-bagua-v1.json +70 -0
  156. fatebridge/data/fengshui/expert-methods-v1.json +157 -0
  157. fatebridge/data/fengshui/expert-policy-v1.json +73 -0
  158. fatebridge/data/fengshui/interior-relations-v1.json +372 -0
  159. fatebridge/data/fengshui/layout-supplements-v1.json +313 -0
  160. fatebridge/data/fengshui/material-representations-v1.json +119 -0
  161. fatebridge/data/fengshui/method-reference-supplement-v1.json +957 -0
  162. fatebridge/data/fengshui/natal-interpretation-v1.json +158 -0
  163. fatebridge/data/fengshui/rules-v1.json +303 -0
  164. fatebridge/data/fengshui/workstation-authored-v1.json +380 -0
  165. fatebridge/data/fengshui/xuankong-v1.json +328 -0
  166. fatebridge/data/heluo/__init__.py +0 -0
  167. fatebridge/data/heluo/heluoTiaowen.json +3266 -0
  168. fatebridge/data/knowledge/__init__.py +3 -0
  169. fatebridge/data/knowledge/astro.json +678 -0
  170. fatebridge/data/knowledge/bazi.json +825 -0
  171. fatebridge/data/knowledge/index.json +361 -0
  172. fatebridge/data/knowledge/liureng.json +590 -0
  173. fatebridge/data/knowledge/qimen.json +2481 -0
  174. fatebridge/diagnostics.py +171 -0
  175. fatebridge/fetch_ephe.py +147 -0
  176. fatebridge/mcp_server.py +187 -0
  177. fatebridge/mcp_transport.py +184 -0
  178. fatebridge/py.typed +0 -0
  179. fatebridge/services/astrology.py +1174 -0
  180. fatebridge/services/bazi.py +1121 -0
  181. fatebridge/services/birth_context.py +58 -0
  182. fatebridge/services/birth_payload.py +100 -0
  183. fatebridge/services/calculation.py +13 -0
  184. fatebridge/services/calendar_input.py +64 -0
  185. fatebridge/services/calendar_tools.py +267 -0
  186. fatebridge/services/catalog/__init__.py +1 -0
  187. fatebridge/services/catalog/astro_bindings.py +94 -0
  188. fatebridge/services/catalog/astrology.py +136 -0
  189. fatebridge/services/catalog/bazi.py +155 -0
  190. fatebridge/services/catalog/compatibility.py +28 -0
  191. fatebridge/services/catalog/divination.py +215 -0
  192. fatebridge/services/catalog/fengshui.py +79 -0
  193. fatebridge/services/catalog/metaphysics.py +161 -0
  194. fatebridge/services/catalog/reference.py +77 -0
  195. fatebridge/services/catalog/timing.py +166 -0
  196. fatebridge/services/catalog/western_events.py +75 -0
  197. fatebridge/services/catalog/western_lifespan.py +184 -0
  198. fatebridge/services/catalog/western_timing.py +114 -0
  199. fatebridge/services/compatibility.py +144 -0
  200. fatebridge/services/divination.py +644 -0
  201. fatebridge/services/export_tools.py +43 -0
  202. fatebridge/services/fengshui.py +461 -0
  203. fatebridge/services/knowledge.py +223 -0
  204. fatebridge/services/metaphysics.py +1050 -0
  205. fatebridge/services/replay_metadata.py +224 -0
  206. fatebridge/services/run_metadata.py +140 -0
  207. fatebridge/services/snapshot_builders.py +69 -0
  208. fatebridge/services/structured_snapshot.py +192 -0
  209. fatebridge/services/timing.py +821 -0
  210. fatebridge/services/timing_snapshots.py +600 -0
  211. fatebridge/services/timing_state.py +323 -0
  212. fatebridge/services/tool_catalog.py +65 -0
  213. fatebridge/services/western_election.py +108 -0
  214. fatebridge/services/western_events.py +253 -0
  215. fatebridge/services/western_horary.py +115 -0
  216. fatebridge/services/western_lifespan.py +1081 -0
  217. fatebridge/services/western_timing.py +157 -0
  218. fatebridge/services/western_timing_tools.py +430 -0
  219. fatebridge/transports/__init__.py +1 -0
  220. fatebridge/transports/flags.py +26 -0
  221. fatebridge/transports/mcp.py +299 -0
  222. fatebridge/transports/rest.py +236 -0
  223. fatebridge/utils/__init__.py +1 -0
  224. fatebridge/utils/analysis_clock.py +29 -0
  225. fatebridge/utils/birth_input.py +176 -0
  226. fatebridge/utils/data.py +687 -0
  227. fatebridge/utils/elements.py +77 -0
  228. fatebridge/utils/errors.py +204 -0
  229. fatebridge/utils/formatting.py +95 -0
  230. fatebridge/utils/house_systems.py +210 -0
  231. fatebridge/utils/places.py +578 -0
  232. fatebridge/utils/runtime.py +114 -0
  233. fatebridge/utils/solar_time.py +258 -0
  234. fatebridge/utils/timezones.py +51 -0
  235. fatebridge-0.1.0.dist-info/METADATA +158 -0
  236. fatebridge-0.1.0.dist-info/RECORD +241 -0
  237. fatebridge-0.1.0.dist-info/WHEEL +5 -0
  238. fatebridge-0.1.0.dist-info/entry_points.txt +4 -0
  239. fatebridge-0.1.0.dist-info/licenses/LICENSE +201 -0
  240. fatebridge-0.1.0.dist-info/licenses/NOTICE +42 -0
  241. fatebridge-0.1.0.dist-info/top_level.txt +1 -0
fatebridge/__init__.py ADDED
@@ -0,0 +1,25 @@
1
+ """
2
+ FateBridge - Fortune Telling System
3
+
4
+ A backend-only Python toolkit bridging Chinese metaphysics, divination and
5
+ offline Western astrology. The same domain capabilities are exposed through
6
+ three interfaces (FastAPI REST, FastMCP, and the ``fatebridge`` CLI), all
7
+ derived from a single central tool catalog
8
+ (``fatebridge.services.tool_catalog``).
9
+
10
+ See the docs/ directory for the full algorithm coverage matrix and the
11
+ developer / Agent integration guide.
12
+
13
+ Public API
14
+ ----------
15
+ FateBridge is consumed through its three transports rather than as a library of
16
+ importable functions. The programmatic entry point is the central tool catalog
17
+ ``fatebridge.services.tool_catalog`` (every REST route, MCP tool and CLI
18
+ subcommand is derived from it). This top-level module intentionally exposes only
19
+ metadata; deeper capabilities live under ``fatebridge.services`` / ``.core``.
20
+ """
21
+
22
+ __version__ = "0.1.0"
23
+ __author__ = "thomas-yanxin"
24
+
25
+ __all__ = ["__version__", "__author__"]
@@ -0,0 +1 @@
1
+ """FateBridge analysis modules."""
@@ -0,0 +1,606 @@
1
+ """
2
+ 事业分析模块
3
+
4
+ 基于八字命理的事业分析功能,综合以下经典技法:
5
+ - 十神看事业类型与方向
6
+ - 五行看行业选择
7
+ - 格局看事业高度
8
+ - 大运流年看事业时机
9
+
10
+ 核心分析维度:
11
+ 1. 事业类型与适合行业
12
+ 2. 事业格局与高度
13
+ 3. 事业时机(大运/流年)
14
+ 4. 创业 vs 打工倾向
15
+ 5. 贵人与小人
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ from typing import Any, Dict, List, Optional, Tuple
21
+
22
+ from ..utils.data import (
23
+ STEM_ELEMENTS,
24
+ Element,
25
+ TenGod,
26
+ count_element_distribution,
27
+ count_ten_gods,
28
+ get_ten_god,
29
+ iter_pillar_gods,
30
+ )
31
+
32
+ # 五行对应行业
33
+ ELEMENT_INDUSTRIES = {
34
+ Element.WOOD: {
35
+ "label": "木",
36
+ "industries": [
37
+ "教育培训",
38
+ "文化出版",
39
+ "园林绿化",
40
+ "家具木材",
41
+ "纺织服装",
42
+ "医药健康",
43
+ "农业种植",
44
+ "环保生态",
45
+ "设计创意",
46
+ "宗教哲学",
47
+ ],
48
+ "direction": "东方",
49
+ "season": "春季",
50
+ },
51
+ Element.FIRE: {
52
+ "label": "火",
53
+ "industries": [
54
+ "互联网科技",
55
+ "电子电器",
56
+ "能源电力",
57
+ "餐饮娱乐",
58
+ "传媒广告",
59
+ "美容化妆",
60
+ "照明光学",
61
+ "冶炼铸造",
62
+ "心理咨询",
63
+ "演艺娱乐",
64
+ ],
65
+ "direction": "南方",
66
+ "season": "夏季",
67
+ },
68
+ Element.EARTH: {
69
+ "label": "土",
70
+ "industries": [
71
+ "房地产建筑",
72
+ "农业畜牧",
73
+ "矿业资源",
74
+ "仓储物流",
75
+ "陶瓷建材",
76
+ "殡葬服务",
77
+ "宗教场所",
78
+ "人力资源",
79
+ "会计审计",
80
+ "仓储管理",
81
+ ],
82
+ "direction": "中央",
83
+ "season": "四季月(辰戌丑未月)",
84
+ },
85
+ Element.METAL: {
86
+ "label": "金",
87
+ "industries": [
88
+ "金融银行",
89
+ "法律司法",
90
+ "机械制造",
91
+ "汽车交通",
92
+ "珠宝首饰",
93
+ "医疗器械",
94
+ "军事国防",
95
+ "体育竞技",
96
+ "IT硬件",
97
+ "精密仪器",
98
+ ],
99
+ "direction": "西方",
100
+ "season": "秋季",
101
+ },
102
+ Element.WATER: {
103
+ "label": "水",
104
+ "industries": [
105
+ "贸易流通",
106
+ "物流运输",
107
+ "旅游酒店",
108
+ "水产渔业",
109
+ "饮料酒业",
110
+ "水利水务",
111
+ "航海航空",
112
+ "媒体传播",
113
+ "咨询顾问",
114
+ "外交公关",
115
+ ],
116
+ "direction": "北方",
117
+ "season": "冬季",
118
+ },
119
+ }
120
+
121
+ # 十神对应事业特征
122
+ TEN_GOD_CAREER = {
123
+ TenGod.COMPARE: {
124
+ "label": "比肩",
125
+ "career_type": "独立经营",
126
+ "traits": "自主性强、竞争意识强、适合独立创业或合伙经营",
127
+ "suitable": ["创业", "合伙经营", "自由职业", "体育竞技"],
128
+ },
129
+ TenGod.ROB_WEALTH: {
130
+ "label": "劫财",
131
+ "career_type": "竞争型",
132
+ "traits": "行动力强、敢于冒险、适合高竞争行业",
133
+ "suitable": ["销售", "市场营销", "投机行业", "体育"],
134
+ },
135
+ TenGod.FOOD_GOD: {
136
+ "label": "食神",
137
+ "career_type": "才华型",
138
+ "traits": "才华横溢、创意丰富、适合文化产业",
139
+ "suitable": ["艺术创作", "餐饮美食", "教育培训", "文化出版"],
140
+ },
141
+ TenGod.HURT_OFFICER: {
142
+ "label": "伤官",
143
+ "career_type": "创新型",
144
+ "traits": "思维独特、不拘常规、适合创新领域",
145
+ "suitable": ["技术研发", "设计创意", "自媒体", "律师"],
146
+ },
147
+ TenGod.POSITIVE_WEALTH: {
148
+ "label": "正财",
149
+ "career_type": "稳健型",
150
+ "traits": "踏实稳健、理财能力强、适合传统行业",
151
+ "suitable": ["财务管理", "银行金融", "会计审计", "实业经营"],
152
+ },
153
+ TenGod.PARTIAL_WEALTH: {
154
+ "label": "偏财",
155
+ "career_type": "投资型",
156
+ "traits": "眼光独到、善于把握机会、适合投资领域",
157
+ "suitable": ["投资理财", "股票期货", "贸易经商", "地产"],
158
+ },
159
+ TenGod.POSITIVE_OFFICER: {
160
+ "label": "正官",
161
+ "career_type": "管理型",
162
+ "traits": "有领导力、守规矩、适合体制内或大企业管理",
163
+ "suitable": ["公务员", "企业管理", "行政管理", "法律"],
164
+ },
165
+ TenGod.SEVEN_KILLER: {
166
+ "label": "七杀",
167
+ "career_type": "权威型",
168
+ "traits": "果断有魄力、适合高压环境",
169
+ "suitable": ["军警", "外科医生", "高管", "创业"],
170
+ },
171
+ TenGod.POSITIVE_SEAL: {
172
+ "label": "正印",
173
+ "career_type": "学术型",
174
+ "traits": "好学上进、有文化底蕴、适合学术教育",
175
+ "suitable": ["教师", "研究员", "公务员", "文化行业"],
176
+ },
177
+ TenGod.PARTIAL_SEAL: {
178
+ "label": "偏印",
179
+ "career_type": "技术型",
180
+ "traits": "思维敏捷、专业技能强、适合技术领域",
181
+ "suitable": ["技术研发", "医疗", "玄学", "IT"],
182
+ },
183
+ }
184
+
185
+
186
+ class CareerAnalysis:
187
+ """事业分析工具类"""
188
+
189
+ @staticmethod
190
+ def analyze_career(
191
+ pillars: Dict[str, Tuple[str, str]],
192
+ gender: Optional[str] = None,
193
+ dayun_pillar: Optional[Tuple[str, str]] = None,
194
+ liunian_pillar: Optional[Tuple[str, str]] = None,
195
+ ) -> Dict[str, Any]:
196
+ """
197
+ 综合事业分析。
198
+
199
+ Args:
200
+ pillars: 四柱
201
+ gender: 性别
202
+ dayun_pillar: 当前大运柱 (可选)
203
+ liunian_pillar: 当前流年柱 (可选)
204
+
205
+ Returns:
206
+ 事业分析结果字典
207
+ """
208
+ day_stem = pillars["day"][0]
209
+ day_element = STEM_ELEMENTS[day_stem][0]
210
+
211
+ # 1. 主导十神分析
212
+ dominant_god_analysis = CareerAnalysis._analyze_dominant_ten_gods(
213
+ pillars, day_stem
214
+ )
215
+
216
+ # 2. 适合行业分析
217
+ industry_analysis = CareerAnalysis._analyze_industries(
218
+ pillars, day_stem, day_element
219
+ )
220
+
221
+ # 3. 事业格局
222
+ career_structure = CareerAnalysis._analyze_career_structure(pillars, day_stem)
223
+
224
+ # 4. 创业 vs 打工倾向
225
+ entrepreneurship = CareerAnalysis._analyze_entrepreneurship(pillars, day_stem)
226
+
227
+ # 5. 事业时机
228
+ career_timing = CareerAnalysis._analyze_career_timing(
229
+ pillars, day_stem, dayun_pillar, liunian_pillar
230
+ )
231
+
232
+ # 6. 贵人方位
233
+ noble_direction = CareerAnalysis._analyze_noble_direction(pillars, day_element)
234
+
235
+ # 7. 综合建议
236
+ suggestions = CareerAnalysis._generate_suggestions(
237
+ dominant_god_analysis, industry_analysis, career_structure, entrepreneurship
238
+ )
239
+
240
+ return {
241
+ "interpretation_scope": (
242
+ "个人命盘的传统事业规则分析;不测量实际能力、收入或创业成功概率,"
243
+ "不能据此决定辞职、投资或创业。"
244
+ ),
245
+ "dominant_ten_gods": dominant_god_analysis,
246
+ "industry_analysis": industry_analysis,
247
+ "career_structure": career_structure,
248
+ "entrepreneurship": entrepreneurship,
249
+ "career_timing": career_timing,
250
+ "noble_direction": noble_direction,
251
+ "suggestions": suggestions,
252
+ }
253
+
254
+ @staticmethod
255
+ def _analyze_dominant_ten_gods(
256
+ pillars: Dict[str, Tuple[str, str]],
257
+ day_stem: str,
258
+ ) -> Dict[str, Any]:
259
+ """分析命局中主导的十神,确定事业类型。"""
260
+ # career 跳过整个日柱(连日支藏干也不计)
261
+ god_counts = count_ten_gods(pillars, day_stem, skip_day_pillar=True)
262
+
263
+ # 排序取前三
264
+ sorted_gods = sorted(god_counts.items(), key=lambda x: x[1], reverse=True)
265
+ top_gods = [(god, count) for god, count in sorted_gods if count > 0][:3]
266
+
267
+ career_profiles = []
268
+ for god, count in top_gods:
269
+ profile = TEN_GOD_CAREER.get(god, {})
270
+ career_profiles.append(
271
+ {
272
+ "ten_god": god.value,
273
+ "weight": round(count, 1),
274
+ "career_type": profile.get("career_type", "综合型"),
275
+ "traits": profile.get("traits", ""),
276
+ "suitable_roles": profile.get("suitable", []),
277
+ }
278
+ )
279
+
280
+ return {
281
+ "top_gods": career_profiles,
282
+ "primary_career_type": (
283
+ career_profiles[0]["career_type"] if career_profiles else "综合型"
284
+ ),
285
+ }
286
+
287
+ @staticmethod
288
+ def _analyze_industries(
289
+ pillars: Dict[str, Tuple[str, str]],
290
+ day_stem: str,
291
+ day_element: Element,
292
+ ) -> Dict[str, Any]:
293
+ """分析适合的行业方向。"""
294
+ # 统计命局五行分布
295
+ element_counts = count_element_distribution(pillars)
296
+
297
+ # 喜用神五行
298
+ from ..core.elements import ElementAnalysis
299
+
300
+ day_master_analysis = ElementAnalysis.analyze_day_master_strength(pillars)
301
+ favorable = ElementAnalysis.get_favorable_elements(day_master_analysis)
302
+
303
+ # 推荐行业基于喜用神
304
+ recommended_industries: List[Dict[str, Any]] = []
305
+ for elem in favorable:
306
+ info = ELEMENT_INDUSTRIES.get(elem)
307
+ if info:
308
+ recommended_industries.append(
309
+ {
310
+ "element": info["label"],
311
+ "industries": info["industries"],
312
+ "direction": info["direction"],
313
+ "reason": f"喜用神为{info['label']},适合{info['label']}相关行业",
314
+ }
315
+ )
316
+
317
+ # 忌神行业
318
+ avoid_elements = [e for e in Element if e not in favorable]
319
+ avoid_industries: List[Dict[str, Any]] = []
320
+ for elem in avoid_elements:
321
+ info = ELEMENT_INDUSTRIES.get(elem)
322
+ if info:
323
+ avoid_industries.append(
324
+ {
325
+ "element": info["label"],
326
+ "industries": info["industries"][:3],
327
+ "reason": f"忌神为{info['label']},{info['label']}行业需谨慎",
328
+ }
329
+ )
330
+
331
+ return {
332
+ "favorable_elements": [e.value for e in favorable],
333
+ "recommended_industries": recommended_industries,
334
+ "avoid_industries": avoid_industries,
335
+ "element_distribution": {
336
+ e.value: round(c, 1) for e, c in element_counts.items()
337
+ },
338
+ }
339
+
340
+ @staticmethod
341
+ def _analyze_career_structure(
342
+ pillars: Dict[str, Tuple[str, str]],
343
+ day_stem: str,
344
+ ) -> Dict[str, Any]:
345
+ """分析事业格局高低。"""
346
+ score = 60 # 基准分
347
+ notes: List[str] = []
348
+
349
+ # 1. 官印相生 is one positive contribution, not the overall grade.
350
+ has_officer = False
351
+ has_seal = False
352
+ for e in iter_pillar_gods(pillars, day_stem, skip_day_pillar=True):
353
+ if e.ten_god in (TenGod.POSITIVE_OFFICER, TenGod.SEVEN_KILLER):
354
+ has_officer = True
355
+ if e.ten_god in (TenGod.POSITIVE_SEAL, TenGod.PARTIAL_SEAL):
356
+ has_seal = True
357
+
358
+ if has_officer and has_seal:
359
+ score += 15
360
+ notes.append("官印相生,为事业格局加分;总体层级以综合评分为准")
361
+
362
+ # 2. 食伤生财 → 经商格局
363
+ has_food_hurt = False
364
+ has_wealth = False
365
+ for p_name, (stem, branch) in pillars.items():
366
+ if p_name == "day":
367
+ continue
368
+ god = get_ten_god(day_stem, stem)
369
+ if god in (TenGod.FOOD_GOD, TenGod.HURT_OFFICER):
370
+ has_food_hurt = True
371
+ if god in (TenGod.POSITIVE_WEALTH, TenGod.PARTIAL_WEALTH):
372
+ has_wealth = True
373
+
374
+ if has_food_hurt and has_wealth:
375
+ score += 10
376
+ notes.append("食伤生财,传统规则关联经商与技术表达,不据此预测收入")
377
+
378
+ # 3. 财官双美
379
+ if has_officer and has_wealth:
380
+ score += 8
381
+ notes.append("财官双美,为事业格局的传统加分项,不代表现实名利结果")
382
+
383
+ # 4. 日主强弱影响
384
+ from ..core.elements import ElementAnalysis
385
+
386
+ dm_analysis = ElementAnalysis.analyze_day_master_strength(pillars)
387
+ strength = dm_analysis["strength_level"]
388
+ if strength == "强":
389
+ score += 5
390
+ notes.append("日主强旺,按本规则提高事业格局评分,不等于实际承压能力")
391
+ elif strength == "弱":
392
+ score -= 5
393
+ notes.append("日主偏弱,按本规则降低事业格局评分,不据此判断个人能力")
394
+
395
+ score = max(30, min(95, score))
396
+
397
+ if score >= 85:
398
+ level = "上等格局"
399
+ elif score >= 70:
400
+ level = "中等格局"
401
+ elif score >= 55:
402
+ level = "普通格局"
403
+ else:
404
+ level = "需努力突破"
405
+
406
+ return {
407
+ "score": score,
408
+ "score_kind": "traditional_rule_index",
409
+ "scope": "individual_natal_career_structure",
410
+ "score_basis": (
411
+ "以60为基准,按官印、食伤与财、财官及日主强弱规则加减,"
412
+ "限制在30–95;不是事业成就或收入概率。"
413
+ ),
414
+ "level": level,
415
+ "notes": notes,
416
+ }
417
+
418
+ @staticmethod
419
+ def _analyze_entrepreneurship(
420
+ pillars: Dict[str, Tuple[str, str]],
421
+ day_stem: str,
422
+ ) -> Dict[str, Any]:
423
+ """分析创业 vs 打工倾向。"""
424
+ entrepreneur_score = 50
425
+ notes: List[str] = []
426
+
427
+ # 统计十神
428
+ god_counts: Dict[str, float] = {}
429
+ for e in iter_pillar_gods(pillars, day_stem, skip_day_pillar=True):
430
+ key = e.ten_god.value
431
+ god_counts[key] = god_counts.get(key, 0) + e.weight
432
+
433
+ # 偏星多 → 创业倾向
434
+ partial_stars = sum(
435
+ god_counts.get(g, 0)
436
+ for g in [
437
+ TenGod.ROB_WEALTH.value,
438
+ TenGod.HURT_OFFICER.value,
439
+ TenGod.PARTIAL_WEALTH.value,
440
+ TenGod.SEVEN_KILLER.value,
441
+ TenGod.PARTIAL_SEAL.value,
442
+ ]
443
+ )
444
+ normal_stars = sum(
445
+ god_counts.get(g, 0)
446
+ for g in [
447
+ TenGod.COMPARE.value,
448
+ TenGod.FOOD_GOD.value,
449
+ TenGod.POSITIVE_WEALTH.value,
450
+ TenGod.POSITIVE_OFFICER.value,
451
+ TenGod.POSITIVE_SEAL.value,
452
+ ]
453
+ )
454
+
455
+ if partial_stars > normal_stars:
456
+ entrepreneur_score += 15
457
+ notes.append("偏星为主,传统规则提高自主经营倾向评分")
458
+ elif normal_stars > partial_stars:
459
+ entrepreneur_score -= 10
460
+ notes.append("正星为主,传统规则偏向稳定工作倾向")
461
+
462
+ # 七杀有制 → 领导型创业者
463
+ if god_counts.get(TenGod.SEVEN_KILLER.value, 0) > 0:
464
+ if god_counts.get(TenGod.FOOD_GOD.value, 0) > 0:
465
+ entrepreneur_score += 10
466
+ notes.append("食神制杀,按本规则提高创业倾向评分,不代表创业成功概率")
467
+ elif god_counts.get(TenGod.POSITIVE_SEAL.value, 0) > 0:
468
+ entrepreneur_score += 8
469
+ notes.append("杀印相生,传统规则关联管理型自主经营倾向")
470
+
471
+ entrepreneur_score = max(20, min(90, entrepreneur_score))
472
+
473
+ if entrepreneur_score >= 70:
474
+ tendency = "强烈创业倾向"
475
+ elif entrepreneur_score >= 55:
476
+ tendency = "可创业可打工"
477
+ else:
478
+ tendency = "更适合稳定工作"
479
+
480
+ return {
481
+ "score": entrepreneur_score,
482
+ "score_kind": "traditional_rule_index",
483
+ "scope": "individual_natal_entrepreneurship_tendency",
484
+ "score_basis": (
485
+ "以50为基准,按正偏十神权重、食神制杀或杀印相生规则加减,"
486
+ "限制在20–90;只表示本规则的创业倾向,不是成功率或行动建议。"
487
+ ),
488
+ "tendency": tendency,
489
+ "notes": notes,
490
+ }
491
+
492
+ @staticmethod
493
+ def _analyze_career_timing(
494
+ pillars: Dict[str, Tuple[str, str]],
495
+ day_stem: str,
496
+ dayun_pillar: Optional[Tuple[str, str]] = None,
497
+ liunian_pillar: Optional[Tuple[str, str]] = None,
498
+ ) -> Dict[str, Any]:
499
+ """分析事业时机。"""
500
+ signals: List[str] = []
501
+
502
+ if dayun_pillar:
503
+ d_stem, d_branch = dayun_pillar
504
+ d_god = get_ten_god(day_stem, d_stem)
505
+ if d_god in (TenGod.POSITIVE_OFFICER, TenGod.SEVEN_KILLER):
506
+ signals.append(
507
+ f"大运{d_stem}{d_branch}见官杀,传统规则关联事业与管理责任议题"
508
+ )
509
+ elif d_god in (TenGod.POSITIVE_SEAL, TenGod.PARTIAL_SEAL):
510
+ signals.append(
511
+ f"大运{d_stem}{d_branch}见印星,传统规则关联学习与支持议题"
512
+ )
513
+ elif d_god in (TenGod.POSITIVE_WEALTH, TenGod.PARTIAL_WEALTH):
514
+ signals.append(
515
+ f"大运{d_stem}{d_branch}见财星,传统规则关联经营与资源议题,不预测投资收益"
516
+ )
517
+ elif d_god in (TenGod.FOOD_GOD, TenGod.HURT_OFFICER):
518
+ signals.append(
519
+ f"大运{d_stem}{d_branch}见食伤,传统规则关联创意与表达议题"
520
+ )
521
+
522
+ if liunian_pillar:
523
+ l_stem, l_branch = liunian_pillar
524
+ l_god = get_ten_god(day_stem, l_stem)
525
+ if l_god in (TenGod.POSITIVE_OFFICER, TenGod.SEVEN_KILLER):
526
+ signals.append(
527
+ f"流年{l_stem}{l_branch}见官杀,传统规则关联当年的事业与责任议题"
528
+ )
529
+ elif l_god in (TenGod.POSITIVE_WEALTH, TenGod.PARTIAL_WEALTH):
530
+ signals.append(
531
+ f"流年{l_stem}{l_branch}见财星,传统规则关联经营与收入议题,不预测收益"
532
+ )
533
+
534
+ return {
535
+ "timing_signals": signals,
536
+ }
537
+
538
+ @staticmethod
539
+ def _analyze_noble_direction(
540
+ pillars: Dict[str, Tuple[str, str]],
541
+ day_element: Element,
542
+ ) -> Dict[str, Any]:
543
+ """分析贵人方位。"""
544
+ # 喜用神方位
545
+ from ..core.elements import ElementAnalysis
546
+
547
+ dm_analysis = ElementAnalysis.analyze_day_master_strength(pillars)
548
+ favorable = ElementAnalysis.get_favorable_elements(dm_analysis)
549
+
550
+ directions: List[Dict[str, Any]] = []
551
+ for elem in favorable:
552
+ info = ELEMENT_INDUSTRIES.get(elem)
553
+ if info:
554
+ directions.append(
555
+ {
556
+ "element": info["label"],
557
+ "direction": info["direction"],
558
+ "reason": f"喜用神{info['label']}对应{info['direction']}方",
559
+ }
560
+ )
561
+
562
+ return {
563
+ "favorable_directions": directions,
564
+ }
565
+
566
+ @staticmethod
567
+ def _generate_suggestions(
568
+ dominant_god: Dict[str, Any],
569
+ industry: Dict[str, Any],
570
+ structure: Dict[str, Any],
571
+ entrepreneurship: Dict[str, Any],
572
+ ) -> List[str]:
573
+ """生成事业建议。"""
574
+ suggestions: List[str] = []
575
+
576
+ # 基于主导十神
577
+ primary_type = dominant_god.get("primary_career_type", "综合型")
578
+ suggestions.append(f"主导事业类型为{primary_type},建议发挥自身优势")
579
+
580
+ # 基于格局
581
+ level = structure.get("level", "普通格局")
582
+ if "上等" in level:
583
+ suggestions.append("事业格局高,宜志存高远,把握大机遇")
584
+ elif "中等" in level:
585
+ suggestions.append("事业格局中等,稳扎稳打,步步为营")
586
+ else:
587
+ suggestions.append("事业格局需突破,建议持续学习提升,积累人脉资源")
588
+
589
+ # 基于创业倾向
590
+ tendency = entrepreneurship.get("tendency", "")
591
+ if "创业" in tendency:
592
+ suggestions.append(
593
+ "本规则呈现创业相关倾向;是否创业需验证需求、现金流与执行能力,不能据此决定辞职"
594
+ )
595
+ elif "稳定" in tendency:
596
+ suggestions.append(
597
+ "本规则较偏向稳定工作;职业选择仍需结合能力、工作条件和实际机会"
598
+ )
599
+
600
+ # 基于行业
601
+ rec = industry.get("recommended_industries", [])
602
+ if rec:
603
+ first_industries = rec[0].get("industries", [])[:3]
604
+ suggestions.append(f"推荐行业:{'、'.join(first_industries)}等")
605
+
606
+ return suggestions