package controllers import ( "fmt" "net/http" "time" "github.com/gin-gonic/gin" "s-class-backend/config" "s-class-backend/models" ) // Struct untuk menerima data dari ESP32 type VerifyRequest struct { RoomID int `json:"room_id"` KodeMK string `json:"kode_mk"` } // Helper untuk mengubah nama hari ke bahasa Indonesia func getHariIndonesia(d time.Weekday) string { days := []string{"Minggu", "Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu"} return days[d] } func VerifyHardwareCode(c *gin.Context) { var req VerifyRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Format data tidak valid"}) return } // 1. Dapatkan waktu sekarang di zona waktu Surabaya (WIB / GMT+7) loc, _ := time.LoadLocation("Asia/Jakarta") now := time.Now().In(loc) hariIni := getHariIndonesia(now.Weekday()) jamSekarangStr := now.Format("15:04:05") // ========================================================================= // SKENARIO A: Dosen masuk sesuai jadwal perkuliahan // ========================================================================= var schedule models.ClassSchedule err := config.DB.Where( "room_id = ? AND kode_mk = ? AND hari = ? AND jam_mulai <= ? AND jam_selesai >= ?", req.RoomID, req.KodeMK, hariIni, jamSekarangStr, jamSekarangStr, ).First(&schedule).Error if err == nil { // Ditemukan jadwal yang cocok! Izinkan relay menyala. c.JSON(http.StatusOK, gin.H{ "status": "success", "relay": "ON", "message": fmt.Sprintf("Akses diterima. Jadwal %s sedang berlangsung.", schedule.NamaMK), }) return } // ========================================================================= // SKENARIO B: Akses Dadakan (Di luar jadwal / Kode MK tidak cocok jam ini) // ========================================================================= // CEK 1: Apakah ada jadwal KULIAH LAIN yang sedang berlangsung saat ini? var activeSchedule models.ClassSchedule errActive := config.DB.Where( "room_id = ? AND hari = ? AND jam_mulai <= ? AND jam_selesai >= ?", req.RoomID, hariIni, jamSekarangStr, jamSekarangStr, ).First(&activeSchedule).Error if errActive == nil { c.JSON(http.StatusForbidden, gin.H{ "error": fmt.Sprintf("Akses ditolak. Ruangan sedang digunakan untuk jadwal: %s", activeSchedule.NamaMK), }) return } // CEK 2: Apakah ada BOOKING MAHASISWA (Approved) yang sedang berlangsung? // Asumsi tabel booking memiliki status 'Approved', 'Pending', dll. var activeBooking models.Booking errBooking := config.DB.Where( "room_id = ? AND status = 'Approved' AND start_time <= ? AND end_time >= ?", req.RoomID, now, now, // Sesuaikan jika format DB menggunakan timestamp ISO ).First(&activeBooking).Error if errBooking == nil { c.JSON(http.StatusForbidden, gin.H{ "error": "Akses ditolak. Ruangan sedang dipinjam oleh mahasiswa.", }) return } // CEK 3: Pengecekan Aturan 10 Menit untuk Jadwal Berikutnya var nextSchedule models.ClassSchedule errNext := config.DB.Where( "room_id = ? AND hari = ? AND jam_mulai > ?", req.RoomID, hariIni, jamSekarangStr, ).Order("jam_mulai asc").First(&nextSchedule).Error if errNext == nil { // Parse jam mulai jadwal berikutnya nextTime, _ := time.Parse("15:04:05", nextSchedule.JamMulai) currentTime, _ := time.Parse("15:04:05", jamSekarangStr) // Hitung selisih dalam menit diffMinutes := nextTime.Sub(currentTime).Minutes() if diffMinutes <= 10 { c.JSON(http.StatusForbidden, gin.H{ "error": fmt.Sprintf("Akses ditolak. Kelas %s akan segera dimulai dalam %.0f menit. Ruangan harus dikosongkan.", nextSchedule.NamaMK, diffMinutes), }) return } } // Jika lolos semua rintangan di atas, ruangan dipastikan KOSONG dan AMAN. // Akses dadakan diizinkan! c.JSON(http.StatusOK, gin.H{ "status": "success", "relay": "ON", "message": "Akses dadakan diizinkan. Tidak ada tabrakan jadwal terdekat.", }) }