From e1c9649c3e80f1c292e85d250790cd9112684d0d Mon Sep 17 00:00:00 2001 From: meusinfirmary Date: Fri, 20 Jun 2025 13:59:45 +0800 Subject: [PATCH] update --- app/Models/Tracks.php | 138 ++++++++++++++++++++----------------- app/Models/Tracks_copy.php | 23 ++++--- 2 files changed, 86 insertions(+), 75 deletions(-) diff --git a/app/Models/Tracks.php b/app/Models/Tracks.php index c50650d..f96429b 100755 --- a/app/Models/Tracks.php +++ b/app/Models/Tracks.php @@ -310,21 +310,6 @@ class Tracks extends Model $now = time(); $params = []; - /** - * bikin lemot 30s timeout karena ada 2 join di rows yang banyak - * solution: indexing column - * show index from t_gps_tracks_address; - * create index addr_device_id on t_gps_tracks_address (device_id); - * create index addr_master_id on t_gps_tracks_address (master_id); - * show index from t_gps_tracks; - * create index tracks_device_id on t_gps_tracks (device_id); - * show index from t_vehicles; - * create index vhc_device_id on t_vehicles (device_id); - * - * solution not working. Don't reinvent the wheel - * create view. not working - */ - $query = "SELECT"; $query .= " v.id as vid,v.device_id,v.nopol1,v.nopol2,v.nopol3"; $query .= " ,tr.id as master_id,tr.latitude,tr.longitude,tr.speed,tr.orientation"; @@ -335,22 +320,17 @@ class Tracks extends Model $query .= " ,addr.country_text,addr.state_text,addr.city_text,addr.district_text,addr.village_text,addr.postcode,addr.streets,addr.postcode,addr.fulladdress"; $query .= " FROM t_vehicles AS v"; - // $query .= " INNER JOIN " . self::T_TRACKS . " AS tr ON v.device_id = tr.device_id"; // cara lama berlaku utk gps tracker saja - $query .= " INNER JOIN " . self::T_TRACKS . " AS tr ON v.id = tr.vhc_id"; // support gps tracker dan smartphone / apapun yang mempunyai device_id(IMEI) + $query .= " INNER JOIN " . self::T_TRACKS . " AS tr ON v.id = tr.vhc_id"; $query .= " LEFT JOIN " . self::T_TRACKS_ADDR . " AS addr ON tr.id = addr.master_id"; - $query .= " WHERE v.dlt is null"; - $query .= " AND v.id = ?"; - array_push($params, $vid); - $query .= " AND tr.latitude is not null"; - $query .= " AND tr.longitude is not null"; + $query .= " WHERE v.dlt is null AND v.id = ?"; + $params[] = $vid; - // last move based on date - // $query .= " AND tr.crt BETWEEN ? AND ?"; - // array_push($params, strtotime('-24 hours', $now), $now); + $query .= " AND tr.latitude is not null AND tr.longitude is not null"; if (isset($filter["start_date"]) && isset($filter["end_date"])) { $query .= " AND tr.crt_d BETWEEN ? AND ?"; - array_push($params, $filter["start_date"], $filter["end_date"]); + $params[] = $filter["start_date"]; + $params[] = $filter["end_date"]; } if (isset($filter["start_at"])) { @@ -358,10 +338,8 @@ class Tracks extends Model $params[] = $filter["start_at"]; } - // last move based on last count data - $query .= " GROUP BY tr.crt_d"; - $query .= " ORDER BY tr.crt_d DESC"; - // array_push($params, strtotime('-24 hours', $now), $now); + // ASC supaya filter berurutan waktu + $query .= " ORDER BY tr.crt DESC"; if (isset($filter["limit"])) { $query .= " LIMIT ?"; @@ -370,14 +348,75 @@ class Tracks extends Model $query .= " ;"; - // return DB::select($query, $params); + // Ambil data $rawTracks = DB::select($query, $params); - $cleanTracks = self::filterJumps($rawTracks); - if (isset($filter["limit"])) { - return array_slice($cleanTracks, 0, $filter["limit"]); + // Sort manual jika perlu + usort($rawTracks, fn($a, $b) => $a->lst_loc_crt <=> $b->lst_loc_crt); + + // Filter loncatan + $filtered = self::filterJumps($rawTracks, 1000, 5, 300); + + // return $filtered; + return array_reverse($filtered); + } + + public static function filterJumps($points, $maxDistance = 1000, $maxTimeGap = 5, $maxSpeed = 300) + { + $filtered = []; + $last = null; + + foreach ($points as $p) { + // 🛡️ 1. Validasi data koordinat + if (!is_numeric($p->latitude) || !is_numeric($p->longitude)) { + continue; + } + + if (strlen((string) abs($p->latitude)) < 8 || strlen((string) abs($p->longitude)) < 8) { + // Buang lat/lon kurang dari 8 digit desimal (umumnya noise) + continue; + } + + if (!$last) { + $filtered[] = $p; + $last = $p; + continue; + } + + // 2. Hitung jarak dan waktu + $distance = self::haversineDistance( + $last->latitude, + $last->longitude, + $p->latitude, + $p->longitude + ); + $timeGap = $p->lst_loc_crt - $last->lst_loc_crt; + + if ($timeGap <= 0) { + continue; + } + + $speed = ($distance / $timeGap) * 3.6; // m/s to km/h + + // 🧠 3. Validasi kombinasi logis + if ($speed <= $maxSpeed && ($distance <= $maxDistance || $timeGap >= $maxTimeGap)) { + $filtered[] = $p; + $last = $p; + } else { + // Optional debug: + // Log::info("LONCAT: speed={$speed}, dist={$distance}, timeGap={$timeGap}, pointID={$p->master_id}"); + } } - return $cleanTracks; + + // ⏳ Tambahkan titik terakhir jika tidak masuk + if (!empty($points)) { + $lastPoint = end($points); + if (empty($filtered) || end($filtered)->lst_loc_crt !== $lastPoint->lst_loc_crt) { + $filtered[] = $lastPoint; + } + } + + return $filtered; } public static function haversineDistance($lat1, $lon1, $lat2, $lon2) @@ -398,35 +437,6 @@ class Tracks extends Model return $earthRadius * $c; } - public static function filterJumps($points, $maxDistance = 50, $maxTimeGap = 10) - { - $filtered = []; - $last = null; - - foreach ($points as $p) { - if (!$last) { - $filtered[] = $p; - $last = $p; - continue; - } - - $distance = self::haversineDistance( - $last->latitude, - $last->longitude, - $p->latitude, - $p->longitude - ); - $timeGap = $p->lst_loc_crt - $last->lst_loc_crt; - - if ($distance <= $maxDistance || $timeGap > $maxTimeGap) { - $filtered[] = $p; - $last = $p; - } - } - - return $filtered; - } - public static function nearestInCircle($lat, $lng, $rad, $filter = []) { $earth_rad = Helper::EARTH_RADIUS_M; diff --git a/app/Models/Tracks_copy.php b/app/Models/Tracks_copy.php index 322fe8c..e84bdb7 100755 --- a/app/Models/Tracks_copy.php +++ b/app/Models/Tracks_copy.php @@ -128,19 +128,19 @@ class Tracks_copy extends Model } if (isset($filter["get_order_data"])) { // the old way => only 1 order 1 vehicle - // $query .= " LEFT JOIN t_orders as ord ON v.ord_id = ord.id"; - // $query .= " LEFT JOIN t_orders_pickups as ord_pck ON v.ord_id = ord_pck.ord_id"; - // $query .= " LEFT JOIN t_orders_drops as ord_drop ON v.ord_id = ord_drop.ord_id"; - // $query .= " LEFT JOIN t_orders_drivers as ord_drv ON v.ord_id = ord_drv.ord_id"; - // $query .= " LEFT JOIN t_orders_clients as ord_c ON v.ord_id = ord_c.ord_id"; + $query .= " LEFT JOIN t_orders as ord ON v.ord_id = ord.id"; + $query .= " LEFT JOIN t_orders_pickups as ord_pck ON v.ord_id = ord_pck.ord_id"; + $query .= " LEFT JOIN t_orders_drops as ord_drop ON v.ord_id = ord_drop.ord_id"; + $query .= " LEFT JOIN t_orders_drivers as ord_drv ON v.ord_id = ord_drv.ord_id"; + $query .= " LEFT JOIN t_orders_clients as ord_c ON v.ord_id = ord_c.ord_id"; // the new way => can handle 2 order in 1 vehicle - $query .= " LEFT JOIN t_orders_vehicles as ord_vhc ON v.id = ord_vhc.vhc_id"; - $query .= " LEFT JOIN t_orders as ord ON ord_vhc.ord_id = ord.id"; - $query .= " LEFT JOIN t_orders_pickups as ord_pck ON ord_vhc.ord_id = ord_pck.ord_id"; - $query .= " LEFT JOIN t_orders_drops as ord_drop ON ord_vhc.ord_id = ord_drop.ord_id"; - $query .= " LEFT JOIN t_orders_drivers as ord_drv ON ord_vhc.ord_id = ord_drv.ord_id"; - $query .= " LEFT JOIN t_orders_clients as ord_c ON ord_vhc.ord_id = ord_c.ord_id"; + // $query .= " LEFT JOIN t_orders_vehicles as ord_vhc ON v.id = ord_vhc.vhc_id"; + // $query .= " LEFT JOIN t_orders as ord ON ord_vhc.ord_id = ord.id"; + // $query .= " LEFT JOIN t_orders_pickups as ord_pck ON ord_vhc.ord_id = ord_pck.ord_id"; + // $query .= " LEFT JOIN t_orders_drops as ord_drop ON ord_vhc.ord_id = ord_drop.ord_id"; + // $query .= " LEFT JOIN t_orders_drivers as ord_drv ON ord_vhc.ord_id = ord_drv.ord_id"; + // $query .= " LEFT JOIN t_orders_clients as ord_c ON ord_vhc.ord_id = ord_c.ord_id"; } $query .= " WHERE v.dlt is null"; // $query .= " AND tr.action IN ('location','alarm')"; // kalo gamau ngambil data heartbeat(idling) @@ -211,6 +211,7 @@ class Tracks_copy extends Model $query .= " AND ord_c.c_id = ?"; $params[] = $filter["client_id"]; } + // $query .= " AND ord.status IN (22,4)"; } if (isset($filter["company"])) { $query .= " AND client.id = ?";