diff --git a/scripts/avastha_calculator.py b/scripts/avastha_calculator.py index 574b3bed..0956a4f8 100644 --- a/scripts/avastha_calculator.py +++ b/scripts/avastha_calculator.py @@ -227,7 +227,16 @@ class AvasthaCalculator: result["avasthas"]["Shayanadi"] = self._calculate_shayanadi_avastha(planet, sign) for name in ('Deeptadi', 'Lajjitadi', 'Shayanadi'): result['avasthas'][name]['method_status'] = 'simplified_heuristic' - if activity_context is not None: + if activity_context is not None and activity_context.get('unavailable_reason'): + # 极昼极夜等算不出日出时,PVR 公式缺一项。不退回元素启发式冒充,标成无法计算(BUG-1390)。 + result['avasthas']['Shayanadi'] = { + 'state': None, + 'sign': sign, + 'meaning': '当天没有可用的日出(极昼或极夜),姿态无法按 PVR 公式计算。', + 'method_status': 'blocked', + 'blocked_reason': activity_context['unavailable_reason'], + } + elif activity_context is not None: result['avasthas']['Shayanadi'] = calculate_pvr_shayanadi( planet, SIGNS.index(sign) * 30 + degree, @@ -540,7 +549,7 @@ class AvasthaCalculator: # Shayanadi Avastha shayanadi = avasthas["Shayanadi"] - interpretation += f"5. 行为模式:{shayanadi['state']}({shayanadi['sign']})\n" + interpretation += f"5. 行为模式:{shayanadi['state'] or '无法计算'}({shayanadi['sign']})\n" interpretation += f" {shayanadi['meaning']}\n" return interpretation diff --git a/scripts/jyotish_engine.py b/scripts/jyotish_engine.py index a7be4b8e..9f9917c0 100644 --- a/scripts/jyotish_engine.py +++ b/scripts/jyotish_engine.py @@ -16369,15 +16369,20 @@ def cmd_full_reading(args): # ── Step 10.5: Avasthas 行星状态 (v4.4.0) ── try: from avastha_calculator import AvasthaCalculator - from saham_daynight import determine_daytime - avastha_solar_day = determine_daytime( - _birth_datetime_from_args(args), lat=args.lat, lon=args.lon, tz=args.tz, rising='hindu') - hours_since_sunrise = (avastha_solar_day['julian_day_ut'] - avastha_solar_day['sunrise_jd_ut']) * 24 - avastha_activity_context = { - 'moon_longitude': planet_lons['Moon'], - 'asc_longitude': asc_deg, - 'hours_since_sunrise': hours_since_sunrise, - } + from saham_daynight import SahamDayNightError, determine_daytime + try: + avastha_solar_day = determine_daytime( + _birth_datetime_from_args(args), lat=args.lat, lon=args.lon, tz=args.tz, rising='hindu') + except SahamDayNightError as exc: + # 极昼极夜没有日出:只让姿态一项标无法计算,其余四类照常(BUG-1390)。 + avastha_activity_context = {'unavailable_reason': str(exc)} + else: + hours_since_sunrise = (avastha_solar_day['julian_day_ut'] - avastha_solar_day['sunrise_jd_ut']) * 24 + avastha_activity_context = { + 'moon_longitude': planet_lons['Moon'], + 'asc_longitude': asc_deg, + 'hours_since_sunrise': hours_since_sunrise, + } avast_calc = AvasthaCalculator() avast_result = {} for pn, pd in planets.items(): diff --git a/tests/test_avastha_full_reading_wiring.py b/tests/test_avastha_full_reading_wiring.py index 54419eb9..31e09cb2 100644 --- a/tests/test_avastha_full_reading_wiring.py +++ b/tests/test_avastha_full_reading_wiring.py @@ -37,3 +37,29 @@ def test_full_reading_wires_hindu_sunrise_into_activity_formula(monkeypatch): assert actual['method_status'] == 'pvr_15_4_4_running_ghati' assert actual['components']['running_ghati'] == 43 assert actual['state_index'] == 10 + + +def test_polar_birth_without_sunrise_keeps_other_avasthas(monkeypatch): + # BUG-1390:北极圈夏至没有日出。原来整个 avasthas 模块报错消失;现在只有姿态一项标无法计算。 + repo = Path(__file__).resolve().parents[1] + monkeypatch.syspath_prepend(str(repo / 'scripts')) + tree = ast.parse((repo / 'scripts/jyotish_engine.py').read_text(encoding='utf-8')) + blocks = [node for node in ast.walk(tree) if isinstance(node, ast.Try) + and any(isinstance(item, ast.ImportFrom) and item.module == 'avastha_calculator' + for item in node.body)] + report = {'modules': {}, 'errors': []} + env = dict( + report=report, + args=SimpleNamespace(lat=69.65, lon=18.96, tz=2), + asc_deg=0, + planet_lons={'Sun': 90, 'Moon': 0}, + planets={'Sun': {'degree': 90, 'degree_raw': 90, 'sign': 'Cancer', 'house': 4}}, + _birth_datetime_from_args=lambda args: datetime(1990, 6, 21, 12, 0), + ) + exec(compile(ast.Module(body=blocks, type_ignores=[]), '', 'exec'), env) + assert report['errors'] == [] + sun = report['modules']['avasthas']['Sun'] + assert sun['avasthas']['Shayanadi']['state'] is None + assert sun['avasthas']['Shayanadi']['method_status'] == 'blocked' + assert sun['avasthas']['Deeptadi']['state'] + assert '无法计算' in sun['interpretation']