This commit is contained in:
meusinfirmary
2025-07-04 04:34:30 +07:00
parent b463e9578b
commit 840a321d20

View File

@ -307,11 +307,10 @@ class Tracks extends Model
public static function lastMoveTracks($vid, $filter = []) public static function lastMoveTracks($vid, $filter = [])
{ {
$now = time();
$params = []; $params = [];
$query = "SELECT"; $query = "SELECT";
$query .= " v.id as vid,v.device_id,v.nopol1,v.nopol2,v.nopol3"; $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.id as master_id,tr.latitude,tr.longitude,tr.speed,tr.orientation, tr.crt_d_format";
$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.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.ignition,tr.stts_engine";
$query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1"; $query .= " ,tr.pre_milleage,tr.sum_milleage,tr.vhc_milleage,v.sum_milleage AS vhc_sum_milleage_1";
@ -321,13 +320,11 @@ class Tracks extends Model
$query .= " FROM t_vehicles AS v"; $query .= " FROM t_vehicles AS v";
$query .= " INNER JOIN " . self::T_TRACKS . " AS tr ON v.id = tr.vhc_id"; $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 .= " 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 AND v.id = ?";
$query .= " AND v.id = ?";
$params[] = $vid; $params[] = $vid;
$query .= " AND tr.latitude IS NOT NULL"; $query .= " AND tr.latitude IS NOT NULL AND tr.longitude IS NOT NULL";
$query .= " AND tr.longitude IS NOT NULL";
if (isset($filter["start_date"]) && isset($filter["end_date"])) { if (isset($filter["start_date"], $filter["end_date"])) {
$query .= " AND tr.crt_d BETWEEN ? AND ?"; $query .= " AND tr.crt_d BETWEEN ? AND ?";
$params[] = $filter["start_date"]; $params[] = $filter["start_date"];
$params[] = $filter["end_date"]; $params[] = $filter["end_date"];
@ -338,39 +335,19 @@ class Tracks extends Model
$params[] = $filter["start_at"]; $params[] = $filter["start_at"];
} }
// $query .= " GROUP BY tr.crt_d";
$query .= " ORDER BY tr.crt_d DESC"; $query .= " ORDER BY tr.crt_d DESC";
$limit = isset($filter["limit"]) && $filter["limit"] > 500 ? $filter["limit"] : 3000;
if (!isset($filter["limit"]) || $filter["limit"] < 3000) {
$filter["limit"] = 3000;
}
$query .= " LIMIT ?"; $query .= " LIMIT ?";
$params[] = $filter["limit"]; $params[] = $limit;
$raw = DB::select($query, $params); $raw = DB::select($query, $params);
$rawAscCleaned = self::removeSpeedSandwich($raw);
$filtered = self::filterJumps($rawAscCleaned);
$combined = $filtered;
usort($raw, function ($a, $b) { usort($combined, fn($a, $b) => $b->lst_loc_crt_d <=> $a->lst_loc_crt_d);
$aTime = strtotime($a->lst_loc_crt ?? "1970-01-01 00:00:00"); $final = array_slice($combined, 0, 500);
$bTime = strtotime($b->lst_loc_crt ?? "1970-01-01 00:00:00"); return $final;
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);
}
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 $filtered;
} }
public static function haversineDistance($lat1, $lon1, $lat2, $lon2) public static function haversineDistance($lat1, $lon1, $lat2, $lon2)
@ -391,21 +368,45 @@ class Tracks extends Model
return $earthRadius * $c; return $earthRadius * $c;
} }
private static function removeSpeedSandwich($data)
{
$cleaned = [];
for ($i = 0; $i < count($data); $i++) {
$next = $data[$i + 1] ?? null; // lebih lama
$curr = $data[$i];
$prev = $data[$i - 1] ?? null; // lebih baru
// Logika dibalik: prev = lebih baru, next = lebih lama
if ($prev && $next && $prev->speed > 5 && $curr->speed < 5 && $next->speed > 5) {
continue;
}
$cleaned[] = $curr;
}
return $cleaned;
}
public static function filterJumps( public static function filterJumps(
$points, $points,
$maxDistance = 150, $maxDistance = 150,
$maxTimeGap = 20, $maxTimeGap = 20,
$maxSpeed = 40, $maxSpeed = 40,
$maxHardJump = 800, $maxHardJump = 800,
$maxIdleJump = 1000 $maxIdleJump = 1000,
$maxRealSpeed = 150
) { ) {
// km/h
$filtered = []; $filtered = [];
$last = null; $last = null;
$start = null;
foreach ($points as $p) { foreach ($points as $p) {
if (!$last) { if (!$last) {
$filtered[] = $p; $filtered[] = $p;
$last = $p; $last = $p;
$start = $p;
continue; continue;
} }
@ -416,21 +417,45 @@ class Tracks extends Model
$p->longitude $p->longitude
); );
$timeGap = $p->lst_loc_crt - $last->lst_loc_crt; $t1 = strtotime($last->lst_loc_crt);
$t2 = strtotime($p->lst_loc_crt);
$timeGap = $t2 - $t1;
$speed = $timeGap > 0 ? $distance / $timeGap : 0; $speed = $timeGap > 0 ? $distance / $timeGap : 0;
$realSpeedKmh = $speed * 3.6;
// Tambahan: jarak terhadap titik awal
$jumpFromStart = self::haversineDistance(
$start->latitude,
$start->longitude,
$p->latitude,
$p->longitude
);
// 🚫 Lompatan keras (langsung > 800 m)
if ($distance > $maxHardJump) { if ($distance > $maxHardJump) {
continue; continue;
} }
if ($distance > $maxIdleJump && $p->speed == 0) {
// 🚫 Lompat saat idle (dianggap tidak wajar jika dua titik idle dan lompat jauh)
if ($distance > $maxIdleJump && $p->speed < 5 && $last->speed < 5) {
continue; continue;
} }
// 🚫 Lompat dalam waktu pendek dan speed terlalu tinggi
if ($timeGap <= $maxTimeGap && $speed > $maxSpeed) { if ($timeGap <= $maxTimeGap && $speed > $maxSpeed) {
continue; continue;
} }
if ($distance > $maxDistance) {
// 🚫 Speed tidak masuk akal
if ($realSpeedKmh > $maxRealSpeed) {
continue; continue;
} }
// 🚫 Lompat dari titik awal terlalu jauh (anomaly GPS loncat)
if ($jumpFromStart > 10000 && $p->speed < 5) {
continue;
} // >10 km dari area awal tapi status idle
$filtered[] = $p; $filtered[] = $p;
$last = $p; $last = $p;
} }