bab0718700
Web export now calls the same full pack as the long skill report and caches an owner-only Markdown download. Appendix failure stays unavailable and does not change the main report status. Co-authored-by: Cursor <cursoragent@cursor.com>
129 lines
5.0 KiB
Python
Executable File
129 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
||
"""Theme-level KP monthly support aggregation."""
|
||
|
||
from __future__ import annotations
|
||
|
||
|
||
_DOMAIN_HOUSES = {
|
||
"career": (2, 6, 10, 11),
|
||
"wealth": (2, 5, 9, 11),
|
||
"relationship": (2, 7, 11),
|
||
}
|
||
|
||
_DOMAIN_LABELS = {
|
||
"career": "事业",
|
||
"wealth": "财务",
|
||
"relationship": "关系",
|
||
}
|
||
|
||
_HOUSE_LABELS = {
|
||
2: "收入与资源",
|
||
5: "机会与投入",
|
||
6: "职责与压力",
|
||
7: "合作与伴侣",
|
||
9: "运气与扩张",
|
||
10: "事业与位置",
|
||
11: "回报与支持",
|
||
}
|
||
|
||
_DOMAIN_TEMPLATES = {
|
||
"career": "这段时间更适合把重心放在职责变化、位置调整和回报兑现的节奏里观察。",
|
||
"wealth": "这段时间更适合把注意力放在现金流、机会选择和回报兑现的节奏里观察。",
|
||
"relationship": "这段时间更适合把重心放在合作默契、关系回应和现实支持的变化里观察。",
|
||
}
|
||
|
||
_PLANET_CN = {
|
||
"Sun": "太阳",
|
||
"Moon": "月亮",
|
||
"Mars": "火星",
|
||
"Mercury": "水星",
|
||
"Jupiter": "木星",
|
||
"Venus": "金星",
|
||
"Saturn": "土星",
|
||
"Rahu": "北交点",
|
||
"Ketu": "南交点",
|
||
}
|
||
|
||
_SIGN_CN = {
|
||
"Aries": "白羊座",
|
||
"Taurus": "金牛座",
|
||
"Gemini": "双子座",
|
||
"Cancer": "巨蟹座",
|
||
"Leo": "狮子座",
|
||
"Virgo": "处女座",
|
||
"Libra": "天秤座",
|
||
"Scorpio": "天蝎座",
|
||
"Sagittarius": "射手座",
|
||
"Capricorn": "摩羯座",
|
||
"Aquarius": "水瓶座",
|
||
"Pisces": "双鱼座",
|
||
}
|
||
|
||
|
||
def _collect_active_houses(houses: dict, house_numbers: tuple[int, ...]) -> list[int]:
|
||
active: list[int] = []
|
||
for house in house_numbers:
|
||
row = houses.get(str(house)) if isinstance(houses.get(str(house)), dict) else {}
|
||
significators = row.get("significators") if isinstance(row.get("significators"), dict) else {}
|
||
if significators.get("A") not in (None, "", [], (), set()):
|
||
active.append(house)
|
||
return active
|
||
|
||
|
||
def _house_signal_text(active_houses: list[int], fallback_houses: tuple[int, ...]) -> str:
|
||
if not active_houses:
|
||
return "相关宫位线索暂时偏弱"
|
||
labels = [f"{house}宫{_HOUSE_LABELS.get(house, '')}" for house in active_houses]
|
||
return "、".join(labels)
|
||
|
||
|
||
def _summary_text(domain: str, active_houses: list[int], fallback_houses: tuple[int, ...], md_lord: str, saturn_sign: str) -> str:
|
||
label = _DOMAIN_LABELS.get(domain, domain)
|
||
focus = _house_signal_text(active_houses, fallback_houses)
|
||
template = _DOMAIN_TEMPLATES.get(domain, "这段时间更适合先看结构支持,再看外部触发。")
|
||
md_label = _PLANET_CN.get(md_lord, md_lord)
|
||
saturn_label = _SIGN_CN.get(saturn_sign, saturn_sign)
|
||
if active_houses:
|
||
return (
|
||
f"{label}线本月先看 {focus} 的本命承诺;"
|
||
f"当前主运星为{md_label},土星行运落在{saturn_label},{template}"
|
||
)
|
||
fallback_text = "、".join(
|
||
f"{house}宫{_HOUSE_LABELS.get(house, '')}" for house in fallback_houses
|
||
)
|
||
return (
|
||
f"{label}线本月更适合先按 {fallback_text} 这组标准宫位阅读,再等待更强触发出现;"
|
||
f"当前主运星为{md_label},土星行运落在{saturn_label},{template}"
|
||
)
|
||
|
||
|
||
def _brief_summary_text(domain: str, active_houses: list[int], fallback_houses: tuple[int, ...], md_lord: str) -> str:
|
||
label = _DOMAIN_LABELS.get(domain, domain)
|
||
md_label = _PLANET_CN.get(md_lord, md_lord)
|
||
focus_houses = active_houses or list(fallback_houses[:2])
|
||
focus_text = "、".join(f"{house}宫" for house in focus_houses)
|
||
return f"本命焦点:{focus_text};月运主轴:{label}线跟随{md_label}主运推进。"
|
||
|
||
|
||
def build_kp_monthly_theme_support(
|
||
*, natal_kp: dict, monthly_levels: dict, monthly_transits: dict
|
||
) -> dict:
|
||
houses = natal_kp.get("houses") if isinstance(natal_kp.get("houses"), dict) else {}
|
||
ruling = natal_kp.get("ruling_planets") if isinstance(natal_kp.get("ruling_planets"), dict) else {}
|
||
md_lord = ((monthly_levels.get("mahadasha") or {}) if isinstance(monthly_levels, dict) else {}).get("lord") or "-"
|
||
saturn_sign = ((((monthly_transits.get("planets") or {}) if isinstance(monthly_transits, dict) else {}).get("Saturn") or {}) if isinstance((monthly_transits.get("planets") or {}).get("Saturn"), dict) else {}).get("sign") or "-"
|
||
out = {}
|
||
for domain, house_numbers in _DOMAIN_HOUSES.items():
|
||
active_houses = _collect_active_houses(houses, house_numbers)
|
||
out[domain] = {
|
||
"houses": list(house_numbers),
|
||
"active_houses": active_houses,
|
||
"promise_code": " / ".join(str(h) for h in active_houses) if active_houses else "-",
|
||
"summary": _summary_text(domain, active_houses, house_numbers, md_lord, saturn_sign),
|
||
"brief_summary": _brief_summary_text(domain, active_houses, house_numbers, md_lord),
|
||
"ruling_planet_snapshot": ruling.get("day_lord") or "-",
|
||
"status": "parameter_sensitive",
|
||
"must_not_claim": ["exact_event_timing", "specific_event_prediction"],
|
||
}
|
||
return out
|