Files
Jyotisha/scripts/report_render/dasha_reference.py
T
ClaudeandClaude Opus 5.5 2028d7fdf7
Independent Staging Quality Gate / validate-frontend (push) Successful in 5m8s
Independent Staging Quality Gate / validate-python (push) Successful in 5m55s
Independent Staging Quality Gate / publish (push) Successful in 3m9s
feat(report): 「大运传统参考」 from the astrologer's bilingual nine-lord text (yinduzhanxing 058c4f5f)
- Sync references/mahadasha_editorial_bilingual.json (9 lords x 3 paragraphs,
  zh + en, per-paragraph source locators) and mahadasha_editorial_policy.md,
  plus the one-line pointers in SKILL.md and vimshottari_dasha_guide.md.
- New chapter after 大运解释 in both editions: the three paragraphs side by
  side (general / traditionally supportive / traditionally strained), never
  picked by lord or chart, Mahadasha layer only; source labelled as secondary
  study notes with the original edition pending verification; English only
  in the English edition.
- Coverage contract: the topic moves from NOT_CARRIED to the checked list.

No change to the frozen exporter, dates or any scoring.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-06 21:48:09 +08:00

95 lines
4.5 KiB
Python
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.
"""「大运传统参考」: nine Mahadasha lords, three paragraphs each, both editions.
Text: `references/mahadasha_editorial_bilingual.json`, synced from the
astrologer's skill repository (yinduzhanxing 058c4f5f, 2026-11-06). Rules:
`references/mahadasha_editorial_policy.md`.
- A general reference, the three paragraphs side by side. Nothing here picks
「有利」 or 「压力」 for this chart, and nothing says the reader is afflicted.
- Mahadasha lord layer only; no Mahadasha/Antardasha combinations.
- The source is secondary study notes; the page markers are not BPHS edition
pages, and the report says so. The English edition shows English only.
"""
from __future__ import annotations
import json
import re
from functools import lru_cache
from pathlib import Path
_PATH = Path(__file__).resolve().parents[2] / "references" / "mahadasha_editorial_bilingual.json"
_KINDS = (
("general", "一般背景", "General background"),
("supportive_conditions", "传统有利条件下", "Under traditionally supportive conditions"),
("strained_conditions", "传统压力条件下", "Under traditionally strained conditions"),
)
_HAN = re.compile(r"[一-鿿]")
@lru_cache(maxsize=1)
def load_reference() -> dict:
with _PATH.open(encoding="utf-8") as handle:
return json.load(handle)
def _source_line(pages: list[int], language: str) -> str:
pages_text = "、".join(str(page) for page in pages) if language == "zh" else ", ".join(str(page) for page in pages)
if language == "zh":
return f"来源:《BPHS 读书笔记》第 44 节,PDF 页 {pages_text}(二手资料;原典印刷版待核)。"
return f"Source: BPHS Study Notes, section 44, PDF page {pages_text} (secondary source; original edition pending verification)."
def render_dasha_reference(language: str) -> str:
data = load_reference()
zh = language == "zh"
lines = [
"## 大运传统参考(通用)" if zh else "## Traditional Dasha Reference (general)",
"",
(
"下面是九颗大运主星在传统文本里的通用主题,三段并列。哪一段更贴近这张盘,"
"要看功能吉凶、宫主与落宫、尊贵、力量、燃烧、相照与缓解因素,本章不替这张盘做判断,也不是推算结果。"
"只写大运主星这一层,不拼接小运。"
) if zh else (
"Traditional themes for each of the nine Mahadasha lords, the three paragraphs side by side. "
"Which one is closer to this chart depends on functional roles, house lordship and placement, dignity, "
"strength, combustion, aspects and mitigating factors; this chapter does not decide that for the chart "
"and is not a calculated result. It covers the Mahadasha lord only, not sub-period combinations."
),
"",
]
for planet in data.get("planets") or []:
if not isinstance(planet, dict):
continue
name = planet.get("name_zh") if zh else planet.get("id")
paragraphs = {item.get("kind"): item for item in planet.get("paragraphs") or [] if isinstance(item, dict)}
if not name or not all(kind in paragraphs for kind, _zh, _en in _KINDS):
continue
lines.extend([f"### {name}", ""])
pages: list[int] = []
for kind, label_zh, label_en in _KINDS:
item = paragraphs[kind]
text = str(item.get("zh" if zh else "en") or "").strip()
if not text or (not zh and _HAN.search(text)):
continue
lines.extend([f"**{label_zh if zh else label_en}**:{text}" if zh else f"**{label_en}**: {text}", ""])
page = item.get("pdf_page")
if isinstance(page, int) and page not in pages:
pages.append(page)
if pages:
lines.extend([_source_line(pages, language), ""])
return "\n".join(lines).rstrip() + "\n"
def insert_dasha_reference(markdown: str, language: str) -> str:
"""Right after the 「大运解释」 / Dasha Interpretation chapter; unchanged when it is absent."""
if not markdown:
return markdown
heading = r"^## (?:大运解释|Dasha Interpretation)\s*$"
match = re.search(heading, markdown, flags=re.MULTILINE)
if not match:
return markdown
following = re.search(r"^## ", markdown[match.end():], flags=re.MULTILINE)
cut = match.end() + following.start() if following else len(markdown)
return markdown[:cut].rstrip() + "\n\n" + render_dasha_reference(language).rstrip() + "\n\n" + markdown[cut:].lstrip()