feat(ashtakavarga): standard Sodhita chain on reports and cards, raw values beside (T7, BUG-1209)
Astrologer ruling 乙8. New scripts/ashtakavarga_shodhana.py: per BAV row Trikona then Ekadhipatya (the two existing ashtakavarga functions, previously only called by tests), Sodhita SAV = sum of reduced rows; occupied signs = seven grahas. Removed calc_sodhita_av (Sun/Mars/Saturn contribution removal labelled 'BPHS标准'). Wired into /api/ashtakavarga (result.sodhita, house_scores[*].sav_sodhita) and the full reading. Reader: SAV table 'Sodhita SAV | Raw SAV', house table gains Sodhita column, Sodhita BAV table before raw BAV; reference edition section rewritten. Card: sav_sodhita before sav_score plus sav_columns label. Personal report facts: score = Sodhita, rawScore/savRawTotal beside (optional schema fields). Fact tables: Sodhita column and Sodhita BAV subtable. Transit scoring unchanged (raw bindus). Golden: report-density-fictional-engine.json leaf worksheets.strengths_and_scores .ashtakavarga recaptured from the real engine (scripts/research/refresh_density_ fixture_ashtakavarga.py); bav/sav identical, every other leaf byte-equal. Changed assertions (three columns in PROGRESS): BUG-1200 house-table tests, report-fact-tables ashtakavarga columns/subtables, run_all t1/t57. 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
5fdf2f7498
commit
ea78804b78
@@ -1310,19 +1310,34 @@ def render_pl9_parity_markdown(packet: dict) -> str:
|
||||
ashtakavarga = _dict(strengths.get('ashtakavarga'))
|
||||
sav = _dict(ashtakavarga.get('sav'))
|
||||
sav_scores = _dict(sav.get('scores'))
|
||||
# BUG-1209 (乙8): the main value is the Sodhita SAV (Trikona then
|
||||
# Ekadhipatya per BAV row); the raw value stands beside it.
|
||||
sodhita = _dict(ashtakavarga.get('sodhita'))
|
||||
sodhita_ok = sodhita.get('status') == 'executed'
|
||||
sodhita_scores = _dict(_dict(sodhita.get('sodhita_sav')).get('scores')) if sodhita_ok else {}
|
||||
sodhita_bav = _dict(sodhita.get('sodhita_bav')) if sodhita_ok else {}
|
||||
english = _pl9_report_language(packet) == 'en'
|
||||
if sav_scores:
|
||||
lines.extend([
|
||||
'### p51-p60 Ashtakavarga SAV / BAV / Pinda',
|
||||
'',
|
||||
f"- 方法:{_cell(ashtakavarga.get('method'))}",
|
||||
f"- BAV 校验:{_cell('all_valid' if ashtakavarga.get('all_bav_valid') else ashtakavarga.get('all_bav_valid'))}",
|
||||
])
|
||||
if sodhita_ok:
|
||||
lines.append(
|
||||
f"- Reduction: {_cell(sodhita.get('method'))}" if english
|
||||
else f"- 净化:{_cell(sodhita.get('method_zh') or sodhita.get('method'))};原始值并列"
|
||||
)
|
||||
lines.extend([
|
||||
'',
|
||||
'| Sign | SAV score |',
|
||||
'|------|-----------|',
|
||||
'| Sign | Sodhita SAV | Raw SAV |' if sodhita_ok else '| Sign | Raw SAV |',
|
||||
'|------|-------------|---------|' if sodhita_ok else '|------|---------|',
|
||||
])
|
||||
for sign in globals().get('SIGNS', []):
|
||||
if sign in sav_scores:
|
||||
lines.append(f"| {_cell(_token(sign))} | {_cell(sav_scores.get(sign))} |")
|
||||
main = f"{_cell(sodhita_scores.get(sign))} | " if sodhita_ok else ''
|
||||
lines.append(f"| {_cell(_token(sign))} | {main}{_cell(sav_scores.get(sign))} |")
|
||||
lines.append('')
|
||||
full_house_scores = ashtakavarga.get('house_scores_full')
|
||||
if isinstance(full_house_scores, dict):
|
||||
@@ -1335,8 +1350,8 @@ def render_pl9_parity_markdown(packet: dict) -> str:
|
||||
lines.extend([
|
||||
'### p53 Ashtakavarga 完整宫位分数',
|
||||
'',
|
||||
'| House | Sign | SAV | Lagna BAV | SAV + Lagna |',
|
||||
'|-------|------|-----|-----------|-------------|',
|
||||
'| House | Sign | Sodhita SAV | Raw SAV | Lagna BAV | Raw SAV + Lagna |',
|
||||
'|-------|------|-------------|---------|-----------|-----------------|',
|
||||
])
|
||||
# `house_scores_full[*].sav_score` is the with-Lagna total (386
|
||||
# scale), never plain SAV (BUG-1200). Split it from the engine's
|
||||
@@ -1361,15 +1376,32 @@ def render_pl9_parity_markdown(packet: dict) -> str:
|
||||
sav_value, lagna_value = parts if split else (None, None)
|
||||
lines.append(
|
||||
f"| {_cell(row.get('house'))} | {_cell(_token(row.get('sign')))} | "
|
||||
f"{_cell(sodhita_scores.get(row.get('sign')))} | "
|
||||
f"{_cell(sav_value)} | {_cell(lagna_value)} | {_cell(row.get('sav_score'))} |"
|
||||
)
|
||||
if split:
|
||||
sodhita_total = sum(sodhita_scores.values()) if len(sodhita_scores) == 12 else '-'
|
||||
lines.append(
|
||||
f"| 合计 | - | {sum(parts[0] for parts in splits)} | "
|
||||
f"| 合计 | - | {sodhita_total} | {sum(parts[0] for parts in splits)} | "
|
||||
f"{sum(parts[1] for parts in splits)} | {sum(row['sav_score'] for row in full_rows)} |"
|
||||
)
|
||||
lines.append('')
|
||||
bav = _dict(ashtakavarga.get('bav'))
|
||||
if bav and sodhita_bav:
|
||||
signs = globals().get('SIGNS', [])
|
||||
lines.extend([
|
||||
('Sodhita BAV (after Trikona and Ekadhipatya reduction):' if english else '净化后 BAV(三方净化 + 单宫主净化):'),
|
||||
'',
|
||||
'| Planet | Sodhita total | Aries | Taurus | Gemini | Cancer | Leo | Virgo | Libra | Scorpio | Sagittarius | Capricorn | Aquarius | Pisces |',
|
||||
'|--------|---------------|-------|--------|--------|--------|-----|-------|-------|---------|-------------|-----------|----------|--------|',
|
||||
])
|
||||
for planet in ('Sun', 'Moon', 'Mars', 'Mercury', 'Jupiter', 'Venus', 'Saturn'):
|
||||
reduced = _list(sodhita_bav.get(planet))
|
||||
if len(reduced) != 12:
|
||||
continue
|
||||
cells = ' | '.join(_cell(value) for value in reduced)
|
||||
lines.append(f"| {_cell(_token(planet))} | {_cell(sum(reduced))} | {cells} |")
|
||||
lines.extend(['', 'Raw BAV:' if english else '原始 BAV:', ''])
|
||||
if bav:
|
||||
signs = globals().get('SIGNS', [])
|
||||
lines.extend([
|
||||
|
||||
Reference in New Issue
Block a user