Files
Siro/backend/ride/location/getBalash.php
2026-06-09 08:40:31 +03:00

167 lines
7.5 KiB
PHP
Executable File

<?php
require_once __DIR__ . '/../../connect.php'; // يفترض أن هذا الملف ينشئ $con و $con_tracking
//getBalash.php
try {
// 1) قراءة والتحقق من الإحداثيات
$southwestLat = filterRequest("southwestLat");
$southwestLon = filterRequest("southwestLon");
$northeastLat = filterRequest("northeastLat");
$northeastLon = filterRequest("northeastLon");
if ($southwestLat === false || $southwestLon === false || $northeastLat === false || $northeastLon === false) {
jsonError("Invalid coordinates provided");
exit;
}
$freshSeconds = 180; // 3 دقائق
// =================================================================
// الخطوة 1: جلب المواقع والمعرفات من قاعدة بيانات التتبع
// =================================================================
// إعادة استخدام التحسين الجغرافي ST_CONTAINS لأنه أسرع بمراحل
$boundingBoxWKT = sprintf(
'POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))',
$southwestLon, $southwestLat,
$northeastLon, $southwestLat,
$northeastLon, $northeastLat,
$southwestLon, $northeastLat,
$southwestLon, $southwestLat
);
// ملاحظة: نزيل LIMIT 5 من هنا ونجلب مجموعة أكبر من المرشحين
// لأن الترتيب النهائي يعتمد على بيانات من القاعدة الأخرى
$sql_locations = "
SELECT driver_id, latitude, longitude, heading, speed, status, updated_at
FROM car_locations
WHERE
ST_CONTAINS(ST_GeomFromText(:boundingBox, 4326), location_point)
AND status = 'off'
AND updated_at >= NOW() - INTERVAL :freshSeconds SECOND
ORDER BY updated_at DESC
LIMIT 20; -- نجلب 100 مرشح محتمل للفلترة والترتيب لاحقاً
";
$stmt_locations = $con_tracking->prepare($sql_locations);
$stmt_locations->bindValue(':boundingBox', $boundingBoxWKT);
$stmt_locations->bindValue(':freshSeconds', $freshSeconds, PDO::PARAM_INT);
$stmt_locations->execute();
$locations = $stmt_locations->fetchAll(PDO::FETCH_ASSOC);
if (!$locations) {
jsonError("No car locations found in the specified area.");
exit;
}
// =================================================================
// الخطوة 2: تجميع معرفات السائقين (driver_id)
// =================================================================
$driver_ids = array_column($locations, 'driver_id');
// =================================================================
// الخطوة 3: جلب البيانات الثابتة من القاعدة الأساسية وتطبيق الفلاتر الإضافية
// =================================================================
$drivers_info = [];
if (!empty($driver_ids)) {
$placeholders = implode(',', array_fill(0, count($driver_ids), '?'));
// هنا نطبق الشروط الخاصة بهذا السكريبت (موديل السيارة < 2000)
$sql_drivers_info = "
SELECT
d.id AS driver_id, d.phone, d.email, d.birthdate, d.first_name, d.last_name,
cr.make, cr.model, cr.color, cr.color_hex, cr.year,
dt.token,
COALESCE(rdAvg.ratingDriver, 0) AS ratingDriver,
COALESCE(rdAvg.ratingCount, 0) AS ratingCount
FROM driver d
LEFT JOIN CarRegistration cr ON cr.driverID = d.id
LEFT JOIN driverToken dt ON dt.captain_id = d.id
LEFT JOIN (
SELECT driver_id, AVG(rating) AS ratingDriver, COUNT(id) AS ratingCount
FROM ratingDriver
GROUP BY driver_id
) rdAvg ON rdAvg.driver_id = d.id
WHERE d.id IN ($placeholders)
AND COALESCE(cr.year, 0) < 2000 -- ⭐ الشرط الخاص بهذا السكريبت
AND (cr.make NOT LIKE '%دراج%' AND cr.model NOT LIKE '%دراج%')
AND (cr.model NOT LIKE '%Van%' AND cr.make NOT LIKE '%Van%')
";
$stmt_drivers_info = $con->prepare($sql_drivers_info);
$stmt_drivers_info->execute($driver_ids);
$drivers_info_raw = $stmt_drivers_info->fetchAll(PDO::FETCH_ASSOC);
// تحويل المصفوفة لتسهيل عملية الدمج لاحقاً
foreach ($drivers_info_raw as $driver) {
$drivers_info[$driver['driver_id']] = $driver;
}
}
// =================================================================
// الخطوة 4: دمج النتائج في PHP
// =================================================================
$final_results = [];
foreach ($locations as $location) {
$driver_id = $location['driver_id'];
// ندمج فقط السائقين الذين طابقوا شروطنا في الاستعلام الثاني
if (isset($drivers_info[$driver_id])) {
$final_results[] = array_merge($location, $drivers_info[$driver_id]);
}
}
// =================================================================
// الخطوة 5: تطبيق الترتيب والحد النهائي في PHP
// =================================================================
// الآن بعد أن دمجنا كل البيانات، يمكننا تطبيق الترتيب المعقد
usort($final_results, function ($a, $b) {
// الترتيب الأول: حسب التقييم (تنازلي)
if ($a['ratingDriver'] != $b['ratingDriver']) {
return $b['ratingDriver'] <=> $a['ratingDriver'];
}
// الترتيب الثاني: حسب عدد التقييمات (تنازلي)
if ($a['ratingCount'] != $b['ratingCount']) {
return $b['ratingCount'] <=> $a['ratingCount'];
}
// الترتيب الثالث: حسب حداثة الموقع (تنازلي)
return strtotime($b['updated_at']) <=> strtotime($a['updated_at']);
});
// وأخيراً، نأخذ أفضل 5 نتائج فقط
$limited_results = array_slice($final_results, 0, 5);
if (empty($limited_results)) {
jsonError("No cars matching the specific criteria (year < 2000) found.");
exit;
}
// =================================================================
// الخطوة 6: فك التشفير وحساب العمر (بدون تغيير)
// =================================================================
$fieldsToDecrypt = [ 'phone','email','gender','birthdate', 'first_name','last_name', 'token','car_plate','vin' ];
foreach ($limited_results as &$row) {
foreach ($fieldsToDecrypt as $field) {
if (isset($row[$field]) && !empty($row[$field])) {
try { $row[$field] = $encryptionHelper->decryptData($row[$field]); }
catch (Exception $e) { $row[$field] = null; }
}
}
if (!empty($row['birthdate'])) {
try {
$birthDate = new DateTime($row['birthdate']);
$today = new DateTime();
$row['age'] = $today->diff($birthDate)->y;
} catch (Exception $e) { $row['age'] = null; }
} else {
$row['age'] = null;
}
}
unset($row);
jsonSuccess($limited_results);
} catch (PDOException $e) {
jsonError("Database error: " . $e->getMessage());
} catch (Throwable $e) {
jsonError("Internal error: " . $e->getMessage());
}