Files
Jyotisha/scripts/kp_monthly_theme_support.py
T
Jesse_Chen bab0718700
Independent Staging Quality Gate / validate (push) Failing after 9m41s
Independent Staging Quality Gate / publish (push) Has been skipped
feat(report): ship full-mode longform appendix beside the five-chapter report
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>
2026-09-05 11:10:44 +08:00

129 lines
5.0 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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