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
+4
-95
@@ -491,101 +491,10 @@ def calc_yoga_pinda(bav_results: Dict, planets: Dict, asc_sign_idx: int) -> Dict
|
||||
}
|
||||
|
||||
|
||||
def calc_sodhita_av(bav_results: Dict, planets: Dict, asc_sign_idx: int) -> Dict:
|
||||
"""
|
||||
计算 Sodhita Ashtakavarga — 净化后的八分行星力量表
|
||||
|
||||
Sodhita 算法(BPHS标准):
|
||||
从每颗行星的每个宫位BAV中,减去Saturn、Mars和Sun的贡献(若结果为负取0)。
|
||||
这反映了"减去凶星影响后的纯净力量"。
|
||||
|
||||
Args:
|
||||
bav_results: calc_ashtakavarga返回的bav结果
|
||||
planets: 行星数据 dict
|
||||
asc_sign_idx: 上升星座索引
|
||||
|
||||
Returns:
|
||||
{
|
||||
'sodhita_bav': {planet: [12个sodhita值]},
|
||||
'sodhita_sav': [12个sodhita SAV值],
|
||||
'reduction_summary': {...}
|
||||
}
|
||||
"""
|
||||
# 1. 获取PAV展开表(需要知道每个贡献源的单独贡献)
|
||||
pav_data = calc_prastara_av(planets, asc_sign_idx)
|
||||
pav = pav_data['pav']
|
||||
|
||||
# 2. 定义需要减去的"凶星"贡献源
|
||||
malefic_sources = ['Saturn', 'Mars', 'Sun']
|
||||
|
||||
# 3. 计算Sodhita BAV
|
||||
sodhita_bav = {}
|
||||
total_reduction = {}
|
||||
|
||||
for planet in SEVEN_PLANETS:
|
||||
if planet not in pav:
|
||||
continue
|
||||
|
||||
# 原始BAV(从所有8个来源)
|
||||
original_bav = [0] * 12
|
||||
for source in ALL_SOURCES:
|
||||
if source in pav.get(planet, {}):
|
||||
for i in range(12):
|
||||
original_bav[i] += pav[planet][source][i]
|
||||
|
||||
# 减去凶星贡献
|
||||
reduction = [0] * 12
|
||||
sodhita = [0] * 12
|
||||
|
||||
for i in range(12):
|
||||
malefic_sum = 0
|
||||
for source in malefic_sources:
|
||||
if source in pav.get(planet, {}):
|
||||
malefic_sum += pav[planet][source][i]
|
||||
|
||||
reduction[i] = malefic_sum
|
||||
sodhita[i] = max(0, original_bav[i] - malefic_sum)
|
||||
|
||||
sodhita_bav[planet] = sodhita
|
||||
total_reduction[planet] = sum(reduction)
|
||||
|
||||
# 4. 计算Sodhita SAV
|
||||
sodhita_sav = [0] * 12
|
||||
for planet in SEVEN_PLANETS:
|
||||
if planet in sodhita_bav:
|
||||
for i in range(12):
|
||||
sodhita_sav[i] += sodhita_bav[planet][i]
|
||||
|
||||
# 5. 评估
|
||||
sodhita_assessment = []
|
||||
for i in range(12):
|
||||
score = sodhita_sav[i]
|
||||
if score >= 25:
|
||||
level = "极吉"
|
||||
elif score >= 22:
|
||||
level = "吉利"
|
||||
elif score >= 19:
|
||||
level = "中等"
|
||||
else:
|
||||
level = "挑战"
|
||||
sodhita_assessment.append({
|
||||
'sign': SIGNS[i],
|
||||
'score': score,
|
||||
'level': level,
|
||||
})
|
||||
|
||||
return {
|
||||
'method': 'Sodhita Ashtakavarga (BPHS标准)',
|
||||
'version': '1.0',
|
||||
'sodhita_bav': sodhita_bav,
|
||||
'sodhita_sav': {
|
||||
'scores': {SIGNS[i]: sodhita_sav[i] for i in range(12)},
|
||||
'assessment': sodhita_assessment,
|
||||
'total': sum(sodhita_sav),
|
||||
},
|
||||
'reduction_summary': total_reduction,
|
||||
'validation_note': 'Sodhita AV ≤ 原始BAV(逐宫位)',
|
||||
}
|
||||
# calc_sodhita_av (removed, BUG-1209): it subtracted the Sun, Mars and Saturn
|
||||
# contributions from every BAV and was labelled "BPHS标准"; that is not the BPHS
|
||||
# Sodhita. The standard chain (Trikona -> Ekadhipatya per BAV row) is
|
||||
# scripts/ashtakavarga_shodhana.py, built on the two functions below.
|
||||
|
||||
|
||||
TRIKONA_SIGN_GROUPS = (
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Standard Ashtakavarga reduction chain for display (ruling 乙8, BUG-1209).
|
||||
|
||||
BAV of each of the seven planets -> Trikona Shodhana -> Ekadhipatya Shodhana ->
|
||||
Sodhita BAV; Sodhita SAV is the sum of the seven reduced BAV rows. The two
|
||||
reductions are `ashtakavarga.calc_trikona_shodhana` (the minimum of each trine
|
||||
removed from its three signs, i.e. PVR rules 1-3) and
|
||||
`ashtakavarga.calc_ekadhipatya_shodhana` (the five dual-lordship sign pairs,
|
||||
PVR rules 1-4), applied to every BAV row as BPHS ch. 67 orders them.
|
||||
|
||||
Occupied signs for Ekadhipatya: signs holding one of the seven grahas (Rahu,
|
||||
Ketu and the Lagna are not counted). PyJHora 4.8.7 counts any non-empty chart
|
||||
cell (nodes, Lagna marker) and reduces only each planet's own sign pair in its
|
||||
own row; both differences are recorded as a question for the astrologer.
|
||||
|
||||
Display only: transit (gochara) scoring keeps the raw BAV bindus (decision
|
||||
record of TASK-astrologer-rulings-batch1-20261003). Raw values are kept beside
|
||||
the reduced ones.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Dict, List
|
||||
|
||||
try: # scripts/ on sys.path
|
||||
from ashtakavarga import SEVEN_PLANETS, SIGNS, calc_ekadhipatya_shodhana, calc_trikona_shodhana
|
||||
except ImportError: # package import
|
||||
from scripts.ashtakavarga import SEVEN_PLANETS, SIGNS, calc_ekadhipatya_shodhana, calc_trikona_shodhana
|
||||
|
||||
METHOD = 'Trikona Shodhana -> Ekadhipatya Shodhana (BPHS ch. 67), per BAV row; Sodhita SAV = sum of reduced BAV'
|
||||
METHOD_ZH = '三方净化 → 单宫主净化(BPHS 第 67 章,逐行 BAV);净化后 SAV = 七星净化后 BAV 之和'
|
||||
|
||||
|
||||
def occupied_signs(planets: Dict[str, Any]) -> set[int]:
|
||||
signs = set()
|
||||
for name in SEVEN_PLANETS:
|
||||
sign = (planets.get(name) or {}).get('sign') if isinstance(planets.get(name), dict) else None
|
||||
if sign in SIGNS:
|
||||
signs.add(SIGNS.index(sign))
|
||||
return signs
|
||||
|
||||
|
||||
def sodhita_chain(bav_results: Dict[str, Any], planets: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Reduced BAV rows and Sodhita SAV from `calc_ashtakavarga(...)['bav']`."""
|
||||
raw: Dict[str, List[int]] = {}
|
||||
for name in SEVEN_PLANETS:
|
||||
bindus = (bav_results.get(name) or {}).get('bindus')
|
||||
if isinstance(bindus, list) and len(bindus) == 12:
|
||||
raw[name] = [int(value) for value in bindus]
|
||||
if len(raw) != len(SEVEN_PLANETS):
|
||||
return {'status': 'blocked', 'reason': 'bav_rows_missing', 'method': METHOD}
|
||||
trikona = {name: calc_trikona_shodhana(row)['reduced_scores'] for name, row in raw.items()}
|
||||
occupied = occupied_signs(planets)
|
||||
ekadhipatya = calc_ekadhipatya_shodhana(trikona, occupied)
|
||||
reduced = ekadhipatya['rows']
|
||||
sav = [sum(reduced[name][index] for name in SEVEN_PLANETS) for index in range(12)]
|
||||
raw_sav = [sum(raw[name][index] for name in SEVEN_PLANETS) for index in range(12)]
|
||||
return {
|
||||
'status': 'executed',
|
||||
'method': METHOD,
|
||||
'method_zh': METHOD_ZH,
|
||||
'source': 'scripts/ashtakavarga_shodhana.py (ashtakavarga.calc_trikona_shodhana + calc_ekadhipatya_shodhana)',
|
||||
'occupied_signs': [SIGNS[index] for index in sorted(occupied)],
|
||||
'raw_bav': raw,
|
||||
'trikona_bav': trikona,
|
||||
'sodhita_bav': reduced,
|
||||
'ekadhipatya_audit': ekadhipatya['audit'],
|
||||
'sodhita_sav': {
|
||||
'scores': {SIGNS[index]: sav[index] for index in range(12)},
|
||||
'assessment': [{'sign': SIGNS[index], 'score': sav[index]} for index in range(12)],
|
||||
'total': sum(sav),
|
||||
},
|
||||
'raw_sav': {'scores': {SIGNS[index]: raw_sav[index] for index in range(12)}, 'total': sum(raw_sav)},
|
||||
'transit_scoring': 'raw BAV bindus (unchanged)',
|
||||
}
|
||||
|
||||
|
||||
def attach_house_values(house_scores: Dict[str, Any], chain: Dict[str, Any]) -> None:
|
||||
"""Add `sav_sodhita` next to the raw `sav_score` of each house row."""
|
||||
if chain.get('status') != 'executed' or not isinstance(house_scores, dict):
|
||||
return
|
||||
scores = chain['sodhita_sav']['scores']
|
||||
for row in house_scores.values():
|
||||
if isinstance(row, dict) and row.get('sign') in scores:
|
||||
row['sav_sodhita'] = scores[row['sign']]
|
||||
@@ -7917,7 +7917,9 @@ class JyotishAPIHandler(BaseHTTPRequestHandler, VedastroEvidenceMixin, SynastryM
|
||||
ashtakavarga = _load_local_module('ashtakavarga')
|
||||
result = ashtakavarga.calc_ashtakavarga(planets, asc_sign_idx)
|
||||
pav = ashtakavarga.calc_prastara_av(planets, asc_sign_idx)
|
||||
sodhita = ashtakavarga.calc_sodhita_av(result.get('bav', {}), planets, asc_sign_idx)
|
||||
# BUG-1209 (乙8): standard Trikona -> Ekadhipatya chain; raw values kept.
|
||||
sodhita = _load_local_module('ashtakavarga_shodhana').sodhita_chain(result.get('bav', {}), planets)
|
||||
_load_local_module('ashtakavarga_shodhana').attach_house_values(result.get('house_scores'), sodhita)
|
||||
yoga_pinda = result.get('yoga_pinda') or ashtakavarga.calc_yoga_pinda(result.get('bav', {}), planets, asc_sign_idx)
|
||||
result['pav'] = pav
|
||||
result['sodhita'] = sodhita
|
||||
@@ -8085,7 +8087,7 @@ class JyotishAPIHandler(BaseHTTPRequestHandler, VedastroEvidenceMixin, SynastryM
|
||||
'available': [
|
||||
{'key': 'sav_bav', 'label': 'SAV/BAV', 'status': 'active', 'source': 'scripts/ashtakavarga.py'},
|
||||
{'key': 'prastara_av', 'label': 'Prastara AV / PAV', 'status': 'active', 'source': 'scripts/ashtakavarga.py'},
|
||||
{'key': 'sodhita_av', 'label': 'Sodhita AV', 'status': 'active', 'source': 'scripts/ashtakavarga.py'},
|
||||
{'key': 'sodhita_av', 'label': 'Sodhita AV (Trikona + Ekadhipatya)', 'status': 'active', 'source': 'scripts/ashtakavarga_shodhana.py'},
|
||||
{'key': 'yoga_pinda', 'label': 'Yoga Pinda', 'status': 'active', 'source': 'scripts/ashtakavarga.py'},
|
||||
],
|
||||
'boundary': '当前按本地 BAV 贡献规则生成 SAV、PAV、Sodhita 与 Yoga Pinda;后续可继续加入 Sarvashtakavarga 规则版本对比。',
|
||||
|
||||
@@ -7513,23 +7513,24 @@ def render_pl9_markdown(packet: dict) -> str:
|
||||
if sodhita_rows:
|
||||
out.extend([
|
||||
'',
|
||||
'#### Sodhita Ashtakavarga(本地减分结果)',
|
||||
'#### Sodhita Ashtakavarga(三方净化 + 单宫主净化)',
|
||||
'',
|
||||
'本表复用既有本地 Sodhita producer,按该 producer 的 Sun / Mars / Saturn 贡献扣减生成。它不等同于 PL9 第 54 页的 Trikona / Ekadhipatya reduction 前后矩阵;逐阶段规则、矩阵与外部数值 parity 未闭环,所有行保持 parameter_sensitive。',
|
||||
'逐行 BAV 先做三方净化(Trikona Shodhana),再做单宫主净化(Ekadhipatya Shodhana),净化后 SAV 为七星净化后 BAV 之和;原始 SAV 并列。外部数值 parity 未闭环,所有行保持 parameter_sensitive。',
|
||||
'',
|
||||
'| 项目 | 数值 | 状态 |',
|
||||
'|------|------|------|',
|
||||
f"| 方法 | {_md_cell(sodhita.get('method'))} | parameter_sensitive |",
|
||||
f"| 总分 | {_md_cell(sodhita_sav.get('total'))} | parameter_sensitive |",
|
||||
f"| 方法 | {_md_cell(sodhita.get('method_zh') or sodhita.get('method'))} | parameter_sensitive |",
|
||||
f"| 净化后总分 | {_md_cell(sodhita_sav.get('total'))} | parameter_sensitive |",
|
||||
'',
|
||||
'| 星座 | Sodhita SAV | 本地等级 | 状态 |',
|
||||
'|------|-------------|----------|------|',
|
||||
'| 星座 | 净化后 SAV | 原始 SAV | 状态 |',
|
||||
'|------|------------|----------|------|',
|
||||
])
|
||||
raw_scores = (sodhita.get('raw_sav') or {}).get('scores') or {}
|
||||
for row in sodhita_rows:
|
||||
if isinstance(row, dict):
|
||||
out.append(
|
||||
f"| {_md_cell(_humanize_reader_token(row.get('sign')))} | {_md_cell(row.get('score'))} | "
|
||||
f"{_md_cell(row.get('level'))} | parameter_sensitive |"
|
||||
f"{_md_cell(raw_scores.get(row.get('sign')))} | parameter_sensitive |"
|
||||
)
|
||||
pav = ashtakavarga.get('pav') if isinstance(ashtakavarga.get('pav'), dict) else {}
|
||||
pav_summary = pav.get('pav_summary') if isinstance(pav.get('pav_summary'), dict) else {}
|
||||
@@ -16490,9 +16491,11 @@ def cmd_full_reading(args):
|
||||
# ── Step 11: Ashtakavarga八分法 ──
|
||||
asht_data = None
|
||||
try:
|
||||
from ashtakavarga import calc_ashtakavarga, calc_prastara_av, calc_sodhita_av
|
||||
from ashtakavarga import calc_ashtakavarga, calc_prastara_av
|
||||
from ashtakavarga_shodhana import attach_house_values, sodhita_chain # BUG-1209
|
||||
asht_data = calc_ashtakavarga(planets, asc_idx)
|
||||
asht_data['sodhita'] = calc_sodhita_av(asht_data.get('bav', {}), planets, asc_idx)
|
||||
asht_data['sodhita'] = sodhita_chain(asht_data.get('bav', {}), planets)
|
||||
attach_house_values(asht_data.get('house_scores'), asht_data['sodhita'])
|
||||
asht_data['pav'] = calc_prastara_av(planets, asc_idx)
|
||||
report['modules']['ashtakavarga'] = asht_data
|
||||
except Exception as e:
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
"""Refresh one leaf of the report density fixture from the real engine (BUG-1209).
|
||||
|
||||
`frontend/tests/fixtures/report-density-fictional-engine.json` is a 2026-09-23
|
||||
real-engine snapshot without a capture script. The Ashtakavarga reduction moved
|
||||
to the standard Trikona -> Ekadhipatya chain, so only
|
||||
`worksheets.strengths_and_scores.ashtakavarga` is recaptured here, from the
|
||||
fixture's own recorded input (fictional, 2000-01-01 12:00 UT, 0/0); every other
|
||||
leaf stays byte-identical.
|
||||
|
||||
PYTHONHASHSEED=0 python3 scripts/research/refresh_density_fixture_ashtakavarga.py
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
sys.path[:0] = [str(ROOT), str(ROOT / "scripts")]
|
||||
|
||||
from scripts.jyotish_engine import build_professional_report_reference_packet, cmd_full_reading # noqa: E402
|
||||
from scripts.professional_report_reference import _export_args # noqa: E402
|
||||
|
||||
FIXTURE = ROOT / "frontend/tests/fixtures/report-density-fictional-engine.json"
|
||||
|
||||
|
||||
def main() -> int:
|
||||
text = FIXTURE.read_text(encoding="utf-8")
|
||||
fixture = json.loads(text)
|
||||
case = dict(fixture["fixtureProvenance"]["input"])
|
||||
case.setdefault("age", int(case["target_year"]) - int(case["year"]))
|
||||
packet = build_professional_report_reference_packet(cmd_full_reading(type("Args", (), dict(case))()), _export_args(dict(case)), [])
|
||||
fixture["worksheets"]["strengths_and_scores"]["ashtakavarga"] = packet["worksheets"]["strengths_and_scores"]["ashtakavarga"]
|
||||
fixture["fixtureProvenance"]["refreshed"] = {
|
||||
"leaf": "worksheets.strengths_and_scores.ashtakavarga",
|
||||
"reason": "BUG-1209 standard Sodhita chain (TASK-astrologer-rulings-batch1-20261003 T7)",
|
||||
"generator": "scripts/research/refresh_density_fixture_ashtakavarga.py",
|
||||
}
|
||||
indent = 2 if text.startswith("{\n ") else None
|
||||
FIXTURE.write_text(json.dumps(fixture, ensure_ascii=False, indent=indent) + ("\n" if text.endswith("\n") else ""), encoding="utf-8")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user