checkSession()) { echo json_encode(['status' => 'error', 'message' => 'Unauthorized']); exit(); } $database = new Database(); $conn = $database->connect(); try { // 1. Ambil data RFID yang sedang 'digunakan' // Ini penting karena hanya gelang yang statusnya 'digunakan' yang relevan $stmt_rfid = $conn->prepare("SELECT kode_gelang FROM rfid_tags WHERE status = 'digunakan'"); $stmt_rfid->execute(); $used_rfid_tags = $stmt_rfid->fetchAll(PDO::FETCH_COLUMN, 0); if (empty($used_rfid_tags)) { // Jika tidak ada gelang yang sedang digunakan, langsung kembalikan array kosong echo json_encode(['status' => 'success', 'data' => []]); exit(); } $placeholders = implode(',', array_fill(0, count($used_rfid_tags), '?')); // 2. Ambil data anak, kunjungan, dan wahana terakhir yang relevan // DITAMBAHKAN: k.waktu_keluar IS NULL untuk hanya mengambil kunjungan aktif $query = " SELECT a.id AS anak_id, a.nama AS nama_anak, a.no_hp AS no_hp_anak, a.kode_gelang AS kode_gelang_anak, a.durasi AS durasi_anak, k.id AS kunjungan_id, k.waktu_masuk AS waktu_masuk_kunjungan, rw.wahana AS wahana_terakhir, rw.waktu_masuk AS waktu_wahana_terakhir FROM anak a JOIN kunjungan k ON a.id = k.id_anak LEFT JOIN ( SELECT id_kunjungan, wahana, waktu_masuk, ROW_NUMBER() OVER(PARTITION BY id_kunjungan ORDER BY waktu_masuk DESC) as rn FROM riwayat_wahana ) rw ON k.id = rw.id_kunjungan AND rw.rn = 1 WHERE a.kode_gelang IN ($placeholders) AND k.waktu_keluar IS NULL -- <--- BARIS INI DITAMBAHKAN ORDER BY a.id, k.waktu_masuk DESC "; $stmt_active_data = $conn->prepare($query); $stmt_active_data->execute($used_rfid_tags); $raw_active_data = $stmt_active_data->fetchAll(PDO::FETCH_ASSOC); $final_active_visitors_data = []; $processed_children = []; // Digunakan untuk memastikan setiap anak hanya muncul sekali foreach ($raw_active_data as $row) { // Karena kita sudah memfilter `k.waktu_keluar IS NULL` di query, // kita hanya perlu memastikan setiap anak unik yang memiliki sesi aktif terbaru. // `ORDER BY a.id, k.waktu_masuk DESC` membantu kita mendapatkan kunjungan paling baru. // Jika satu anak punya banyak kunjungan aktif (yang seharusnya tidak terjadi // jika `waktu_keluar` diupdate dengan benar), ini akan ambil yang paling baru. if (!in_array($row['anak_id'], $processed_children)) { list($h, $m, $s) = array_pad(explode(':', $row['durasi_anak']), 3, 0); $total_duration_seconds = ((int)$h * 3600) + ((int)$m * 60) + (int)$s; $waktu_masuk_timestamp = strtotime($row['waktu_masuk_kunjungan']); if ($waktu_masuk_timestamp === false) { // Fallback yang lebih robust jika parsing gagal $waktu_masuk_timestamp = (new DateTime())->getTimestamp(); error_log("Failed to parse waktu_masuk_kunjungan: " . $row['waktu_masuk_kunjungan'] . ". Using current timestamp."); } $final_active_visitors_data[] = [ 'nama_anak' => $row['nama_anak'], 'no_hp' => $row['no_hp_anak'] ?? '-', 'kode_gelang' => $row['kode_gelang_anak'], 'total_durasi_detik' => $total_duration_seconds, 'waktu_masuk_timestamp' => $waktu_masuk_timestamp, // Ini yang dikirim ke JS 'wahana_terakhir' => $row['wahana_terakhir'] ?? 'Belum ada', 'waktu_masuk_kunjungan_string' => $row['waktu_masuk_kunjungan'] ]; $processed_children[] = $row['anak_id']; // Tandai anak ini sudah diproses } } echo json_encode(['status' => 'success', 'data' => $final_active_visitors_data]); } catch (PDOException $e) { error_log("Database Error in get_active_visitors.php: " . $e->getMessage()); echo json_encode(['status' => 'error', 'message' => 'Terjadi kesalahan server database: ' . $e->getMessage()]); } catch (Exception $e) { error_log("General Error in get_active_visitors.php: " . $e->getMessage()); echo json_encode(['status' => 'error', 'message' => 'Terjadi kesalahan sistem yang tidak terduga.']); } ?>