Files
Jyotisha/tests/test_chara_karaka_8_bphs_order.py
T
Jesse_ChenandClaude Opus 5.5 0cf2249e6b fix(jaimini): 8-karaka order follows BPHS ch. 32 (PiK 5th, DK 8th) (T6, BUG-1204)
KARAKA_8 put Putrakaraka 5th, Darakaraka 7th and Pitrukaraka 8th. BPHS ch. 32
order with Rahu counted is AK, AmK, BK, MK, PiK, PK, GK, DK. Test pins the
table and a public AA chart (Steve Jobs, Raman, mean nodes) plus the reader
report's live 8-karaka rows. jaimini.py is in the frozen rectification identity;
re-freeze follows in a separate commit (rectification does not read karakas).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
2026-10-03 11:33:16 +08:00

74 lines
3.8 KiB
Python

"""8-karaka Chara Karaka order follows BPHS ch. 32 (BUG-1204).
BPHS ch. 32 (Karakas): with Rahu counted, the eight roles in descending
order of degrees are Atma, Amatya, Bhratru, Matru, Pitru, Putra, Gnati, Dara;
Rahu ranks by 30 minus its degree in sign. The old table put Putra 5th, Dara
7th and Pitru 8th (TASK-astrologer-rulings-batch1-20261003 T6).
Public chart: Steve Jobs, Astro-Databank AA (repository development case
library), Raman ayanamsa, mean nodes.
"""
from __future__ import annotations
import json
from pathlib import Path
from scripts.jaimini import KARAKA_7, KARAKA_8, calc_chara_karaka_8
from scripts.jyotish_engine import compute_chart_data
ROOT = Path(__file__).resolve().parents[1]
BPHS_8 = ["Atmakaraka", "Amatyakaraka", "Bhratrikaraka", "Matrikaraka",
"Pitrukaraka", "Putrakaraka", "Gnatikaraka", "Darakaraka"]
def _jobs_degrees() -> dict[str, float]:
cases = json.loads((ROOT / "references/real_case_calibration/minute_rectification_development_v1.json").read_text(encoding="utf-8"))["cases"]
birth = next(case for case in cases if case["case_id"] == "steve_jobs_1955_development")["birth"]
assert birth["source"]["rodden_rating"] == "AA"
year, month, day = (int(part) for part in birth["date"].split("-"))
hour, minute = (int(part) for part in birth["time"].split(":"))
chart, *_ = compute_chart_data(year, month, day, hour, minute, birth["latitude"], birth["longitude"],
birth["timezone_offset"], ayanamsa_name="raman")
return {name: row["degree_raw"] % 30 for name, row in chart["planets"].items()}
def test_table_is_the_bphs_order() -> None:
assert [KARAKA_8[rank] for rank in range(1, 9)] == BPHS_8
# The 7-karaka scheme (no Pitrukaraka) is unchanged.
assert [KARAKA_7[rank] for rank in range(1, 8)] == [
"Atmakaraka", "Amatyakaraka", "Bhratrikaraka", "Matrikaraka", "Putrakaraka", "Gnatikaraka", "Darakaraka"]
def test_public_chart_roles_follow_bphs_ranking() -> None:
degrees = _jobs_degrees()
effective = {name: (30.0 - value) % 30.0 if name == "Rahu" else value
for name, value in degrees.items() if name != "Ketu"}
expected_order = sorted(effective, key=effective.get, reverse=True)
table = calc_chara_karaka_8(degrees)["karaka_table_8"]
assert {role: row["planet"] for role, row in table.items()} == dict(zip(BPHS_8, expected_order))
assert {role: row["rank"] for role, row in table.items()} == {role: rank for rank, role in enumerate(BPHS_8, 1)}
# Lowest effective degree is Dara; Pitru sits between Matru and Putra.
assert table["Darakaraka"]["planet"] == min(effective, key=effective.get)
assert table["Matrikaraka"]["effective_degree_in_sign"] >= table["Pitrukaraka"]["effective_degree_in_sign"] >= table["Putrakaraka"]["effective_degree_in_sign"]
# This chart's own values (Raman, mean nodes): Rahu at 10.72° ranks by 19.28°.
assert table["Pitrukaraka"]["planet"] == "Rahu"
assert table["Darakaraka"]["planet"] == "Mars"
assert table["Putrakaraka"]["planet"] == "Moon"
def test_reader_report_karaka_table_is_in_bphs_order() -> None:
"""Live render of a fictional chart: the reader's 8-karaka rows run AK..DK."""
import copy
from scripts.jaimini import KARAKA_CN
from scripts.pl9_reader_export import _pl9_export_markdown_for_edition
from tests.test_report_english_edition import CASES, _packet
packet = _packet(CASES["day"])
markdown = _pl9_export_markdown_for_edition(copy.deepcopy(packet), "reader_main")
lines = markdown.splitlines()
start = next(i for i, line in enumerate(lines) if line.startswith("### Jaimini Karaka"))
rows = [line for line in lines[start + 1:start + 14] if line.startswith("| ") and "星" in line.split("|")[1]]
assert [row.split("|")[1].strip() for row in rows] == [KARAKA_CN[role] for role in BPHS_8]