feat(shadbala): BPHS minimum check first, bands labelled as the site's (T3, BUG-1208)
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
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
de79390175
commit
5fdf2f7498
@@ -0,0 +1,65 @@
|
||||
#!/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
|
||||
Reference in New Issue
Block a user