Enhance Jyotish validation and Jaimini modules

- add external validation reports and open-source comparison references

- integrate Jaimini arudha/graha pada, enhanced argala, and additional synastry kutas

- update skill docs and capability matrices

- add smoke tests for open-source integrations
This commit is contained in:
732642856
2026-06-10 20:50:52 +08:00
parent d178292208
commit f83db2fac1
134 changed files with 28023 additions and 508 deletions
+137
View File
@@ -0,0 +1,137 @@
#!/usr/bin/env python3
"""Indastro 验证脚本 - 对比引擎输出与 Indastro.com 参考值"""
import json
import subprocess
import sys
import os
from datetime import datetime
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SKILL_DIR = os.path.dirname(SCRIPT_DIR)
ENGINE = os.path.join(SKILL_DIR, 'scripts', 'jyotish_engine.py')
CASES_FILE = os.path.join(SCRIPT_DIR, 'indastro_cases.json')
def run_engine(year, month, day, hour, minute, lat, lon, tz):
cmd = [
sys.executable, ENGINE, 'chart',
'--year', str(year), '--month', str(month), '--day', str(day),
'--hour', str(hour), '--minute', str(minute),
'--lat', str(lat), '--lon', str(lon), '--tz', str(tz)
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=30)
return json.loads(result.stdout)
def format_degree(sign, deg):
return f"{sign} {deg:.2f}°"
def main():
with open(CASES_FILE) as f:
cases = json.load(f)
results = []
passes = 0
fails = 0
print("=" * 90)
print("INDSTRO 验证报告")
print(f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 90)
print(f"{'案例':<20s} | {'tz':>5s} | {'状态':<6s} | Lagna (引擎 vs Indastro)")
print("-" * 90)
for c in cases:
try:
data = run_engine(
c['year'], c['month'], c['day'],
c['hour'], c['minute'],
c['lat'], c['lon'], c['tz']
)
except Exception as e:
print(f"{c['name']:<20s} | {c['tz']:+5.1f} | ERROR | {e}")
continue
eng = {
'lagna': data['ascendant']['sign'],
'lagna_deg': data['ascendant']['degree'],
'sun': data['planets']['Sun']['sign'],
'sun_deg': data['planets']['Sun']['degree'],
'moon': data['planets']['Moon']['sign'],
'moon_deg': data['planets']['Moon']['degree'],
}
lagna_ok = eng['lagna'] == c['expected_lagna']
sun_ok = eng['sun'] == c['expected_sun']
moon_ok = eng['moon'] == c['expected_moon']
all_ok = lagna_ok and sun_ok and moon_ok
if all_ok:
passes += 1
else:
fails += 1
status = 'PASS' if all_ok else 'FAIL'
# Build lagna comparison
if 'expected_lagna_degree' in c:
lagna_str = f"{eng['lagna']} {eng['lagna_deg']:.2f}° vs {c['expected_lagna']} {c['expected_lagna_degree']:.2f}°"
else:
lagna_str = f"{eng['lagna']} vs {c['expected_lagna']}"
print(f"{c['name']:<20s} | {c['tz']:+5.1f} | {status:<6s} | {lagna_str}")
# Details for failures
if not all_ok:
issues = []
if not lagna_ok:
issues.append(f"Lagna: {eng['lagna']} ≠ {c['expected_lagna']}")
if not sun_ok:
issues.append(f"Sun: {eng['sun']} ≠ {c['expected_sun']}")
if not moon_ok:
issues.append(f"Moon: {eng['moon']} ≠ {c['expected_moon']}")
for issue in issues:
print(f" {'':20s} {'':6s} ✗ {issue}")
if 'tz_note' in c:
print(f" {'':20s} {'':6s} ℹ {c['tz_note'][:100]}")
print("-" * 90)
total = passes + fails
print(f"总计: {total} | 通过: {passes} | 失败: {fails} | 通过率: {passes/total*100:.1f}%")
print("=" * 90)
# Detailed report
print("\n## 失败案例详情\n")
for c in cases:
try:
data = run_engine(
c['year'], c['month'], c['day'],
c['hour'], c['minute'],
c['lat'], c['lon'], c['tz']
)
except:
continue
eng = {
'lagna': data['ascendant']['sign'],
'lagna_deg': data['ascendant']['degree'],
'sun': data['planets']['Sun']['sign'],
'sun_deg': data['planets']['Sun']['degree'],
'moon': data['planets']['Moon']['sign'],
'moon_deg': data['planets']['Moon']['degree'],
}
if eng['lagna'] != c['expected_lagna'] or eng['sun'] != c['expected_sun'] or eng['moon'] != c['expected_moon']:
print(f"### {c['name']} ({c['id']})")
print(f"- 出生: {c['year']}-{c['month']:02d}-{c['day']:02d} {c['hour']:02d}:{c['minute']:02d} UTC{c['tz']:+.0f}")
print(f"- 坐标: ({c['lat']}, {c['lon']})")
print(f"- Lagna: 引擎={format_degree(eng['lagna'], eng['lagna_deg'])} | Indastro={c['expected_lagna']}")
if 'expected_lagna_degree' in c:
print(f" 差值: {abs(eng['lagna_deg'] - c['expected_lagna_degree']):.2f}°")
print(f"- Sun: 引擎={format_degree(eng['sun'], eng['sun_deg'])} | Indastro={c['expected_sun']}")
print(f"- Moon: 引擎={format_degree(eng['moon'], eng['moon_deg'])} | Indastro={c['expected_moon']}")
if 'tz_note' in c:
print(f"- 时区说明: {c['tz_note']}")
print()
if __name__ == '__main__':
main()