feat: 完整数据版加入六种星座大运
Sthira、Drig、Shoola、Navamsha、Niryaana Shoola 与 K.N. Rao 的 Chara 从本盘算出。Lagna Kendradi 不上表。未推送。
This commit is contained in:
@@ -0,0 +1,196 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Freeze PyJHora 4.8.7 rashi-dasha rows for four public or fictional charts.
|
||||
|
||||
Run with the Anaconda interpreter that has PyJHora 4.8.7. Product code does
|
||||
not import this module. Tests read the JSON only.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import importlib.metadata
|
||||
import io
|
||||
import json
|
||||
import sys
|
||||
from contextlib import redirect_stdout
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path[:0] = [str(ROOT), str(ROOT / "scripts")]
|
||||
|
||||
OUT = ROOT / "tests" / "fixtures" / "rashi_dasha_pyjhora_20261008.json"
|
||||
CASE_IDS = (
|
||||
"steve_jobs_1955_aa",
|
||||
"barack_obama_1961_aa",
|
||||
"einstein_1879_aa",
|
||||
"fictional_reader_main",
|
||||
)
|
||||
|
||||
|
||||
def _births() -> dict:
|
||||
public = json.loads((ROOT / "references" / "public_oracle_cases.json").read_text(encoding="utf-8"))
|
||||
births = {case["id"]: case["birth"] for case in public["cases"]}
|
||||
special = json.loads((ROOT / "tests" / "fixtures" / "special_lagnas_pyjhora_487.json").read_text(encoding="utf-8"))
|
||||
births["fictional_reader_main"] = special["cases"]["fictional_reader_main"]["birth"]
|
||||
return births
|
||||
|
||||
|
||||
def _parse_row(row):
|
||||
if not isinstance(row, (list, tuple)) or len(row) < 3:
|
||||
return None
|
||||
if (
|
||||
len(row) >= 4
|
||||
and isinstance(row[0], int)
|
||||
and isinstance(row[1], int)
|
||||
and not isinstance(row[2], (int, float))
|
||||
):
|
||||
signs = [int(row[0]), int(row[1])]
|
||||
start, years = row[2], row[3]
|
||||
else:
|
||||
lord, start, years = row[0], row[1], row[2]
|
||||
signs = [int(item) for item in lord] if isinstance(lord, (list, tuple)) else [int(lord)]
|
||||
if isinstance(start, (list, tuple)):
|
||||
start_iso = f"{int(start[0]):04d}-{int(start[1]):02d}-{int(start[2]):02d}"
|
||||
else:
|
||||
start_iso = str(start)[:10]
|
||||
years_n = float(years)
|
||||
years_out = int(round(years_n)) if abs(years_n - round(years_n)) < 1e-6 else years_n
|
||||
return signs, start_iso, years_out
|
||||
|
||||
|
||||
def _call(fn, args):
|
||||
with redirect_stdout(io.StringIO()):
|
||||
return fn(*args)
|
||||
|
||||
|
||||
def _pyjhora_case(birth: dict, modules, swe, drik, charts, Place) -> dict:
|
||||
local_hour = birth["hour"] + birth["minute"] / 60.0 + birth.get("second", 0) / 3600.0
|
||||
with redirect_stdout(io.StringIO()):
|
||||
drik.set_ayanamsa_mode("LAHIRI")
|
||||
jd = swe.julday(birth["year"], birth["month"], birth["day"], local_hour)
|
||||
place = Place("birth_place", birth["lat"], birth["lon"], birth["tz"])
|
||||
positions = charts.rasi_chart(jd, place)
|
||||
dob = (birth["year"], birth["month"], birth["day"])
|
||||
tob = (birth["hour"], birth["minute"], birth["second"])
|
||||
calls = {
|
||||
"sthira": lambda level: modules["sthira"].get_dhasa_antardhasa(dob, tob, place, dhasa_level_index=level),
|
||||
"shoola": lambda level: modules["shoola"].shoola_dhasa(positions, dob, tob, dhasa_level_index=level),
|
||||
"niryaana_shoola": lambda level: modules["nirayana"].nirayana_shoola_dhasa(positions, dob, tob, dhasa_level_index=level),
|
||||
"drig": lambda level: modules["drig"].drig_dhasa(positions, dob, tob, dhasa_level_index=level),
|
||||
"navamsha": lambda level: modules["navamsa"].get_dhasa_antardhasa(dob, tob, place, dhasa_level_index=level),
|
||||
"chara": lambda level: modules["chara"].get_dhasa_antardhasa(dob, tob, place, dhasa_level_index=level),
|
||||
"lagna_kendradi": lambda level: modules["lagna_kendraadhi"].lagna_kendradhi_rasi_dhasa(dob, tob, place, dhasa_level_index=level),
|
||||
}
|
||||
parsed = {}
|
||||
for key, call in calls.items():
|
||||
level_1 = [_parse_row(row) for row in _call(call, (1,))]
|
||||
level_2 = [_parse_row(row) for row in _call(call, (2,))]
|
||||
majors = [row for row in level_1 if row and len(row[0]) == 1]
|
||||
if not majors:
|
||||
majors = [row for row in level_2 if row and len(row[0]) == 1]
|
||||
subs = [row for row in level_2 if row and len(row[0]) == 2]
|
||||
first_sign = majors[0][0][0] if majors else None
|
||||
first_subs = [row[0][1] for row in subs if row[0][0] == first_sign]
|
||||
parsed[key] = {
|
||||
"sign_indexes": [row[0][0] for row in majors],
|
||||
"years": [row[2] for row in majors],
|
||||
"second_start": majors[1][1] if len(majors) > 1 else None,
|
||||
"first_sub_sign_indexes": first_subs,
|
||||
}
|
||||
return parsed
|
||||
|
||||
|
||||
def _succession(signs: list[int]) -> tuple[int, ...]:
|
||||
return tuple((signs[index] - signs[index - 1]) % 12 for index in range(1, len(signs)))
|
||||
|
||||
|
||||
def _diff_steps(section: dict, pyjhora: dict) -> list[str]:
|
||||
our_signs = [row["sign_index"] for row in section["periods"]]
|
||||
their_signs = pyjhora["sign_indexes"]
|
||||
our_years = [row["years"] for row in section["periods"]]
|
||||
their_years = pyjhora["years"]
|
||||
steps = []
|
||||
if not our_signs or not their_signs or our_signs[0] != their_signs[0]:
|
||||
steps.append("start_sign")
|
||||
if _succession(our_signs) != _succession(their_signs):
|
||||
steps.append("direction")
|
||||
if sorted(zip(our_signs, our_years)) != sorted(zip(their_signs, their_years)):
|
||||
steps.append("years")
|
||||
our_sub = [row["sign_index"] for row in (section["periods"][0].get("antardasha") or [])] if section["periods"] else []
|
||||
if our_sub != (pyjhora.get("first_sub_sign_indexes") or []):
|
||||
steps.append("subperiod")
|
||||
if our_signs == their_signs and our_years == their_years and len(section["periods"]) > 1:
|
||||
if section["periods"][1]["start"] != pyjhora.get("second_start"):
|
||||
steps.append("date_basis")
|
||||
return steps
|
||||
|
||||
|
||||
def main() -> None:
|
||||
with redirect_stdout(io.StringIO()):
|
||||
import swisseph as swe
|
||||
from jhora.horoscope.chart import charts
|
||||
from jhora.panchanga import drik
|
||||
from jhora.panchanga.drik import Place
|
||||
|
||||
modules = {
|
||||
name: importlib.import_module("jhora.horoscope.dhasa.raasi." + module_name)
|
||||
for name, module_name in (
|
||||
("sthira", "sthira"),
|
||||
("shoola", "shoola"),
|
||||
("nirayana", "nirayana"),
|
||||
("drig", "drig"),
|
||||
("navamsa", "navamsa"),
|
||||
("chara", "chara"),
|
||||
("lagna_kendraadhi", "lagna_kendraadhi"),
|
||||
)
|
||||
}
|
||||
from jyotish_engine import compute_chart_data
|
||||
from rashi_dashas_native import calculate_rashi_dashas
|
||||
|
||||
payload = {
|
||||
"pyjhora_version": importlib.metadata.version("PyJHora"),
|
||||
"generator_python_has_pyjhora": True,
|
||||
"generator": "scripts/research/freeze_rashi_dasha_pyjhora_fixture.py",
|
||||
"note": "Anaconda PyJHora 4.8.7 produced the external rows. Pytest reads this file and does not import PyJHora.",
|
||||
"cases": {},
|
||||
}
|
||||
births = _births()
|
||||
for case_id in CASE_IDS:
|
||||
birth = births[case_id]
|
||||
chart, _asc, _jd, _ayanamsa = compute_chart_data(
|
||||
birth["year"], birth["month"], birth["day"], birth["hour"], birth["minute"],
|
||||
birth["lat"], birth["lon"], birth["tz"], second=birth.get("second") or 0,
|
||||
)
|
||||
longitudes = {
|
||||
name: float(row["degree_raw"])
|
||||
for name, row in chart["planets"].items()
|
||||
if isinstance(row, dict) and "degree_raw" in row
|
||||
}
|
||||
native = calculate_rashi_dashas(chart["birth_info"]["date"], float(chart["ascendant"]["degree_raw"]), longitudes)
|
||||
external = _pyjhora_case(birth, modules, swe, drik, charts, Place)
|
||||
native_view = {}
|
||||
diff_steps = {}
|
||||
for key, section in native.items():
|
||||
if key == "lagna_kendradi":
|
||||
diff_steps[key] = ["start_sign", "direction", "years", "subperiod"]
|
||||
native_view[key] = {"status": "omitted", "sign_indexes": [], "years": []}
|
||||
continue
|
||||
native_view[key] = {
|
||||
"sign_indexes": [row["sign_index"] for row in section["periods"]],
|
||||
"years": [row["years"] for row in section["periods"]],
|
||||
}
|
||||
diff_steps[key] = _diff_steps(section, external[key])
|
||||
payload["cases"][case_id] = {
|
||||
"birth_source": birth,
|
||||
"pyjhora": external,
|
||||
"native": native_view,
|
||||
"diff_steps": diff_steps,
|
||||
}
|
||||
print(case_id, {key: value for key, value in diff_steps.items()}, flush=True)
|
||||
OUT.parent.mkdir(parents=True, exist_ok=True)
|
||||
OUT.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
|
||||
print(OUT)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user