feat(report): English reader edition from the same packet; yoga combination English twins (E1/E2/E3 wiring)
- /api/professional_report_reference accepts languages [zh,en]; one packet, zh byte-identical, markdown_en + reader_dasha_applicability_en, or english_unavailable when a Chinese character would leak. - pl9_reader_english renders the parity volume with report_language=en and a fixed term table; yoga_engine carries combination_en / effects_en / strength_en. - 75 fictional charts: zero Han, same line count, same numbers outside yoga tables. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0c06ab1d78
commit
419e1f4d37
@@ -7,6 +7,7 @@ calculation, and delegates packet assembly/rendering to ``jyotish_engine``.
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import copy
|
||||
from datetime import datetime
|
||||
from importlib import import_module
|
||||
from types import SimpleNamespace
|
||||
@@ -77,6 +78,54 @@ def _normalize_packs(value: Any) -> list[str]:
|
||||
return selected
|
||||
|
||||
|
||||
def _normalize_languages(value: Any) -> list[str]:
|
||||
"""``languages`` is optional; only ``zh`` and ``en`` exist. Absent means today's zh-only reply."""
|
||||
if value is None:
|
||||
return []
|
||||
if not isinstance(value, list) or any(not isinstance(item, str) for item in value):
|
||||
raise ProfessionalReportReferenceInputError("languages must be an array of strings")
|
||||
selected = []
|
||||
for item in value:
|
||||
language = item.strip().lower()
|
||||
if language not in {"zh", "en"}:
|
||||
raise ProfessionalReportReferenceInputError("languages may contain only zh and en")
|
||||
if language not in selected:
|
||||
selected.append(language)
|
||||
return selected
|
||||
|
||||
|
||||
def _english_edition(packet: dict, include_fact_tables: bool) -> dict[str, Any]:
|
||||
"""Render the English reader from a deep copy of the same packet.
|
||||
|
||||
The English edition is secondary: any failure, or any Chinese character left
|
||||
in it, drops it and reports why. The Chinese edition is never touched.
|
||||
"""
|
||||
try:
|
||||
from scripts.pl9_reader_english import HAN, _public_wording_en
|
||||
from scripts.pl9_reader_export import _pl9_export_markdown_for_edition
|
||||
except ModuleNotFoundError: # pragma: no cover - direct scripts/ execution path
|
||||
from pl9_reader_english import HAN, _public_wording_en
|
||||
from pl9_reader_export import _pl9_export_markdown_for_edition
|
||||
try:
|
||||
english = copy.deepcopy(packet)
|
||||
english["report_language"] = "en"
|
||||
markdown = _pl9_export_markdown_for_edition(english, READER_MAIN_EDITION)
|
||||
applicability = (
|
||||
_public_wording_en(render_dasha_applicability(copy.deepcopy(packet), language="en"))
|
||||
if include_fact_tables else None
|
||||
)
|
||||
except Exception: # noqa: BLE001 - the English edition must never fail the Chinese one
|
||||
return {"english_unavailable": "render_error"}
|
||||
if not isinstance(markdown, str) or not markdown.strip():
|
||||
return {"english_unavailable": "empty"}
|
||||
if HAN.search(markdown) or (applicability is not None and HAN.search(applicability)):
|
||||
return {"english_unavailable": "han_leak"}
|
||||
return {
|
||||
"markdown_en": markdown,
|
||||
**({"reader_dasha_applicability_en": applicability} if applicability is not None else {}),
|
||||
}
|
||||
|
||||
|
||||
def _load_engine():
|
||||
try:
|
||||
return import_module("scripts.jyotish_engine")
|
||||
@@ -120,6 +169,9 @@ def build_professional_report_reference(handler, body: dict[str, Any], *, engine
|
||||
output_format = _normalize_format(body.get("format"))
|
||||
edition = _normalize_edition(body.get("edition"))
|
||||
packs = _normalize_packs(body.get("packs"))
|
||||
languages = _normalize_languages(body.get("languages"))
|
||||
if languages and (output_format != "markdown" or edition != READER_MAIN_EDITION):
|
||||
raise ProfessionalReportReferenceInputError("languages requires format markdown and edition reader_main")
|
||||
|
||||
birth = handler._high_rigor_birth_payload(body)
|
||||
full_reading = handler._compute_full_reading_for_thematic(birth)
|
||||
@@ -142,6 +194,9 @@ def build_professional_report_reference(handler, body: dict[str, Any], *, engine
|
||||
from scripts.pl9_reader_export import _pl9_export_markdown_for_edition
|
||||
except ModuleNotFoundError: # pragma: no cover - direct scripts/ execution path
|
||||
from pl9_reader_export import _pl9_export_markdown_for_edition
|
||||
# English renders from its own deep copy first, so nothing the Chinese
|
||||
# renderer does to the packet can reach it (and vice versa).
|
||||
english = _english_edition(packet, body.get("include_fact_tables") is True) if "en" in languages else {}
|
||||
markdown = _pl9_export_markdown_for_edition(packet, READER_MAIN_EDITION)
|
||||
else:
|
||||
markdown = resolved_engine.render_pl9_markdown(packet)
|
||||
@@ -153,6 +208,7 @@ def build_professional_report_reference(handler, body: dict[str, Any], *, engine
|
||||
**({"fact_table_packet": report_density_packet(packet),
|
||||
"reader_dasha_applicability": clean_reader_appendix_markdown(render_dasha_applicability(packet))}
|
||||
if body.get("include_fact_tables") is True else {}),
|
||||
**(english if edition == READER_MAIN_EDITION and "en" in languages else {}),
|
||||
}
|
||||
return {
|
||||
"format": "json",
|
||||
|
||||
Reference in New Issue
Block a user