Update: 2026-07-06 00:53:15

This commit is contained in:
Hamza-Ayed
2026-07-06 00:53:15 +03:00
parent 0c19486a24
commit d00502769a
4 changed files with 92 additions and 30 deletions
+14 -3
View File
@@ -85,9 +85,6 @@ foreach ($data as $row) {
} }
$distanceKm = (float)($resultData['distance_km'] ?? 1); $distanceKm = (float)($resultData['distance_km'] ?? 1);
if ($distanceKm <= 0) $distanceKm = 1; // Prevent division by zero
$pricePerKm = $amount / $distanceKm;
$durationMin = isset($resultData['duration_min']) ? (int)$resultData['duration_min'] : null; $durationMin = isset($resultData['duration_min']) ? (int)$resultData['duration_min'] : null;
$startLat = $resultData['start_lat'] ?? null; $startLat = $resultData['start_lat'] ?? null;
@@ -95,6 +92,20 @@ foreach ($data as $row) {
$endLat = $resultData['end_lat'] ?? null; $endLat = $resultData['end_lat'] ?? null;
$endLng = $resultData['end_lng'] ?? null; $endLng = $resultData['end_lng'] ?? null;
// --- OSRM Integration (Dynamic Distance & Duration) ---
require_once __DIR__ . '/../core/osrm_routing.php';
if ($startLat && $endLat && (!$durationMin || $durationMin <= 0)) {
$osrmResult = getOsrmRouteDetails($startLat, $startLng, $endLat, $endLng);
if ($osrmResult) {
$distanceKm = $osrmResult['distance_km']; // Override with accurate OSRM distance
$durationMin = $osrmResult['duration_min'];
}
}
// ------------------------------------------------------
if ($distanceKm <= 0) $distanceKm = 1; // Prevent division by zero
$pricePerKm = $amount / $distanceKm;
$countryCode = $row['country_code'] ?? 'JO'; // Default $countryCode = $row['country_code'] ?? 'JO'; // Default
if ($stmt->execute([ if ($stmt->execute([
+16 -3
View File
@@ -131,15 +131,28 @@ if ($method === 'GET') {
$pricePerKm = $distance_km > 0 ? ($price / $distance_km) : 0.0; $pricePerKm = $distance_km > 0 ? ($price / $distance_km) : 0.0;
$country_code = $result_data['country_code'] ?? 'SY'; $country_code = $result_data['country_code'] ?? 'SY';
// --- OSRM Integration (Dynamic Distance & Duration) ---
require_once __DIR__ . '/../core/osrm_routing.php';
$duration_min = 0;
if ($start_lat != 0 && $end_lat != 0) {
$osrmResult = getOsrmRouteDetails($start_lat, $start_lng, $end_lat, $end_lng);
if ($osrmResult) {
$distance_km = $osrmResult['distance_km']; // Override with accurate OSRM distance
$duration_min = $osrmResult['duration_min'];
$pricePerKm = $distance_km > 0 ? ($price / $distance_km) : 0.0; // Recalculate based on OSRM
}
}
// ------------------------------------------------------
// 1. Save to MySQL // 1. Save to MySQL
$stmt = $con->prepare(" $stmt = $con->prepare("
INSERT INTO scraped_competitor_prices INSERT INTO scraped_competitor_prices
(task_id, app_name, competitor_name, start_location, end_location, start_lat, start_lng, end_lat, end_lng, price_amount, price_per_km, currency, country_code) (task_id, app_name, competitor_name, start_location, end_location, start_lat, start_lng, end_lat, end_lng, price_amount, price_per_km, distance_km, duration_min, currency, country_code)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"); ");
$start_loc = "Lat: $start_lat, Lng: $start_lng"; $start_loc = "Lat: $start_lat, Lng: $start_lng";
$end_loc = "Lat: $end_lat, Lng: $end_lng"; $end_loc = "Lat: $end_lat, Lng: $end_lng";
$stmt->execute([$task_id, $app_name, $app_name, $start_loc, $end_loc, (string)$start_lat, (string)$start_lng, (string)$end_lat, (string)$end_lng, $price, $pricePerKm, 'JOD', $country_code]); $stmt->execute([$task_id, $app_name, $app_name, $start_loc, $end_loc, (string)$start_lat, (string)$start_lng, (string)$end_lat, (string)$end_lng, $price, $pricePerKm, $distance_km, $duration_min, 'JOD', $country_code]);
// 2. Save to Redis (Calculate Price Per KM) // 2. Save to Redis (Calculate Price Per KM)
if ($distance_km > 0 && $price > 0) { if ($distance_km > 0 && $price > 0) {
+54
View File
@@ -0,0 +1,54 @@
<?php
// ============================================================
// osrm_routing.php
// Helper functions for OpenStreetMap Routing Machine (OSRM)
// Used to estimate accurate distance (km) and duration (mins)
// ============================================================
/**
* Get Distance and Duration between two coordinates using public OSRM server.
* Note: If you host your own OSRM, replace the $osrmBaseUrl.
*
* @param float $startLat
* @param float $startLng
* @param float $endLat
* @param float $endLng
* @return array|null Returns ['distance_km' => float, 'duration_min' => float] or null on failure.
*/
function getOsrmRouteDetails($startLat, $startLng, $endLat, $endLng) {
// Format: longitude,latitude
$coordinates = "{$startLng},{$startLat};{$endLng},{$endLat}";
// Using public demo server. Note: Has rate limits.
// For production, highly recommended to use: "http://your-own-osrm-server.com:5000"
$osrmBaseUrl = "http://router.project-osrm.org";
$url = "{$osrmBaseUrl}/route/v1/driving/{$coordinates}?overview=false";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 5); // 5 seconds timeout
// Add a User-Agent to avoid being blocked by the public demo server
curl_setopt($ch, CURLOPT_USERAGENT, "SiroRideHailingApp/1.0");
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($httpCode === 200 && $response) {
$data = json_decode($response, true);
if (isset($data['code']) && $data['code'] === 'Ok' && isset($data['routes'][0])) {
$route = $data['routes'][0];
$distanceMeters = isset($route['distance']) ? (float)$route['distance'] : 0;
$durationSeconds = isset($route['duration']) ? (float)$route['duration'] : 0;
return [
'distance_km' => round($distanceMeters / 1000, 2),
'duration_min' => round($durationSeconds / 60, 2)
];
}
}
return null;
}
+8 -24
View File
@@ -184,19 +184,12 @@ function calculateDynamicPrice($country, $minFare, $distance, $duration, $kazanR
break; break;
} }
$longSpeedThresholdKm = 40.0;
$longSpeedPerKm = 26.0;
$mediumDistThresholdKm = 25.0; $mediumDistThresholdKm = 25.0;
$longDistThresholdKm = 35.0; $longDistThresholdKm = 35.0;
$longTripPerMin = 6.0;
$minuteCapMedium = 60; $minuteCapMedium = 60;
$minuteCapLong = 80; $minuteCapLong = 80;
$freeMinutesLong = 10; $freeMinutesLong = 10;
$extraReduction100 = 0.07;
$maxReductionCap = 0.35;
$totalMinutes = floor($duration / 60); $totalMinutes = floor($duration / 60);
$airportCtx = (stripos($startNameAddress, 'airport') !== false || stripos($startNameAddress, 'مطار') !== false || stripos($endNameAddress, 'airport') !== false || stripos($endNameAddress, 'مطار') !== false); $airportCtx = (stripos($startNameAddress, 'airport') !== false || stripos($startNameAddress, 'مطار') !== false || stripos($endNameAddress, 'airport') !== false || stripos($endNameAddress, 'مطار') !== false);
@@ -210,23 +203,15 @@ function calculateDynamicPrice($country, $minFare, $distance, $duration, $kazanR
$isInDamascusAirportBoundCtx = ($passengerLat <= $northLat && $passengerLat >= $southLat && $passengerLng <= $eastLng && $passengerLng >= $westLng); $isInDamascusAirportBoundCtx = ($passengerLat <= $northLat && $passengerLat >= $southLat && $passengerLng <= $eastLng && $passengerLng >= $westLng);
$billableDistance = ($distance < $minBillableKm) ? $minBillableKm : $distance; $billableDistance = ($distance < $minBillableKm) ? $minBillableKm : $distance;
$isLongSpeed = $billableDistance > $longSpeedThresholdKm;
$perKmSpeedBaseFromServer = getPerKmRate($carType, $kazanRow); $perKmSpeedBaseFromServer = getPerKmRate($carType, $kazanRow);
$perKmSpeed = $isLongSpeed ? $longSpeedPerKm : $perKmSpeedBaseFromServer;
// Apply dynamic percentage discount instead of hardcoded currencies for long trips
$reductionPct40 = 0.0; $perKmSpeed = $perKmSpeedBaseFromServer;
if ($perKmSpeedBaseFromServer > 0) { if ($billableDistance > $longDistThresholdKm) {
$r = 1.0 - ($longSpeedPerKm / $perKmSpeedBaseFromServer); $perKmSpeed = $perKmSpeedBaseFromServer * 0.85; // 15% discount per km
$reductionPct40 = max(0.0, min($maxReductionCap, $r)); } else if ($billableDistance > $mediumDistThresholdKm) {
} $perKmSpeed = $perKmSpeedBaseFromServer * 0.90; // 10% discount per km
$reductionPct100 = max(0.0, min($maxReductionCap, $reductionPct40 + $extraReduction100));
$distanceReduction = 0.0;
if ($billableDistance > 100.0) {
$distanceReduction = $reductionPct100;
} else if ($billableDistance > 40.0) {
$distanceReduction = $reductionPct40;
} }
date_default_timezone_set('Asia/Damascus'); date_default_timezone_set('Asia/Damascus');
@@ -242,11 +227,10 @@ function calculateDynamicPrice($country, $minFare, $distance, $duration, $kazanR
$billableMinutes = $totalMinutes; $billableMinutes = $totalMinutes;
if ($billableDistance > $longDistThresholdKm) { if ($billableDistance > $longDistThresholdKm) {
$effectivePerMin = $longTripPerMin; // Prevent absurd time billing for very long trips
$capped = ($billableMinutes > $minuteCapLong) ? $minuteCapLong : $billableMinutes; $capped = ($billableMinutes > $minuteCapLong) ? $minuteCapLong : $billableMinutes;
$billableMinutes = max(0, $capped - $freeMinutesLong); $billableMinutes = max(0, $capped - $freeMinutesLong);
} else if ($billableDistance > $mediumDistThresholdKm) { } else if ($billableDistance > $mediumDistThresholdKm) {
$effectivePerMin = $longTripPerMin;
$billableMinutes = ($billableMinutes > $minuteCapMedium) ? $minuteCapMedium : $billableMinutes; $billableMinutes = ($billableMinutes > $minuteCapMedium) ? $minuteCapMedium : $billableMinutes;
} }