From 51fe0ef7f6460ef76f45a690d204273ab1a88c93 Mon Sep 17 00:00:00 2001 From: meusinfirmary Date: Tue, 1 Jul 2025 02:54:10 +0700 Subject: [PATCH] update --- app/Models/Tracks.php | 159 ++++++++++++++++-------------------------- 1 file changed, 59 insertions(+), 100 deletions(-) diff --git a/app/Models/Tracks.php b/app/Models/Tracks.php index 6d63415..3f86d9d 100755 --- a/app/Models/Tracks.php +++ b/app/Models/Tracks.php @@ -305,85 +305,10 @@ class Tracks extends Model return $list; } - // public static function lastMoveTracks($vid, $filter = []) - // { - // $now = time(); - // $params = []; - // $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"; - // $query .= " ,tr.crt AS lst_loc_crt,tr.crt_d AS lst_loc_crt_d,tr.crt_s AS lst_loc_crt_s"; - // $query .= " ,tr.ignition,tr.stts_engine"; - // $query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1"; - // $query .= " ,addr.master_id AS addr_master_id,addr.crt AS addr_loc_crt"; - // $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 .= " 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"; - - // // last move based on date - // // $query .= " AND tr.crt BETWEEN ? AND ?"; - // // array_push($params, strtotime('-24 hours', $now), $now); - - // 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"]); - // } - - // if (isset($filter["start_at"])) { - // $query .= " AND tr.crt > ?"; - // $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); - - // // if (isset($filter["limit"])) { - // // $query .= " LIMIT ?"; - // // $params[] = $filter["limit"] ?? 500; - // // } - - // $query .= " ;"; - - // // return DB::select($query, $params); - // $rawTracks = DB::select($query, $params); - // $cleanTracks = self::filterJumps($rawTracks); - - // if (isset($filter["limit"])) { - // return array_slice($cleanTracks, 0, $filter["limit"]); - // } - // return $cleanTracks; - // } - public static function lastMoveTracks($vid, $filter = []) { $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"; @@ -394,22 +319,18 @@ 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 .= " 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"; - - // last move based on date - // $query .= " AND tr.crt BETWEEN ? AND ?"; - // array_push($params, strtotime('-24 hours', $now), $now); + $params[] = $vid; + $query .= " AND tr.latitude IS NOT NULL"; + $query .= " 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"])) { @@ -417,19 +338,39 @@ class Tracks extends Model $params[] = $filter["start_at"]; } - // last move based on last count data - $query .= " GROUP BY tr.crt_d"; + // $query .= " GROUP BY tr.crt_d"; $query .= " ORDER BY tr.crt_d DESC"; - // array_push($params, strtotime('-24 hours', $now), $now); - if (isset($filter["limit"])) { - $query .= " LIMIT ?"; - $params[] = $filter["limit"] ?? 500; + if (!isset($filter["limit"]) || $filter["limit"] < 3000) { + $filter["limit"] = 3000; + } + $query .= " LIMIT ?"; + $params[] = $filter["limit"]; + + $raw = DB::select($query, $params); + + usort($raw, function ($a, $b) { + $aTime = strtotime($a->lst_loc_crt ?? "1970-01-01 00:00:00"); + $bTime = strtotime($b->lst_loc_crt ?? "1970-01-01 00:00:00"); + return $aTime <=> $bTime; + }); + + $filtered = self::filterJumps($raw); + + $minData = 500; + if (count($filtered) < $minData) { + $needed = $minData - count($filtered); + $lastRaw = array_slice($raw, -$needed); + $filtered = array_merge($filtered, $lastRaw); } - $query .= " ;"; + usort($filtered, function ($a, $b) { + $aTime = strtotime($a->lst_loc_crt ?? "1970-01-01 00:00:00"); + $bTime = strtotime($b->lst_loc_crt ?? "1970-01-01 00:00:00"); + return $bTime <=> $aTime; + }); - return DB::select($query, $params); + return $filtered; } public static function haversineDistance($lat1, $lon1, $lat2, $lon2) @@ -450,8 +391,14 @@ class Tracks extends Model return $earthRadius * $c; } - public static function filterJumps($points, $maxDistance = 50, $maxTimeGap = 10) - { + public static function filterJumps( + $points, + $maxDistance = 150, + $maxTimeGap = 20, + $maxSpeed = 40, + $maxHardJump = 800, + $maxIdleJump = 1000 + ) { $filtered = []; $last = null; @@ -468,12 +415,24 @@ class Tracks extends Model $p->latitude, $p->longitude ); - $timeGap = $p->lst_loc_crt - $last->lst_loc_crt; - if ($distance <= $maxDistance || $timeGap > $maxTimeGap) { - $filtered[] = $p; - $last = $p; + $timeGap = $p->lst_loc_crt - $last->lst_loc_crt; + $speed = $timeGap > 0 ? $distance / $timeGap : 0; + + if ($distance > $maxHardJump) { + continue; } + if ($distance > $maxIdleJump && $p->speed == 0) { + continue; + } + if ($timeGap <= $maxTimeGap && $speed > $maxSpeed) { + continue; + } + if ($distance > $maxDistance) { + continue; + } + $filtered[] = $p; + $last = $p; } return $filtered;