The English personal report was discarded whenever a Chinese fragment survived the trailing glossary. English sections now render the English fields that were already calculated. Co-Authored-By: Grok (agent loop) Co-authored-by: Cursor <cursoragent@cursor.com>
206 lines
8.1 KiB
Python
206 lines
8.1 KiB
Python
"""Fixed fictional charts for the English-edition sweep (issue #89).
|
||
|
||
Not collected by pytest. Birth data stays inside the generator; callers report
|
||
only the chart index and leftover fragments.
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
import builtins
|
||
import importlib
|
||
import os
|
||
import random
|
||
import re
|
||
import sys
|
||
from pathlib import Path
|
||
|
||
HAN = re.compile(r"[㐀-鿿豈-]")
|
||
GLUE = (
|
||
"scoreandtimeline",
|
||
"marriagequality",
|
||
"inperiod start",
|
||
"Dashasignpresent",
|
||
"aturninperiod",
|
||
"atpresent",
|
||
"planetsinbetween",
|
||
"whetherinunderway",
|
||
"withSaturn",
|
||
"careerplanetAmK",
|
||
"careerdirection",
|
||
"supportingstrongdegree",
|
||
"beneficfactor count",
|
||
"comparativelystrong",
|
||
"occupiesplanetcount",
|
||
"lordandstrong",
|
||
"lordstrongand",
|
||
"weakafflicted",
|
||
"partialreducedweak",
|
||
"debilitatedsign",
|
||
"planetenterssign",
|
||
"planetsdistributed",
|
||
"beneficlocated",
|
||
"house 5 level",
|
||
"house seven-round",
|
||
"condition planets",
|
||
"[source text retained",
|
||
)
|
||
SEED = 20261021
|
||
TODAY = "2026-10-21"
|
||
CHART_COUNT = 200
|
||
|
||
|
||
def fictional_case(index: int) -> dict:
|
||
"""Chart ``index`` from the fixed sequence. Replaying 0..index keeps the seed stable."""
|
||
rng = random.Random(SEED)
|
||
chosen = None
|
||
for i in range(index + 1):
|
||
year = rng.randint(1940, 2015)
|
||
month = rng.randint(1, 12)
|
||
day = rng.randint(1, 28)
|
||
hour = rng.randint(0, 23)
|
||
minute = rng.randint(0, 59)
|
||
lat = round(rng.uniform(-45, 60), 4)
|
||
lon = round(rng.uniform(-120, 150), 4)
|
||
tz = max(-12.0, min(14.0, round(lon / 7.5) * 0.5))
|
||
chosen = {
|
||
"name": f"chart-{i:03d}",
|
||
"year": year,
|
||
"month": month,
|
||
"day": day,
|
||
"hour": hour,
|
||
"minute": minute,
|
||
"second": 0,
|
||
"lat": lat,
|
||
"lon": lon,
|
||
"tz": tz,
|
||
"node_mode": rng.choice(("mean", "true")),
|
||
"ayanamsa": rng.choice(("lahiri", "raman", "kp")),
|
||
"today": TODAY,
|
||
"transit_date": TODAY,
|
||
"target_year": 2026,
|
||
"age": 2026 - year,
|
||
"birth_time_accuracy": "confirmed",
|
||
}
|
||
return chosen
|
||
|
||
|
||
def block_jhora() -> None:
|
||
"""Fail closed if this process imports PyJHora. Call once per process."""
|
||
real_import = builtins.__import__
|
||
|
||
def guarded(name, globals=None, locals=None, fromlist=(), level=0):
|
||
if str(name).split(".", 1)[0] == "jhora":
|
||
raise ImportError("jhora blocked")
|
||
return real_import(name, globals, locals, fromlist, level)
|
||
|
||
builtins.__import__ = guarded
|
||
real_import_module = importlib.import_module
|
||
|
||
def guarded_module(name, package=None):
|
||
if str(name).split(".", 1)[0] == "jhora":
|
||
raise ImportError("jhora blocked")
|
||
return real_import_module(name, package)
|
||
|
||
importlib.import_module = guarded_module
|
||
for key in list(sys.modules):
|
||
if key == "jhora" or key.startswith("jhora."):
|
||
del sys.modules[key]
|
||
|
||
|
||
def _prepare_process() -> None:
|
||
root = Path(__file__).resolve().parents[1]
|
||
for entry in (str(root), str(root / "scripts")):
|
||
if entry not in sys.path:
|
||
sys.path.insert(0, entry)
|
||
block_jhora()
|
||
|
||
|
||
def _residue(text: str) -> dict:
|
||
found = HAN.findall(text or "")
|
||
glue = [word for word in GLUE if word in (text or "")]
|
||
return {"han": len(found), "han_chars": "".join(sorted(set(found)))[:40], "glue": glue}
|
||
|
||
|
||
def render_english(index: int) -> dict:
|
||
"""Build one fictional packet and run ``_english_edition``. No birth data in the result."""
|
||
_prepare_process()
|
||
from scripts.jyotish_engine import build_professional_report_reference_packet, cmd_full_reading
|
||
from scripts.professional_report_reference import _english_edition, _export_args
|
||
|
||
birth = fictional_case(index)
|
||
reading = cmd_full_reading(type("Args", (), dict(birth))())
|
||
packet = dict(build_professional_report_reference_packet(reading, _export_args(dict(birth)), []))
|
||
packet["report_version"] = "pl9_personal_long_report.v3"
|
||
edition = _english_edition(packet, True)
|
||
markdown = edition.get("markdown_en") or ""
|
||
flags = _flags_from_packet(packet)
|
||
applicability = edition.get("reader_dasha_applicability_en") or ""
|
||
body = _residue(markdown)
|
||
extra = _residue(applicability)
|
||
dump_dir = os.environ.get("REPORT_ENGLISH_SWEEP_DUMP")
|
||
if dump_dir and markdown:
|
||
path = Path(dump_dir)
|
||
path.mkdir(parents=True, exist_ok=True)
|
||
(path / f"chart-{index:03d}.md").write_text(markdown, encoding="utf-8")
|
||
return {
|
||
"i": index,
|
||
"status": "ok" if markdown and not edition.get("english_unavailable") else edition.get("english_unavailable") or "empty",
|
||
"han": body["han"] + extra["han"],
|
||
"han_chars": (body["han_chars"] + extra["han_chars"])[:40],
|
||
"glue": sorted(set(body["glue"] + extra["glue"])),
|
||
**flags,
|
||
}
|
||
|
||
|
||
def _flags_from_packet(packet: dict) -> dict:
|
||
rath = (((packet.get("worksheets") or {}).get("timing_and_predictive_systems") or {}).get("narayana_dasha") or {}).get("rath") or {}
|
||
rule = rath.get("current_md_antardasha_rule") or {}
|
||
direction = rule.get("direction") if isinstance(rule, dict) else {}
|
||
advanced = (packet.get("worksheets") or {}).get("advanced_systems") or {}
|
||
doshas = advanced.get("yogas_doshas") or {}
|
||
kaal = doshas.get("kaal_sarp_dosha") or {}
|
||
birth_sheet = (packet.get("worksheets") or {}).get("birth_and_parameters") or {}
|
||
pack = birth_sheet.get("panchanga") or {}
|
||
panchanga = pack.get("raw") if isinstance(pack, dict) and isinstance(pack.get("raw"), dict) else pack
|
||
yoga = advanced.get("yoga") if isinstance(advanced.get("yoga"), dict) else {}
|
||
rows = [row for row in (yoga.get("detected_yogas") or []) if isinstance(row, dict)]
|
||
return {
|
||
"level": rath.get("strength_level_decided"),
|
||
"direction": rath.get("direction"),
|
||
"ad_rule": direction.get("rule") if isinstance(direction, dict) else None,
|
||
"overall": panchanga.get("overall_quality") if isinstance(panchanga, dict) else None,
|
||
"kaal": kaal.get("type") if isinstance(kaal, dict) else None,
|
||
"punarphoo": any(str(row.get("strength") or "") == "观察" or "Punarphoo" in str(row.get("name") or "") for row in rows),
|
||
}
|
||
|
||
|
||
def chart_flags(index: int) -> dict:
|
||
"""Class flags used to prove the smoke set covers L1–L6. No birth data."""
|
||
_prepare_process()
|
||
from scripts.jyotish_engine import build_professional_report_reference_packet, cmd_full_reading
|
||
from scripts.professional_report_reference import _export_args
|
||
|
||
birth = fictional_case(index)
|
||
reading = cmd_full_reading(type("Args", (), dict(birth))())
|
||
packet = dict(build_professional_report_reference_packet(reading, _export_args(dict(birth)), []))
|
||
rath = (((packet.get("worksheets") or {}).get("timing_and_predictive_systems") or {}).get("narayana_dasha") or {}).get("rath") or {}
|
||
rule = rath.get("current_md_antardasha_rule") or {}
|
||
direction = rule.get("direction") if isinstance(rule, dict) else {}
|
||
advanced = (packet.get("worksheets") or {}).get("advanced_systems") or {}
|
||
doshas = advanced.get("yogas_doshas") or {}
|
||
kaal = doshas.get("kaal_sarp_dosha") or {}
|
||
birth_sheet = (packet.get("worksheets") or {}).get("birth_and_parameters") or {}
|
||
pack = birth_sheet.get("panchanga") or {}
|
||
panchanga = pack.get("raw") if isinstance(pack, dict) and isinstance(pack.get("raw"), dict) else pack
|
||
yoga = advanced.get("yoga") if isinstance(advanced.get("yoga"), dict) else {}
|
||
names = [str(row.get("name") or "") for row in (yoga.get("detected_yogas") or []) if isinstance(row, dict)]
|
||
strengths = [str(row.get("strength") or "") for row in (yoga.get("detected_yogas") or []) if isinstance(row, dict)]
|
||
return {
|
||
"i": index,
|
||
"level": rath.get("strength_level_decided"),
|
||
"direction": rath.get("direction"),
|
||
"ad_rule": direction.get("rule") if isinstance(direction, dict) else None,
|
||
"overall": panchanga.get("overall_quality") if isinstance(panchanga, dict) else None,
|
||
"kaal": kaal.get("type") if isinstance(kaal, dict) else None,
|
||
"punarphoo": "观察" in strengths or any("Punarphoo" in name for name in names),
|
||
}
|