Files
Jyotisha/references/open_source_sources/jaimini-tropical/jaimini_gui.py
T
732642856 f83db2fac1 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
2026-06-10 20:50:52 +08:00

162 lines
6.1 KiB
Python

"""Jaimini Tropical Astrology — Windows GUI
tkinter-based GUI for the Jaimini engine. Packaged as .exe via PyInstaller.
"""
import sys
import os
import tkinter as tk
from tkinter import ttk, scrolledtext, messagebox
from datetime import datetime
import io
from contextlib import redirect_stdout
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from jaimini.chart.chart import Chart
from jaimini.engine.time_utils import parse_dms, parse_timezone
from jaimini.core.karakas import karaka_report
from jaimini.core.dashas import format_dasha_table
DEFAULTS = {
"date": "1949-10-01",
"time": "15:00:00",
"tz": "+8",
"lat": "39.907",
"lon": "116.397",
"name": "",
}
class JaiminiApp:
def __init__(self, root):
self.root = root
root.title("Jaimini 回归黄道占星引擎")
root.geometry("780x720")
root.resizable(True, True)
# Input frame
input_frame = ttk.LabelFrame(root, text="输入参数", padding=10)
input_frame.pack(fill=tk.X, padx=10, pady=5)
# Row 0: Date, Time, Timezone
row0 = ttk.Frame(input_frame)
row0.pack(fill=tk.X, pady=2)
ttk.Label(row0, text="日期 (YYYY-MM-DD):", width=22).pack(side=tk.LEFT)
self.date_var = tk.StringVar(value=DEFAULTS["date"])
ttk.Entry(row0, textvariable=self.date_var, width=14).pack(side=tk.LEFT, padx=2)
ttk.Label(row0, text="时间 (HH:MM:SS):", width=18).pack(side=tk.LEFT, padx=(15, 0))
self.time_var = tk.StringVar(value=DEFAULTS["time"])
ttk.Entry(row0, textvariable=self.time_var, width=12).pack(side=tk.LEFT, padx=2)
ttk.Label(row0, text="时区:", width=5).pack(side=tk.LEFT, padx=(15, 0))
self.tz_var = tk.StringVar(value=DEFAULTS["tz"])
ttk.Entry(row0, textvariable=self.tz_var, width=6).pack(side=tk.LEFT, padx=2)
# Row 1: Latitude, Longitude, Name
row1 = ttk.Frame(input_frame)
row1.pack(fill=tk.X, pady=2)
ttk.Label(row1, text="纬度 (dec or DMS):", width=22).pack(side=tk.LEFT)
self.lat_var = tk.StringVar(value=DEFAULTS["lat"])
ttk.Entry(row1, textvariable=self.lat_var, width=14).pack(side=tk.LEFT, padx=2)
ttk.Label(row1, text="经度 (dec or DMS):", width=18).pack(side=tk.LEFT, padx=(15, 0))
self.lon_var = tk.StringVar(value=DEFAULTS["lon"])
ttk.Entry(row1, textvariable=self.lon_var, width=12).pack(side=tk.LEFT, padx=2)
ttk.Label(row1, text="名称:", width=5).pack(side=tk.LEFT, padx=(15, 0))
self.name_var = tk.StringVar(value=DEFAULTS["name"])
ttk.Entry(row1, textvariable=self.name_var, width=14).pack(side=tk.LEFT, padx=2)
# Row 2: Options
row2 = ttk.Frame(input_frame)
row2.pack(fill=tk.X, pady=5)
self.rahu_var = tk.BooleanVar(value=False)
ttk.Checkbutton(row2, text="含 Rahu (8 Karaka)", variable=self.rahu_var).pack(side=tk.LEFT)
self.dasha_var = tk.BooleanVar(value=False)
ttk.Checkbutton(row2, text="仅 Dasha", variable=self.dasha_var).pack(side=tk.LEFT, padx=(15, 0))
self.karaka_var = tk.BooleanVar(value=False)
ttk.Checkbutton(row2, text="仅 Karaka", variable=self.karaka_var).pack(side=tk.LEFT, padx=(15, 0))
# Buttons
btn_frame = ttk.Frame(input_frame)
btn_frame.pack(fill=tk.X, pady=5)
self.calc_btn = ttk.Button(btn_frame, text="计算星盘", command=self.calculate)
self.calc_btn.pack(side=tk.LEFT, padx=5)
ttk.Button(btn_frame, text="清空", command=self.clear).pack(side=tk.LEFT, padx=5)
ttk.Button(btn_frame, text="复制结果", command=self.copy_result).pack(side=tk.LEFT, padx=5)
# Output area
out_frame = ttk.LabelFrame(root, text="计算结果", padding=5)
out_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
self.output = scrolledtext.ScrolledText(
out_frame, wrap=tk.NONE, font=("Consolas", 10), bg="#1e1e1e", fg="#d4d4d4"
)
self.output.pack(fill=tk.BOTH, expand=True)
self.output.insert(tk.END, "就绪。请输入出生数据,点击「计算星盘」。\n")
# Status bar
self.status = ttk.Label(root, text="就绪", relief=tk.SUNKEN, anchor=tk.W)
self.status.pack(fill=tk.X, padx=10, pady=(0, 5))
def calculate(self):
self.calc_btn.config(state=tk.DISABLED)
self.status.config(text="计算中...")
self.output.delete(1.0, tk.END)
self.root.update()
try:
dt = datetime.strptime(
f"{self.date_var.get()} {self.time_var.get()}", "%Y-%m-%d %H:%M:%S"
)
lat = parse_dms(self.lat_var.get())
lon = parse_dms(self.lon_var.get())
tz = parse_timezone(self.tz_var.get())
name = self.name_var.get() or None
chart = Chart(
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second,
lat, lon, tz, name=name
)
buf = io.StringIO()
with redirect_stdout(buf):
if self.karaka_var.get():
karakas = chart.karakas_8 if self.rahu_var.get() else chart.karakas_7
print(karaka_report(karakas))
elif self.dasha_var.get():
print(format_dasha_table(chart.chara_dasha, include_antar=True))
else:
print(chart.summary())
self.output.insert(tk.END, buf.getvalue())
self.status.config(text="计算完成")
except Exception as e:
messagebox.showerror("错误", str(e))
self.status.config(text=f"错误: {e}")
self.calc_btn.config(state=tk.NORMAL)
def clear(self):
self.output.delete(1.0, tk.END)
self.output.insert(tk.END, "就绪。\n")
self.status.config(text="就绪")
def copy_result(self):
text = self.output.get(1.0, tk.END)
self.root.clipboard_clear()
self.root.clipboard_append(text)
self.status.config(text="结果已复制到剪贴板")
def main():
root = tk.Tk()
app = JaiminiApp(root)
root.mainloop()
if __name__ == "__main__":
main()