From 38dc31df2442c03a7648d7e1b1ef671136c22535 Mon Sep 17 00:00:00 2001 From: 732642856 <732642856@qq.com> Date: Thu, 11 Jun 2026 21:12:44 +0800 Subject: [PATCH] =?UTF-8?q?v6.7.4:=20Shadbala+Yoga=E9=9B=86=E6=88=90=20+?= =?UTF-8?q?=2030=E9=A1=B9=E8=87=AA=E5=8A=A8=E5=8C=96=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 精度提升 - 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 --- scripts/jyotish_api_server.py | 23 ++++- tests/run_all.py | 156 ++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+), 4 deletions(-) create mode 100644 tests/run_all.py diff --git a/scripts/jyotish_api_server.py b/scripts/jyotish_api_server.py index 81c67d38..2e38b73a 100644 --- a/scripts/jyotish_api_server.py +++ b/scripts/jyotish_api_server.py @@ -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), diff --git a/tests/run_all.py b/tests/run_all.py new file mode 100644 index 00000000..cb794b9d --- /dev/null +++ b/tests/run_all.py @@ -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)