menu5.py

Download
import os, datetime, math
import customtkinter as ctk
from tkinter import messagebox
import ephem
from skyfield.api import Loader
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from PIL import Image

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# ---> COPAS CITY_DB LENGKAP DARI KODE MASTER ANDA DI SINI <---
CITY_DB = {
    "Selandia Baru": {"Gisborne": (-38.6623, 178.0176)},
    "Amerika Serikat": {"Los Angeles": (34.0522, -118.2437)},
    "Jawa Tengah": {"Semarang": (-7.0667, 110.4100)} 
} 

class Menu5App(ctk.CTk):
    def __init__(self):
        super().__init__()
        self.title("Titik Pertama KHGT (Modul 5)")
        self.geometry("1100x700")
        ctk.set_appearance_mode("Dark")
        
        self.load_obj = Loader(BASE_DIR, verbose=False)
        self.ts = self.load_obj.timescale()
        self.eph = self.load_obj('de421.bsp')
        
        self.setup_ui()

    def setup_ui(self):
        self.sidebar = ctk.CTkFrame(self, width=250)
        self.sidebar.pack(side="left", fill="y", padx=10, pady=10)

        ctk.CTkLabel(self.sidebar, text="KOTA PERTAMA KHGT", font=("Segoe UI", 16, "bold")).pack(pady=20)
        
        row = ctk.CTkFrame(self.sidebar, fg_color="transparent")
        row.pack()
        self.entry_d = ctk.CTkEntry(row, width=40); self.entry_d.insert(0, "17"); self.entry_d.pack(side="left", padx=2)
        self.entry_m = ctk.CTkEntry(row, width=40); self.entry_m.insert(0, "2"); self.entry_m.pack(side="left", padx=2)
        self.entry_y = ctk.CTkEntry(row, width=60); self.entry_y.insert(0, "2026"); self.entry_y.pack(side="left", padx=2)
        
        ctk.CTkButton(self.sidebar, text="▶ LACAK GLOBAL", command=self.lacak).pack(pady=20)
        self.main_frame = ctk.CTkFrame(self)
        self.main_frame.pack(side="right", fill="both", expand=True, padx=10, pady=10)

    def lacak(self):
        for w in self.main_frame.winfo_children(): w.destroy()
        
        y, m, d = int(self.entry_y.get()), int(self.entry_m.get()), int(self.entry_d.get())
        waktu_tuple = (y, m, d, 12, 0, 0)
        
        matahari, bulan = ephem.Sun(), ephem.Moon()
        ijtimak_1 = ephem.previous_new_moon(waktu_tuple)
        
        titik_hasil = []
        # Pencarian brute-force
        for offset_hari in range(4):
            kandidat = []
            waktu_pencarian = ephem.Date(ijtimak_1 + offset_hari)
            for negara, kota_dict in CITY_DB.items():
                for nama_kota, koordinat in kota_dict.items():
                    pengamat = ephem.Observer()
                    pengamat.lat, pengamat.lon = str(koordinat[0]), str(koordinat[1])
                    pengamat.date = waktu_pencarian
                    try: 
                        ws = pengamat.next_setting(matahari)
                        pengamat.date = ws
                        matahari.compute(pengamat)
                        bulan.compute(pengamat)
                        
                        # Pseudo-Geocentric (Untuk kecepatan Modul Standalone)
                        elong = math.degrees(ephem.separation(matahari, bulan))
                        alt = math.degrees(bulan.alt)
                        
                        if alt >= 5.0 and elong >= 8.0:
                            kandidat.append({'kota': nama_kota, 'lat': koordinat[0], 'lon': koordinat[1], 'sunset': ws})
                    except: continue
            if kandidat:
                kandidat.sort(key=lambda x: x['sunset'])
                titik_hasil.append(kandidat[0])
                break

        if not titik_hasil:
            messagebox.showinfo("Hasil", "Tidak ditemukan daratan yang memenuhi kriteria.")
            return

        pt = titik_hasil[0]
        
        # Plot Matplotlib Map
        fig, ax = plt.subplots(figsize=(8, 5))
        try:
            img = Image.open(os.path.join(BASE_DIR, "map_topografi.jpg"))
            ax.imshow(img, extent=[-180, 180, -90, 90])
        except: pass
        
        ax.scatter([pt['lon']], [pt['lat']], color='yellow', marker='*', s=300, edgecolor='red')
        ax.text(pt['lon'], pt['lat']+5, f"Pertama: {pt['kota']}", color='white', bbox=dict(fc='black'))
        ax.set_title(f"Titik Pertama Pemenuhan KHGT (PKG)")
        
        canvas = FigureCanvasTkAgg(fig, master=self.main_frame)
        canvas.draw()
        canvas.get_tk_widget().pack(fill="both", expand=True)

if __name__ == "__main__":
    app = Menu5App()
    app.mainloop()