This commit is contained in:
meusinfirmary
2025-06-26 04:40:21 +07:00
parent fa04bc880c
commit 83e19e9a3d
4 changed files with 254 additions and 121 deletions

View File

@ -310,21 +310,6 @@ class Tracks_copy 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_copy 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_copy 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,7 +348,92 @@ class Tracks_copy extends Model
$query .= " ;";
return DB::select($query, $params);
// Ambil data
$rawTracks = DB::select($query, $params);
// Sort manual jika perlu
usort($rawTracks, fn($a, $b) => $a->lst_loc_crt <=> $b->lst_loc_crt);
// Filter loncatan
$filtered = self::filterJumps($rawTracks, 3000, 5, 300);
return $filtered;
// return array_reverse($filtered);
}
public static function filterJumps($points, $maxDistance = 3000, $maxTimeGap = 5, $maxSpeed = 150)
{
$filtered = [];
$last = null;
// Sort dari terbaru ke terlama (pastikan sesuai kebutuhan)
usort($points, fn($a, $b) => $b->lst_loc_crt <=> $a->lst_loc_crt);
foreach ($points as $p) {
// 1. Validasi koordinat
if (!is_numeric($p->latitude) || !is_numeric($p->longitude)) {
continue;
}
if (
strlen(explode(".", $p->latitude)[1] ?? "") < 6 ||
strlen(explode(".", $p->longitude)[1] ?? "") < 6
) {
continue;
}
if (!$last) {
$filtered[] = $p;
$last = $p;
continue;
}
// 2. Jarak & waktu
$distance = self::haversineDistance(
$last->latitude,
$last->longitude,
$p->latitude,
$p->longitude
);
$timeGap = $last->lst_loc_crt - $p->lst_loc_crt;
if ($timeGap <= 0) {
continue;
}
$speed = ($distance / $timeGap) * 3.6; // m/s to km/h
// 3. Filter logis
if ($speed <= $maxSpeed || $distance <= $maxDistance) {
$filtered[] = $p;
$last = $p;
}
}
// 4. Pastikan hasil minimal N
if (count($filtered) < 500 && count($points) > 500) {
return array_slice($points, 0, 500); // fallback ke raw jika terlalu sedikit
}
return $filtered;
}
public static function haversineDistance($lat1, $lon1, $lat2, $lon2)
{
$earthRadius = 6371000; // meters
$lat1 = deg2rad($lat1);
$lon1 = deg2rad($lon1);
$lat2 = deg2rad($lat2);
$lon2 = deg2rad($lon2);
$dlat = $lat2 - $lat1;
$dlon = $lon2 - $lon1;
$a = sin($dlat / 2) ** 2 + cos($lat1) * cos($lat2) * sin($dlon / 2) ** 2;
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
return $earthRadius * $c;
}
public static function nearestInCircle($lat, $lng, $rad, $filter = [])