Update: 2026-07-06 02:40:45
This commit is contained in:
@@ -295,112 +295,10 @@ function calculateDynamicPrice($country, $minFare, $distance, $duration, $kazanR
|
|||||||
|
|
||||||
$price = max($fare, $minFare);
|
$price = max($fare, $minFare);
|
||||||
|
|
||||||
// Apply competitor-linked regional pricing overrides (undercut by 8%)
|
// The real-time database competitor check is removed to prevent 40-second MySQL timeouts.
|
||||||
// Skip if it's an airport trip, as airport pricing is highly specific and should rely on our base + addon logic
|
// The background AI Engine (cron_ai_engine.php) already handles undercutting competitors
|
||||||
|
// by dynamically updating the base rates in the `kazan` table every hour.
|
||||||
$competitorTarget = null;
|
$competitorTarget = null;
|
||||||
if (isset($con) && $con !== null && !$airportCtx && !$damascusAirportBoundCtx && !$isInDamascusAirportBoundCtx) {
|
|
||||||
try {
|
|
||||||
$countryCodeMap = [
|
|
||||||
'Syria' => 'SY',
|
|
||||||
'Jordan' => 'JO',
|
|
||||||
'Egypt' => 'EG',
|
|
||||||
'Iraq' => 'IQ'
|
|
||||||
];
|
|
||||||
$cc = $countryCodeMap[$country] ?? 'SY';
|
|
||||||
|
|
||||||
$latDelta = 0.02;
|
|
||||||
$lngDelta = 0.02;
|
|
||||||
|
|
||||||
$minFlat = $passengerLat - $latDelta;
|
|
||||||
$maxFlat = $passengerLat + $latDelta;
|
|
||||||
$minFlng = $passengerLng - $lngDelta;
|
|
||||||
$maxFlng = $passengerLng + $lngDelta;
|
|
||||||
|
|
||||||
$minTlat = $destLat - $latDelta;
|
|
||||||
$maxTlat = $destLat + $latDelta;
|
|
||||||
$minTlng = $destLng - $lngDelta;
|
|
||||||
$maxTlng = $destLng + $lngDelta;
|
|
||||||
|
|
||||||
// Layer 1: Start and End match within bounding box
|
|
||||||
$sqlComp = "SELECT price_amount AS total_price, (price_amount / price_per_km) AS distance_km
|
|
||||||
FROM scraped_competitor_prices
|
|
||||||
WHERE country_code = :country_code
|
|
||||||
AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
|
|
||||||
AND start_lat BETWEEN :min_flat AND :max_flat
|
|
||||||
AND start_lng BETWEEN :min_flng AND :max_flng
|
|
||||||
AND end_lat BETWEEN :min_tlat AND :max_tlat
|
|
||||||
AND end_lng BETWEEN :min_tlng AND :max_tlng
|
|
||||||
AND price_per_km > 0
|
|
||||||
LIMIT 5";
|
|
||||||
$stmtComp = $con->prepare($sqlComp);
|
|
||||||
$stmtComp->execute([
|
|
||||||
':country_code' => $cc,
|
|
||||||
':min_flat' => $minFlat,
|
|
||||||
':max_flat' => $maxFlat,
|
|
||||||
':min_flng' => $minFlng,
|
|
||||||
':max_flng' => $maxFlng,
|
|
||||||
':min_tlat' => $minTlat,
|
|
||||||
':max_tlat' => $maxTlat,
|
|
||||||
':min_tlng' => $minTlng,
|
|
||||||
':max_tlng' => $maxTlng
|
|
||||||
]);
|
|
||||||
$matches = $stmtComp->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
|
|
||||||
if (empty($matches)) {
|
|
||||||
// Layer 2 Fallback: Start match only within bounding box
|
|
||||||
$sqlFallback = "SELECT price_amount AS total_price, (price_amount / price_per_km) AS distance_km
|
|
||||||
FROM scraped_competitor_prices
|
|
||||||
WHERE country_code = :country_code
|
|
||||||
AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR)
|
|
||||||
AND start_lat BETWEEN :min_flat AND :max_flat
|
|
||||||
AND start_lng BETWEEN :min_flng AND :max_flng
|
|
||||||
AND price_per_km > 0
|
|
||||||
LIMIT 10";
|
|
||||||
$stmtFallback = $con->prepare($sqlFallback);
|
|
||||||
$stmtFallback->execute([
|
|
||||||
':country_code' => $cc,
|
|
||||||
':min_flat' => $minFlat,
|
|
||||||
':max_flat' => $maxFlat,
|
|
||||||
':min_flng' => $minFlng,
|
|
||||||
':max_flng' => $maxFlng
|
|
||||||
]);
|
|
||||||
$matches = $stmtFallback->fetchAll(PDO::FETCH_ASSOC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($matches)) {
|
|
||||||
$normalizedPrices = [];
|
|
||||||
foreach ($matches as $row) {
|
|
||||||
$compDist = (float)$row['distance_km'];
|
|
||||||
$compPrice = (float)$row['total_price'];
|
|
||||||
if ($compDist > 0) {
|
|
||||||
// Only trust competitor trips that are somewhat close in distance scale (within 35%)
|
|
||||||
// Otherwise, extrapolating a 3km traffic-heavy trip to 40km highway trip creates nonsense pricing
|
|
||||||
$ratio = $distance / $compDist;
|
|
||||||
if ($ratio >= 0.65 && $ratio <= 1.35) {
|
|
||||||
$normalizedPrices[] = ($compPrice / $compDist) * $distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($normalizedPrices)) {
|
|
||||||
$competitorTarget = array_sum($normalizedPrices) / count($normalizedPrices);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e) {
|
|
||||||
error_log("[calculateDynamicPrice] Competitor pricing query failed: " . $e->getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($competitorTarget !== null) {
|
|
||||||
$undercutPrice = $competitorTarget * 0.92;
|
|
||||||
$speedBaseRate = getPerKmRate('Speed', $kazanRow);
|
|
||||||
$currentBaseRate = getPerKmRate($carType, $kazanRow);
|
|
||||||
$categoryMultiplier = $speedBaseRate > 0 ? ($currentBaseRate / $speedBaseRate) : 1.0;
|
|
||||||
|
|
||||||
$targetAdjustedPrice = $undercutPrice * $categoryMultiplier;
|
|
||||||
if ($price > $targetAdjustedPrice) {
|
|
||||||
$price = $targetAdjustedPrice;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply kazan (e.g. 11%) on the passenger's price
|
// Apply kazan (e.g. 11%) on the passenger's price
|
||||||
$withCommission = round($price * (1 + $kazanPercent / 100), 2);
|
$withCommission = round($price * (1 + $kazanPercent / 100), 2);
|
||||||
|
|||||||
Reference in New Issue
Block a user