import os, datetime, math
import numpy as np
import customtkinter as ctk
from skyfield.api import Loader, wgs84
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
class Menu10App(ctk.CTk):
def __init__(self):
super().__init__()
self.title("Rashdul Qiblah Lokal (Modul 10)")
self.geometry("800x500")
ctk.set_appearance_mode("Dark")
# --- PERBAIKAN SKYFIELD LOADER DI SINI ---
self.load_obj = Loader(BASE_DIR)
self.eph = self.load_obj('de421.bsp')
self.ts = self.load_obj.timescale()
# -----------------------------------------
self.setup_ui()
def setup_ui(self):
self.sidebar = ctk.CTkFrame(self, width=200)
self.sidebar.pack(side="left", fill="y", padx=10, pady=10)
now = datetime.datetime.now()
self.entry_d = ctk.CTkEntry(self.sidebar); self.entry_d.insert(0, str(now.day)); self.entry_d.pack(pady=5)
self.entry_m = ctk.CTkEntry(self.sidebar); self.entry_m.insert(0, str(now.month)); self.entry_m.pack(pady=5)
self.entry_y = ctk.CTkEntry(self.sidebar); self.entry_y.insert(0, str(now.year)); self.entry_y.pack(pady=5)
self.entry_lat = ctk.CTkEntry(self.sidebar); self.entry_lat.insert(0, "-7.0667"); self.entry_lat.pack(pady=5)
self.entry_lon = ctk.CTkEntry(self.sidebar); self.entry_lon.insert(0, "110.4100"); self.entry_lon.pack(pady=5)
ctk.CTkButton(self.sidebar, text="▶ CARI WAKTU KIBLAT", command=self.hitung).pack(pady=20)
self.textbox = ctk.CTkTextbox(self, font=("Consolas", 14))
self.textbox.pack(side="right", fill="both", expand=True, padx=10, pady=10)
def hitung(self):
self.textbox.delete("1.0", "end")
d, m, y = int(self.entry_d.get()), int(self.entry_m.get()), int(self.entry_y.get())
lat, lon = float(self.entry_lat.get()), float(self.entry_lon.get())
tz = 7.0
# Hitung Azimut Kiblat
phi_k, lam_k = math.radians(21.4225), math.radians(39.8262) # Ka'bah
phi, lam = math.radians(lat), math.radians(lon)
y_q = math.sin(lam_k - lam)
x_q = math.cos(phi)*math.tan(phi_k) - math.sin(phi)*math.cos(lam_k-lam)
q_az = math.degrees(math.atan2(y_q, x_q)) % 360
shadow_az = (q_az + 180) % 360
loc = wgs84.latlon(lat, lon)
t0 = self.ts.utc(y, m, d, -int(tz))
t1 = self.ts.utc(y, m, d, 24-int(tz))
tt_array = np.linspace(t0.tt, t1.tt, 1440)
t_search = self.ts.tt_jd(tt_array)
obs = (self.eph['earth'] + loc).at(t_search).observe(self.eph['sun']).apparent()
alt_arr, az_arr, _ = obs.altaz()
az_deg_list, alt_deg_list = az_arr.degrees, alt_arr.degrees
def find_crossing_times(target_az):
diffs = (az_deg_list - target_az + 180) % 360 - 180
results = []
for i in range(len(diffs)-1):
if (diffs[i] <= 0 and diffs[i+1] > 0) or (diffs[i] >= 0 and diffs[i+1] < 0):
if alt_deg_list[i] > 0: # Hanya jika matahari di atas ufuk
frac = abs(diffs[i]) / (abs(diffs[i]) + abs(diffs[i+1]) + 1e-9)
tt_res = tt_array[i] + frac * (tt_array[i+1] - tt_array[i])
t_final = self.ts.tt_jd(tt_res + (tz / 24.0))
_, _, _, h, mn, s = t_final.utc
results.append(f"{int(h):02d}:{int(mn):02d}:{int(s):02d}")
return results
res_sun = ", ".join(find_crossing_times(q_az)) or "----"
res_shd = ", ".join(find_crossing_times(shadow_az)) or "----"
report = f"RASHDUL QIBLAH LOKAL (Waktu Kiblat)\n{'='*50}\n"
report += f"Tanggal : {d:02d}/{m:02d}/{y}\n"
report += f"Arah Kiblat : {q_az:.2f}°\n"
report += f"Arah Bayangan: {shadow_az:.2f}°\n"
report += "-"*50 + "\n\n"
report += f"1. Waktu Matahari Tepat di Arah Kiblat:\n >> {res_sun} LT\n\n"
report += f"2. Waktu Bayangan Tepat di Arah Kiblat:\n >> {res_shd} LT\n\n"
report += "Catatan: Gunakan benda tegak lurus untuk melihat bayangan."
self.textbox.insert("1.0", report)
if __name__ == "__main__":
app = Menu10App()
app.mainloop()