fix(yogini): use Goel Table I order and birth balance (BUG-1262, upstream 1918ffaf)

This commit is contained in:
jesse-ux
2026-10-07 16:48:25 +08:00
parent ab9e30560a
commit 3adb2460e3
5 changed files with 156 additions and 180 deletions
+50 -14
View File
@@ -1,23 +1,59 @@
from datetime import datetime
from datetime import datetime, timedelta
from scripts.yogini_dasha import calculate_yogini_dasha
import pytest
from scripts.yogini_dasha import YOGINI_SEQUENCE, calculate_yogini_dasha
def test_yogini_uses_moon_nakshatra_plus_three_seed_when_available() -> None:
def test_yogini_classical_sequence_and_balance():
# Goel Classical chapter Table I: lord and years, not the older Maya/Jaya/Rati list.
assert [(row['name'], row['planet'], row['years']) for row in YOGINI_SEQUENCE] == [
('Mangala', 'Moon', 1),
('Pingala', 'Sun', 2),
('Dhanya', 'Jupiter', 3),
('Bhramari', 'Mars', 4),
('Bhadrika', 'Mercury', 5),
('Ulka', 'Saturn', 6),
('Siddha', 'Venus', 7),
('Sankata', 'Rahu', 8),
]
birth = datetime(2000, 1, 1, 12)
# Mid-Pushya (eighth nakshatra): remainder 3 is Dhanya, half of 3 years left.
result = calculate_yogini_dasha({
'birth_datetime': birth,
'moon_longitude': 100.0,
'as_of': '2000-01-02',
'dasha_year_days': 360,
})
assert result['starting_planet'] == 'Jupiter'
assert result['starting_yogini'] == 'Dhanya'
assert result['birth_balance_years'] == pytest.approx(1.5)
assert datetime.fromisoformat(result['major'][0]['end_date']) == birth + timedelta(days=540)
assert result['major'][0]['years'] == pytest.approx(1.5)
assert result['current']['planet'] == 'Jupiter'
assert result['major'][1]['planet'] == 'Mars'
assert all(a['end_date'] == b['start_date'] for a, b in zip(result['major'], result['major'][1:]))
def test_yogini_no_invented_lagna_fallback_or_missing_balance():
# 原值: lagna-only input started at Maya via legacy_lagna_rashi_compatibility
# 新值: status blocked,major 为空
# 原因: BUG-1262,没有月亮黄经就不能编一段从出生起算的满周期
result = calculate_yogini_dasha({
'lagna_rashi_index': 0,
'moon_nakshatra_index': 0,
'birth_datetime': datetime(1990, 1, 1),
'birth_datetime': datetime(2000, 1, 1),
})
assert result['starting_yogini'] == 'Rati'
assert result['starting_planet'] == 'Mercury'
assert result['seed_method'] == 'moon_nakshatra_plus_3_mod_8'
assert result['status'] == 'blocked'
assert result['major'] == []
def test_yogini_keeps_legacy_seed_only_without_moon_nakshatra() -> None:
result = calculate_yogini_dasha({
'lagna_rashi_index': 0,
'birth_datetime': datetime(1990, 1, 1),
})
assert result['starting_yogini'] == 'Maya'
assert result['seed_method'] == 'legacy_lagna_rashi_compatibility'
def test_yogini_explicit_reference_controls_current_cycle():
args = {'birth_datetime': '2000-01-01', 'moon_longitude': 0.0, 'dasha_year_days': 360}
first = calculate_yogini_dasha(dict(args, as_of='2000-01-02'))
later = calculate_yogini_dasha(dict(args, as_of='2040-01-01'))
assert first['current']['cycle_number'] == 1
assert later['current']['cycle_number'] == 2
# Ashwini start: (0 + 3) % 8 is Bhramari / Mars, and the balance is the whole period.
assert first['starting_planet'] == 'Mars'
assert first['birth_balance_years'] == pytest.approx(4.0)