Files
Jyotisha/tests/test_narayana_second_cycle.py
T
ClaudeandClaude Opus 5.5 71510682dc fix(narayana): run the second cycle instead of replaying the first (BUG-1545)
The legacy current-period lookup took the age modulo the first-cycle total,
so anyone older than their first cycle (61-96 years on the nine public
charts) got a first-cycle period: an 80-year-old was placed in 2-12. The
second cycle runs the same signs for 12 minus their first-cycle years; the
lookup now places the age on both cycles and subdivides with the second
cycle's years. The rectification cache only covers the first cycle and falls
back to the live lookup past it, so first-cycle scoring is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DbBXoyeZrYn6ryNcSe5Y2Y
2026-11-04 12:05:22 +08:00

69 lines
2.7 KiB
Python

"""BUG-1545: the running Narayana period after the first cycle.
The first cycle runs each sign for its counted years; the second runs the same
signs in the same order for 12 minus those years. The old lookup took the age
modulo the first-cycle total and so repeated the first cycle: an 80-year-old
was placed in a period that ran from age 2 to 12.
"""
from narayana_dasha import (
calc_narayana_mahadasha,
get_current_narayana_dasha,
narayana_dasha_full_report,
second_narayana_cycle,
)
LAGNA = 3 # Cancer
PLANETS = {"Sun": 80.0, "Moon": 200.0, "Mars": 10.0, "Mercury": 95.0, "Jupiter": 250.0,
"Venus": 120.0, "Saturn": 300.0, "Rahu": 40.0, "Ketu": 220.0}
def _first():
return calc_narayana_mahadasha(LAGNA, PLANETS)
def test_second_cycle_runs_the_same_signs_for_twelve_minus_the_first_years():
first = _first()
total = sum(p["years"] for p in first)
second = second_narayana_cycle(first, start_age=total)
expected = [(p["sign"], 12 - p["years"]) for p in first if p["years"] < 12]
assert [(p["sign"], p["years"]) for p in second] == expected
assert second[0]["start_age"] == total
assert all(p["cycle"] == 2 for p in second)
assert total + sum(p["years"] for p in second) == 12 * len(first)
for a, b in zip(second, second[1:]):
assert a["end_age"] == b["start_age"]
def test_first_cycle_ages_are_unchanged():
first = _first()
for p in first:
mid = (p["start_age"] + p["end_age"]) / 2
current = get_current_narayana_dasha(first, mid)
assert current["md"]["sign"] == p["sign"]
assert current["md"]["cycle"] == 1
def test_an_age_past_the_first_cycle_lands_in_the_second_cycle():
first = _first()
total = sum(p["years"] for p in first)
second = second_narayana_cycle(first, start_age=total)
for p in second:
mid = (p["start_age"] + p["end_age"]) / 2
current = get_current_narayana_dasha(first, mid)
assert current["md"]["sign"] == p["sign"], mid
assert current["md"]["cycle"] == 2
assert current["md"]["start_age"] <= mid < current["md"]["end_age"]
# the antardasha sits inside the second-cycle mahadasha
assert current["ad"] is not None
assert current["md"]["start_age"] <= current["ad"]["start_age"] < current["md"]["end_age"]
assert round(current["remaining_years"], 2) == round(p["end_age"] - mid, 2)
def test_full_report_reports_the_second_cycle_period():
first = _first()
total = sum(p["years"] for p in first)
report = narayana_dasha_full_report(LAGNA, PLANETS, current_age=total + 0.5, birth_year=1940)
md = report["current_dasha"]["md"]
assert md["cycle"] == 2
assert md["start_age"] == total