Files
Jyotisha/scripts/source_bounded_child_periods.py
T
Jesse_ChenandCursor 04ad3325d5
Independent Staging Quality Gate / validate (push) Successful in 11m26s
Independent Staging Quality Gate / publish (push) Successful in 13m24s
fix(relationship): freeze marriage event classes and add conditional dashas (BUG-608)
Venus/Jupiter/Moon periods no longer collapse into one marriage-opportunity line. Full reading reports the ten BPHS conditional dasha families; Skill 6.9.16.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-09 16:04:52 +08:00

89 lines
3.6 KiB
Python

"""Optional child-period expanders for source-bounded Dasha producers."""
from __future__ import annotations
from copy import deepcopy
from datetime import datetime, timedelta
from typing import Any
PYJHORA_PARENT_SEEDED_EQUAL_SPLIT_PROFILE = "pyjhora_parent_seeded_equal_split_observed_v1"
def _parse_dt(value: Any) -> datetime:
if isinstance(value, datetime):
return value
return datetime.fromisoformat(str(value))
def _iso(value: datetime) -> str:
return value.isoformat(timespec="seconds")
def _sequence_from(lord: str, sequence: tuple[tuple[str, int], ...]) -> list[tuple[str, int]]:
start = next(index for index, (item, _years) in enumerate(sequence) if item == lord)
return list(sequence[start:] + sequence[:start])
def expand_parent_seeded_equal_split_children(
major_rows: list[dict[str, Any]],
sequence: tuple[tuple[str, int], ...],
*,
profile: str | None,
) -> tuple[list[dict[str, Any]], list[dict[str, Any]], list[dict[str, Any]], str]:
"""Attach PyJHora-observed equal-split AD/PD rows when explicitly selected."""
rows = deepcopy(major_rows)
if profile in (None, "", "blocked"):
return rows, [], [], "mahadasha_executed_ad_pd_blocked_pending_row_level_replay"
if profile != PYJHORA_PARENT_SEEDED_EQUAL_SPLIT_PROFILE:
return rows, [], [], "mahadasha_executed_child_period_profile_unknown_blocked"
child_count = len(sequence)
all_ad: list[dict[str, Any]] = []
all_pd: list[dict[str, Any]] = []
for md in rows:
md_lord = str(md.get("lord") or md.get("planet"))
md_start = _parse_dt(md["start_date"])
md_end = _parse_dt(md["end_date"])
md_seconds = (md_end - md_start).total_seconds()
ad_seconds = md_seconds / child_count
ad_rows: list[dict[str, Any]] = []
ad_cursor = md_start
for ad_index, (ad_lord, _ad_years) in enumerate(_sequence_from(md_lord, sequence)):
ad_end = md_end if ad_index == child_count - 1 else ad_cursor + timedelta(seconds=ad_seconds)
pd_seconds = (ad_end - ad_cursor).total_seconds() / child_count
pd_rows: list[dict[str, Any]] = []
pd_cursor = ad_cursor
for pd_index, (pd_lord, _pd_years) in enumerate(_sequence_from(ad_lord, sequence)):
pd_end = ad_end if pd_index == child_count - 1 else pd_cursor + timedelta(seconds=pd_seconds)
pd_row = {
"level": "pratyantardasha",
"lord": pd_lord,
"planet": pd_lord,
"parent_mahadasha": md_lord,
"parent_antardasha": ad_lord,
"start_date": _iso(pd_cursor),
"end_date": _iso(pd_end),
"child_period_profile": profile,
"derivation": "pyjhora_observed_parent_seeded_equal_split",
}
pd_rows.append(pd_row)
all_pd.append(pd_row)
pd_cursor = pd_end
ad_row = {
"level": "antardasha",
"lord": ad_lord,
"planet": ad_lord,
"parent_mahadasha": md_lord,
"start_date": _iso(ad_cursor),
"end_date": _iso(ad_end),
"child_period_profile": profile,
"derivation": "pyjhora_observed_parent_seeded_equal_split",
"pratyantardasha": pd_rows,
}
ad_rows.append(ad_row)
all_ad.append(ad_row)
ad_cursor = ad_end
md["antardasha"] = ad_rows
return rows, all_ad, all_pd, "mahadasha_antardasha_pratyantardasha_executed_pyjhora_observed_profile"