Astrologer ruling 甲13. New scripts/shadbala_display.py (display only; shadbala.py is frozen and unchanged): chart.shadbala now carries min_required, meets_minimum, minimum_check (达到/未达到 BPHS 最低要求), level_source=site_band and level '<band>(网站分档)'; report Shadbala table gains 'BPHS minimum' and 'Site band' columns (zh/en); evidence snapshot ranking and health narrative say the minimum check first and mark the band as the site's. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
66 lines
2.4 KiB
Python
66 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""How a Shadbala strength is shown (astrologer rulings 2026-10-03 甲13, BUG-1208).
|
|
|
|
First whether the planet meets the BPHS minimum (BPHS ch. 27 vv. 32-33, the
|
|
`shadbala.MIN_REQUIRED` table), then the site's own band (150/125/100/75/50 % of
|
|
that minimum -> 极强…极弱), labelled as the site's band. `shadbala.py` is in the
|
|
frozen rectification identity, so the fields are added here, at display time,
|
|
from values the engine already returns; nothing is recomputed.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Dict, Optional
|
|
|
|
LEVEL_SOURCE = 'site_band'
|
|
SITE_BAND_SUFFIX = '(网站分档)'
|
|
SITE_BAND_SUFFIX_EN = ' (site band)'
|
|
MEETS_ZH = '达到 BPHS 最低要求'
|
|
MISSES_ZH = '未达到 BPHS 最低要求'
|
|
MEETS_EN = 'meets the BPHS minimum'
|
|
MISSES_EN = 'below the BPHS minimum'
|
|
|
|
|
|
def _number(value: Any) -> Optional[float]:
|
|
return float(value) if isinstance(value, (int, float)) and not isinstance(value, bool) else None
|
|
|
|
|
|
def minimum_fields(rupas: Any, min_required: Any, band: Any) -> Dict[str, Any]:
|
|
"""`min_required`, `meets_minimum`, `minimum_check`, band label and source."""
|
|
total = _number(rupas)
|
|
minimum = _number(min_required)
|
|
meets = None if total is None or minimum is None else total >= minimum
|
|
fields: Dict[str, Any] = {
|
|
'min_required': minimum,
|
|
'meets_minimum': meets,
|
|
'minimum_check': None if meets is None else (MEETS_ZH if meets else MISSES_ZH),
|
|
'level_source': LEVEL_SOURCE,
|
|
}
|
|
if band not in (None, ''):
|
|
fields['level'] = f'{band}{SITE_BAND_SUFFIX}'
|
|
return fields
|
|
|
|
|
|
def row_fields(row: Dict[str, Any]) -> Dict[str, Any]:
|
|
"""Display fields for one `shadbala.calc_shadbala` planet row."""
|
|
return minimum_fields(row.get('total_rupas', row.get('rupas')), row.get('min_required'), row.get('strength_level'))
|
|
|
|
|
|
BAND_EN = {'极强': 'very strong', '强': 'strong', '充足': 'adequate', '略弱': 'slightly weak', '弱': 'weak', '极弱': 'very weak'}
|
|
|
|
|
|
def band_text(band: Any, language: str = 'zh') -> Optional[str]:
|
|
if band in (None, ''):
|
|
return None
|
|
if language == 'en':
|
|
return f"{BAND_EN.get(str(band), str(band))}{SITE_BAND_SUFFIX_EN}"
|
|
return f'{band}{SITE_BAND_SUFFIX}'
|
|
|
|
|
|
def check_text(meets: Optional[bool], language: str = 'zh') -> str:
|
|
if meets is None:
|
|
return '-'
|
|
if language == 'en':
|
|
return MEETS_EN if meets else MISSES_EN
|
|
return MEETS_ZH if meets else MISSES_ZH
|