年运附表补上整宫、Tripataki 和特殊点公式轨迹。黄经沿用已算好的星盘,不改原有 Saham 数值。

Co-Authored-By: Grok (agent loop)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jesse-ux
2026-10-22 23:11:48 +08:00
co-authored by Grok (agent loop) Cursor
parent 6b906f85c4
commit 9b2e6aa0b4
9 changed files with 560 additions and 23 deletions
+112 -12
View File
@@ -166,9 +166,12 @@ SECTIONS: tuple[tuple[str, str], ...] = (
("Current Dasha Convergence", "当前多系统收敛"),
("Chara Dasha Period Durations", "Chara 大运时长"),
("Narayana Method Comparison", "Narayana 口径对照"),
("Annual Return House Framework", "年运整宫框架"),
("Annual Return Calculation Contract", "年运返照计算约定"),
("Tajika Aspect and Yoga Candidates", "Tajika 相位与瑜伽候选"),
("Tripataki Chakra Detail", "Tripataki 轮盘明细"),
("Annual Tajika Strength", "年度 Tajika 力量"),
("Annual Saham Formula Trace", "年度特殊点公式轨迹"),
("Shadbala Subcomponent", "六维力量分项"),
("Shadbala Result", "六维力量结果"),
("House Components and Physical Coordinates", "宫位分量与坐标"),
@@ -202,6 +205,7 @@ SECTIONS: tuple[tuple[str, str], ...] = (
("Pancha Pakshi", "五鸟活动"),
("Natal Vivah Saham", "本命 Vivah Saham"),
("Natal Saham Formula Basis", "本命特殊点公式依据"),
("Natal Saham Formula Trace", "本命特殊点公式轨迹"),
("Arudha / UL / A10", "Arudha、Upapada 与 A10"),
("Jaimini Calculation Details", "Jaimini 计算细节"),
("Graha Pada", "Graha Pada"),
@@ -225,10 +229,6 @@ SECTIONS: tuple[tuple[str, str], ...] = (
)
FORBIDDEN_TITLES = (
"Annual Return House Framework",
"Tripataki Chakra Detail",
"Annual Saham Formula Trace",
"Natal Saham Formula Trace",
"Annual Chart Numeric Data",
"Bhava Bala Relative Score Components",
"Score Extremes",
@@ -850,6 +850,102 @@ def _narayana(packet: dict, language: str) -> str:
])
def _pack_data(field: Any) -> Any:
if isinstance(field, dict) and "data" in field and isinstance(field.get("data"), (dict, list)):
return field["data"]
return field
def _occupants_cell(names: Any, language: str) -> str:
if isinstance(names, list) and names:
return planet_list(names, language) or ("无" if language == "zh" else "None")
if isinstance(names, list):
return "无" if language == "zh" else "None"
return names if isinstance(names, str) else ("无" if language == "zh" else "None")
def _phase_word(phase: Any, language: str) -> str | None:
if phase == "day":
return "日间" if language == "zh" else "Day"
if phase == "night":
return "夜间" if language == "zh" else "Night"
return None
def _annual_houses(packet: dict, language: str) -> str:
pack = _first(packet, ("timing_and_predictive_systems", "annual_tajika_pack")) or {}
data = _pack_data(pack.get("annual_houses") if isinstance(pack, dict) else None)
houses = data.get("houses") if isinstance(data, dict) else None
rows = []
for item in houses or []:
if not isinstance(item, dict):
continue
rows.append({
"house": item.get("house"),
"sign": item.get("sign"),
"lord": item.get("lord"),
"occupant": _occupants_cell(item.get("occupants"), language),
})
return _rows_from(rows, language, [("house", "text"), ("sign", "sign"), ("lord", "planet"), ("occupant", "text")])
def _tripataki(packet: dict, language: str) -> str:
pack = _first(packet, ("timing_and_predictive_systems", "annual_tajika_pack")) or {}
data = _pack_data(pack.get("tripataki_chakra") if isinstance(pack, dict) else None)
if not isinstance(data, dict):
return _blank(language, ["point", "sign", "degree", "longitude"])
placements = []
for item in data.get("placements") or []:
if isinstance(item, dict):
placements.append({
"point": item.get("body"),
"sign": item.get("sign"),
"degree": None if item.get("degree_in_sign") is None else round(float(item["degree_in_sign"]), 4),
"longitude": None if item.get("longitude") is None else round(float(item["longitude"]), 4),
})
vedha = []
for item in data.get("vedha_rows") or []:
if isinstance(item, dict):
vedha.append({
"target": item.get("target"),
"planet": item.get("available_sources") or item.get("sources"),
"status": item.get("status"),
})
parts = [
_rows_from(placements, language, [("point", "text"), ("sign", "sign"), ("degree", "text"), ("longitude", "text")]),
_rows_from(vedha, language, [("target", "planet"), ("planet", "planets"), ("status", "text")]),
]
return "\n\n".join(parts)
def _trace_table(traces: Any, language: str) -> str:
rows = []
if isinstance(traces, list):
for item in traces:
if not isinstance(item, dict):
continue
rows.append({
"name": item.get("name"),
"rule": item.get("rule"),
"phase": _phase_word(item.get("phase"), language),
"longitude": item.get("longitude"),
})
return _rows_from(rows, language, [("name", "text"), ("rule", "text"), ("phase", "text"), ("longitude", "text")])
def _annual_saham_trace(packet: dict, language: str) -> str:
pack = _first(packet, ("timing_and_predictive_systems", "annual_tajika_pack")) or {}
sahams = _pack_data(pack.get("sahams") if isinstance(pack, dict) else None)
traces = sahams.get("formula_traces") if isinstance(sahams, dict) else None
return _trace_table(traces, language)
def _natal_saham_trace(packet: dict, language: str) -> str:
module = _first(packet, ("advanced_systems", "sahams")) or {}
traces = module.get("formula_traces") if isinstance(module, dict) else None
return _trace_table(traces, language)
def _annual(packet: dict, language: str) -> str:
pack = _first(packet, ("timing_and_predictive_systems", "annual_tajika_pack")) or {}
solar = pack.get("solar_return") if isinstance(pack, dict) else {}
@@ -2398,9 +2494,12 @@ _BUILDERS = {
"Current Dasha Convergence": _convergence,
"Chara Dasha Period Durations": _chara,
"Narayana Method Comparison": _narayana,
"Annual Return Calculation Contract": _annual,
"Tajika Aspect and Yoga Candidates": _tajika_candidates,
"Annual Tajika Strength": _tajika_strength,
"Annual Return House Framework": _annual_houses,
"Annual Return Calculation Contract": _annual,
"Tajika Aspect and Yoga Candidates": _tajika_candidates,
"Tripataki Chakra Detail": _tripataki,
"Annual Tajika Strength": _tajika_strength,
"Annual Saham Formula Trace": _annual_saham_trace,
}
@@ -2408,11 +2507,11 @@ def _chapter_sections() -> list[list[str]]:
order = [title for title, _zh in SECTIONS]
groups = [
order[:14],
order[14:17],
order[17:32],
order[32:43],
order[43:59],
order[59:],
order[14:20],
order[20:35],
order[35:46],
order[46:63],
order[63:],
]
return groups
@@ -2455,6 +2554,7 @@ def _render_named(packet: dict, language: str, title: str) -> str:
"Pancha Pakshi": lambda: _missing_module(language, ["name", "value", "status"]),
"Natal Vivah Saham": lambda: _vivah(packet, language),
"Natal Saham Formula Basis": lambda: _saham_basis(packet, language),
"Natal Saham Formula Trace": lambda: _natal_saham_trace(packet, language),
"Arudha / UL / A10": lambda: _special_points(packet, language),
"Jaimini Calculation Details": lambda: _jaimini_details(packet, language),
"Graha Pada": lambda: _graha_pada(packet, language),