v6.7.4: Shadbala+Yoga集成 + 30项自动化测试

## 精度提升
- API: 集成 calc_shadbala (jyotishganit MIT算法)
- API: 集成 yoga_expansion (dashaflow MIT: Kemadruma/Adhi/Amala等7种)
- API: /api/chart 返回 shadbala 总结 + 扩展瑜伽

## 测试体系
- tests/run_all.py: 30项自动化测试 (30/30 )
- 覆盖: 20个模块导入 + 10个功能验证
- 包含: PAV验证/Shadbala不变性/KP/合盘/SadeSati/补救/Muhurta
This commit is contained in:
732642856
2026-06-11 21:12:44 +08:00
parent 16feaa1e85
commit 38dc31df24
2 changed files with 175 additions and 4 deletions
+19 -4
View File
@@ -174,13 +174,28 @@ class JyotishAPIHandler(BaseHTTPRequestHandler):
dashas = get_available_dashas()
dasha_list = [{'key': k, 'name': DASHA_REGISTRY[k]['name'], 'years': DASHA_REGISTRY[k]['years'], 'type': DASHA_REGISTRY[k]['type']} for k in dashas]
# Shadbala (v6.7.4: jyotishganit MIT算法)
try:
from shadbala import calc_shadbala
sb = calc_shadbala(planets_data, asc_sign, hour+minute/60.0,
planets_data.get('Sun',{}).get('lon',0), moon_lon, minute)
shadbala_summary = {p: {'rupas': round(d['total_rupas'],2), 'level': d['strength_level']}
for p,d in sb.get('planets',{}).items()}
except: shadbala_summary = {}
# Yoga扩展 (dashaflow MIT规则)
try:
from yoga_expansion import detect_all_yogas as detect_ey
for ey in detect_ey(planets_data, asc_sign):
yogas.append({'name': ey.get('name',''), 'planets': ey.get('planets',[]),
'desc': ey.get('description','')[:80], 'cat': 'extended'})
except: pass
return {
'success': True,
'version': '6.7.3',
'success': True, 'version': '6.7.4',
'birth': {'date': f'{year}-{month:02d}-{day:02d}', 'time': f'{int(hour):02d}:{int(minute):02d}'},
'ascendant': {'sign': asc_sign, 'sign_idx': asc_sign_idx, 'degree': round(asc_lon % 30, 2)},
'planets': planets_data,
'houses': houses,
'planets': planets_data, 'houses': houses, 'shadbala': shadbala_summary,
'dasha': {
'current_md': md_lord,
'remaining_years': round(remaining, 2),
+156
View File
@@ -0,0 +1,156 @@
#!/usr/bin/env python3
"""印度占星Skill自动化测试运行器 v1.0"""
import sys, os, time
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'scripts'))
TESTS = []
def test(name):
def decorator(fn): TESTS.append((name, fn)); return fn
return decorator
# === 模块导入测试 ===
@test("ashtakavarga import")
def t1(): from ashtakavarga import calc_ashtakavarga, calc_prastara_av, calc_sodhita_av
@test("shadbala import")
def t2(): from shadbala import calc_shadbala
@test("jaimini import")
def t3(): from jaimini import _chara_dasha_duration_knrao, _resolve_chara_dasha_lord
@test("bhava_bala import")
def t4(): from bhava_bala import calc_bhava_bala
@test("kakshya import")
def t5(): from kakshya import calc_kakshya_scores, get_kakshya_lord
@test("kp_system import")
def t6(): from kp_system import get_kp_lords, calc_kp_analysis
@test("synastry import")
def t7(): from synastry import calc_ashtakoot
@test("prashna import")
def t8(): from prashna import calc_prashna_chart, get_kp_prashna_answer
@test("remedies import")
def t9(): from remedies import recommend_remedies, quick_remedy
@test("pancha_mahapurusha import")
def t10(): from pancha_mahapurusha import detect_pancha_mahapurusha
@test("sade_sati import")
def t11(): from sade_sati import calc_sade_sati_complete
@test("sudarshana_chakra import")
def t12(): from sudarshana_chakra import calc_sudarshana_chakra
@test("career_analysis import")
def t13(): from career_analysis import analyze_career
@test("relationship_analysis import")
def t14(): from relationship_analysis import analyze_relationship
@test("muhurtha_election import")
def t15(): from muhurtha_election import evaluate_muhurtha
@test("yoga_expansion import")
def t16(): from yoga_expansion import detect_all_yogas
@test("birth_time_rectifier import")
def t17(): from birth_time_rectifier import check_lagna_boundary, get_effective_accuracy
@test("conditional_dashas import")
def t18(): from conditional_dashas import calc_dwisaptati_dasha, check_dwisaptati_condition
@test("extended_dashas import")
def t19(): from extended_dashas import get_available_dashas, DASHA_REGISTRY
@test("chart_renderer import")
def t20(): from chart_renderer import render_south_indian_chart, render_html_report
# === 功能测试 ===
@test("PAV validation")
def t21():
from ashtakavarga import calc_prastara_av, SEVEN_PLANETS
planets = {p: {'sign': 'Aries', 'degree': i*40} for i,p in enumerate(SEVEN_PLANETS)}
pav = calc_prastara_av(planets, 0)
assert pav['all_valid'], "PAV validation failed"
@test("Shadbala invariant")
def t22():
from shadbala import calc_shadbala
p = {pn: {'sign': 'Aries', 'degree': i*40, 'house': i+1} for i,pn in enumerate(['Sun','Moon','Mars','Mercury','Jupiter','Venus','Saturn'])}
result = calc_shadbala(p, 'Aries', 12, 15, 45, 0)
assert len(result['planets']) == 7
@test("KP sublord")
def t23():
from kp_system import get_kp_lords
r = get_kp_lords(15.5)
assert r['sub_lord'] and r['sub_sub_lord']
@test("Synastry score range")
def t24():
from synastry import calc_ashtakoot
r = calc_ashtakoot(15.5, 120)
assert 0 <= r['total_score'] <= 36
@test("Sade Sati detection")
def t25():
from sade_sati import calc_sade_sati
r = calc_sade_sati('Aries', 'Aries')
assert r['active'] and r['phase'] == 'peak'
@test("Remedies generation")
def t26():
from remedies import recommend_remedies
sb = {'Sun': {'total_rupas': 0.4}, 'Saturn': {'total_rupas': 0.3}}
r = recommend_remedies(sb, doshas=['Mangal Dosha'])
assert len(r['recommendations']['gems']) >= 1
@test("Muhurtha evaluation")
def t27():
from muhurtha_election import evaluate_muhurtha
r = evaluate_muhurtha('marriage', 3, 'Rohini', 4, 'Monday', 'Taurus')
assert r['verdict'] in ('大吉', '尚可', '中性', '不吉')
@test("Dasha count")
def t28():
from extended_dashas import get_available_dashas
assert len(get_available_dashas()) >= 30, "Dasha count should be >= 30"
@test("Rectifier boundary check")
def t29():
from birth_time_rectifier import check_lagna_boundary
is_b, _ = check_lagna_boundary(1.5)
assert is_b
@test("PMC detection")
def t30():
from pancha_mahapurusha import detect_pancha_mahapurusha
p = {'Mars': {'sign': 'Capricorn', 'house': 4, 'degree': 280}}
r = detect_pancha_mahapurusha(p)
assert len(r) >= 1
# === 运行 ===
if __name__ == '__main__':
passed = 0; failed = 0; start = time.time()
print(f"\n{'='*50}")
print(f"🔮 Jyotish Skill Test Suite v1.0 — {len(TESTS)} tests")
print(f"{'='*50}")
for name, fn in TESTS:
try:
fn()
passed += 1
print(f"{name}")
except Exception as e:
failed += 1
print(f"{name}: {str(e)[:60]}")
t = time.time() - start
print(f"\n{'='*50}")
print(f" Passed: {passed}/{len(TESTS)} ({passed/len(TESTS)*100:.0f}%)")
print(f" Failed: {failed}")
print(f" Time: {t:.1f}s")
sys.exit(0 if failed == 0 else 1)