定位中... V24.FullInfo

正在加载高精度天文库...

packages = ["./lunar_python-1.4.8-py3-none-any.whl"] import datetime import math import js import json from lunar_python import Lunar, Solar # --- 1. 基础数据 --- GAN = ["甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸"] ZHI = ["子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥"] STARS = ['', '天蓬', '天芮', '天冲', '天辅', '天禽', '天心', '天柱', '天任', '天英'] DOORS = ['', '休门', '死门', '伤门', '杜门', '', '开门', '惊门', '生门', '景门'] GODS = ['值符', '螣蛇', '太阴', '六合', '白虎', '玄武', '九地', '九天'] TERM_NAMES = ['冬至','小寒','大寒','立春','雨水','惊蛰','春分','清明','谷雨','立夏','小满','芒种','夏至','小暑','大暑','立秋','处暑','白露','秋分','寒露','霜降','立冬','小雪','大雪'] JU_MAP = { '冬至':[1,7,4], '小寒':[2,8,5], '大寒':[3,9,6], '立春':[8,5,2], '雨水':[9,6,3], '惊蛰':[1,7,4], '春分':[3,9,6], '清明':[4,1,7], '谷雨':[5,2,8], '立夏':[4,1,7], '小满':[5,2,8], '芒种':[6,3,9], '夏至':[9,3,6], '小暑':[8,2,5], '大暑':[7,1,4], '立秋':[2,5,8], '处暑':[1,4,7], '白露':[9,3,6], '秋分':[7,1,4], '寒露':[6,9,3], '霜降':[5,8,2], '立冬':[6,9,3], '小雪':[5,8,2], '大雪':[4,7,1] } # --- 2. 天文算法 (VSOP87) --- class PreciseAstronomy: @staticmethod def get_lon(dt): y, m, d = dt.year, dt.month, dt.day h = dt.hour + dt.minute/60.0 + dt.second/3600.0 if m <= 2: y -= 1; m += 12 jd = int(365.25 * (y + 4716)) + int(30.6001 * (m + 1)) + d + h/24.0 + 2 - int(y/100) + int(int(y/100)/4) - 1524.5 tau = (jd - 2451545.0) / 365250.0 L0 = 175347046.0 + 3341656.0 * math.cos(4.6692568 + 6283.07585 * tau) L = (L0 * 1e-8 + math.radians(280.46646 + 36000.76983 * tau)) return (math.degrees(L) + 0.0) % 360.0 class QimenEngine: def run(self, year, month, day, hour, minute, lat, lon): solar = Solar.fromYmdHms(year, month, day, hour, minute, 0) lunar = solar.getLunar() gz = lunar.getEightChar() dt_obj = datetime.datetime(year, month, day, hour, minute) doy = dt_obj.timetuple().tm_yday b = (2 * math.pi / 365.24) * (doy - 81) eot = 9.87 * math.sin(2*b) - 7.53 * math.cos(b) - 1.5 * math.sin(b) tst = dt_obj + datetime.timedelta(minutes=eot + (lon-120)*4) slon = PreciseAstronomy.get_lon(tst) dubhe = (slon + 90.0) % 360.0 jiang_idx = (11 - int((slon + 30)/30)) % 12 yue_jiang = ZHI[jiang_idx] current_jieqi = lunar.getPrevJieQi(True) term_name = current_jieqi.getName() day_gan_idx = GAN.index(gz.getDayGan()) day_idx = -1 for i in range(60): if GAN[i%10] == gz.getDayGan() and ZHI[i%12] == gz.getDayZhi(): day_idx = i break diff = day_gan_idx % 5 futou_idx = (day_idx - diff) % 60 futou_zhi = ZHI[futou_idx % 12] yuan = 2 if futou_zhi in ['子', '午', '卯', '酉']: yuan = 0 elif futou_zhi in ['寅', '申', '巳', '亥']: yuan = 1 ju = JU_MAP.get(term_name, [1,1,1])[yuan] yang_terms = ['冬至','小寒','大寒','立春','雨水','惊蛰','春分','清明','谷雨','立夏','小满','芒种'] is_yang = term_name in yang_terms real_yang = is_yang if lat >= 0 else not is_yang # 地盘 stems = ['戊', '己', '庚', '辛', '壬', '癸', '丁', '丙', '乙'] dp = {} for i, s in enumerate(stems): pos = ((ju - 1 + i)%9)+1 if real_yang else ((ju - 1 - i)%9)+1 if pos == 0: pos = 9 dp[pos] = s h_gan = gz.getTimeGan() h_zhi = gz.getTimeZhi() h_zhi_idx = ZHI.index(h_zhi) g_i = GAN.index(h_gan) head_zhi_idx = (h_zhi_idx - g_i) % 12 xun_map = {0:'戊', 10:'己', 8:'庚', 6:'辛', 4:'壬', 2:'癸'} xun_gan = xun_map.get(head_zhi_idx, '戊') pos_xun = 1 for p, s in dp.items(): if s == xun_gan: pos_xun = p; break zhifu_star = STARS[pos_xun] zhishi_door = DOORS[pos_xun] if pos_xun != 5 else "死门" if pos_xun == 5: pos_xun = 2 target_stem = h_gan if h_gan == '甲': target_stem = xun_gan pos_sky_dest = 1 for p, s in dp.items(): if s == target_stem: pos_sky_dest = p; break path = [1,8,3,4,9,2,7,6] full_grid = {} for i in range(1, 10): full_grid[i] = {"stem_d": dp.get(i, ""), "stem_t": "", "star": "", "door": "", "god": ""} # 八神 try: start_idx = path.index(pos_sky_dest) except: start_idx = 0 for i in range(8): g_idx = i if real_yang: p_idx = (start_idx + i) % 8 else: p_idx = (start_idx - i) % 8 full_grid[path[p_idx]]["god"] = GODS[g_idx] # 星 & 干 target_star_name = zhifu_star if target_star_name == "天禽": target_star_name = "天芮" base_stars = ["天蓬","天任","天冲","天辅","天英","天芮","天柱","天心"] try: s_idx = base_stars.index(target_star_name) except: s_idx = 0 for i in range(8): curr_star = base_stars[(s_idx + i) % 8] curr_palace = path[(start_idx + i) % 8] full_grid[curr_palace]["star"] = curr_star if curr_star == "天芮": full_grid[curr_palace]["star"] = "天芮(禽)" orig_p = { "天蓬":1, "天任":8, "天冲":3, "天辅":4, "天英":9, "天芮":2, "天柱":7, "天心":6 }.get(curr_star, 1) full_grid[curr_palace]["stem_t"] = dp.get(orig_p, "") # 门 step = (h_zhi_idx - head_zhi_idx) % 12 try: door_start_palace = pos_xun if door_start_palace == 5: door_start_palace = 2 d_start_idx = path.index(door_start_palace) except: d_start_idx = 0 fly_step = step if real_yang else -step dest_idx = (d_start_idx + fly_step) % 8 base_doors = ["休门","生门","伤门","杜门","景门","死门","惊门","开门"] try: bd_idx = base_doors.index(zhishi_door) except: bd_idx = 5 for i in range(8): curr_door = base_doors[(bd_idx + i) % 8] curr_p = path[(dest_idx + i) % 8] full_grid[curr_p]["door"] = curr_door return json.dumps({ "lunar": f"{gz.getYear()}年 {lunar.toString()}", "ganzhi": f"{gz.getYear()} {gz.getMonth()} {gz.getDay()} {gz.getTime()}", "jieqi": f"{term_name} (拆补法)", "kongwang": f"日空 {lunar.getDayXunKong()}", "info": { "lon": f"{slon:.2f}°", "dubhe": f"{dubhe:.2f}°", "eot": f"{eot + (lon-120)*4:.1f}m", "coords": f"{lat:.1f}, {lon:.1f}" }, "ju": { "name": f"{'阳' if real_yang else '阴'}遁{ju}局 {['上','中','下'][yuan]}元", "zhifu": zhifu_star, "zhishi": zhishi_door, "jiang": yue_jiang }, "grid": full_grid }) engine = QimenEngine() def python_entry(y, m, d, h, minute, lat, lon): try: res = engine.run(int(y), int(m), int(d), int(h), int(minute), float(lat), float(lon)) js.render_result(res) except Exception as e: js.alert("Python Error: " + str(e)) js.window.python_entry = python_entry js.window.init_complete()