getMessage() . "\n"); } echo "Starting Siro AI Engine...\n"; // نسبة الخصم المستهدفة (6.5% من إجمالي سعر الرحلة) $targetMargin = 0.065; // ========================================== // 1. وحدة التسعير الديناميكي بناءً على السعر الإجمالي // ========================================== echo "1. Running Smart Pricing Module (Total Price Formula)...\n"; try { $sql = "SELECT country_code, AVG(price_per_km) as avg_price_km, MIN(price_per_km) as min_price_km FROM scraped_competitor_prices WHERE created_at >= DATE_SUB(NOW(), INTERVAL 3 HOUR) AND price_per_km > 0 GROUP BY country_code"; $stmt = $con->query($sql); $competitorRates = $stmt->fetchAll(PDO::FETCH_ASSOC); foreach ($competitorRates as $rate) { $country = $rate['country_code']; $countryNameMap = ['JO' => 'Jordan', 'SY' => 'Syria', 'EG' => 'Egypt', 'IQ' => 'Iraq']; $countryName = $countryNameMap[$country] ?? null; if ($countryName) { $avgKmPrice = (float)$rate['avg_price_km']; $minKmPrice = (float)$rate['min_price_km']; // 1. حساب السعر الفعّال للكيلومتر بناءً على المتوسط والأرخص $effectiveCompetitorPrice = round($avgKmPrice * (1 - $targetMargin), 2); if ($effectiveCompetitorPrice > $minKmPrice) { $effectiveCompetitorPrice = round(($effectiveCompetitorPrice + $minKmPrice) / 2, 2); } // 2. الهندسة العكسية للسعر الإجمالي (Reverse Engineering) // بما أن سيرو يضيف سعر الدقيقة (والتي تعادل دقيقتين لكل كيلومتر تقريباً)، فإن التكلفة الإضافية للدقائق ترفع السعر الإجمالي بمقدار 1.5x // لضمان أن يكون السعر النهائي أقل بـ 6%، نقسم الناتج على 1.5 ليمتص تكلفة الدقائق. $calculatedSpeedPrice = round($effectiveCompetitorPrice / 1.5, 3); // 3. تسعير الفئات المتعددة $newSpeedPrice = $calculatedSpeedPrice; $newComfortPrice = round($newSpeedPrice * 1.30, 3); $newLadyPrice = round($newSpeedPrice * 1.10, 3); $newElectricPrice = round($newSpeedPrice * 1.20, 3); $newVanPrice = round($newSpeedPrice * 1.50, 3); $newDeliveryPrice = round($newSpeedPrice * 0.90, 3); $newMishwarVipPrice = round($newSpeedPrice * 1.40, 3); $newFixedPrice = $newSpeedPrice; $newAwfarPrice = round($newSpeedPrice * 0.85, 3); // أسعار الدقائق if ($country === 'JO') { $newNormalMin = 0.06; $newPeakMin = 0.07; $newLateMin = 0.08; } else { $newNormalMin = round($newSpeedPrice / 4, 3); $newPeakMin = round($newNormalMin * 1.15, 3); $newLateMin = round($newNormalMin * 1.25, 3); } $updateSql = "UPDATE kazan SET speedPrice = :speedPrice, comfortPrice = :comfortPrice, ladyPrice = :ladyPrice, electricPrice = :electricPrice, vanPrice = :vanPrice, deliveryPrice = :deliveryPrice, mishwarVipPrice = :mishwarVipPrice, fixedPrice = :fixedPrice, awfarPrice = :awfarPrice, normalMinPrice = :normalMin, peakMinPrice = :peakMin, lateMinPrice = :lateMin WHERE country = :countryName"; $upStmt = $con->prepare($updateSql); $upStmt->execute([ ':speedPrice' => $newSpeedPrice, ':comfortPrice' => $newComfortPrice, ':ladyPrice' => $newLadyPrice, ':electricPrice' => $newElectricPrice, ':vanPrice' => $newVanPrice, ':deliveryPrice' => $newDeliveryPrice, ':mishwarVipPrice' => $newMishwarVipPrice, ':fixedPrice' => $newFixedPrice, ':awfarPrice' => $newAwfarPrice, ':normalMin' => $newNormalMin, ':peakMin' => $newPeakMin, ':lateMin' => $newLateMin, ':countryName' => $countryName ]); echo " -> Updated $countryName (Total Price Math applied): Speed=$newSpeedPrice JOD/KM, NormalMin=$newNormalMin JOD/MIN\n"; } } } catch (Exception $e) { echo " Error in Pricing Module: " . $e->getMessage() . "\n"; } // ========================================== // 2. وحدة توجيه السائقين (Demand Predictor) // ========================================== echo "2. Running Demand Predictor Module...\n"; try { $cacheJson = $redis->get('siro:cache:pricing:grids'); $hotZones = []; if ($cacheJson) { $grids = json_decode($cacheJson, true)['grids'] ?? []; foreach ($grids as $key => $data) { if (strpos($key, 'FALLBACK') !== false) continue; if ($data['avg_price'] > 0) { $parts = explode('_', $key); if (count($parts) == 3) { $hotZones[] = [ 'latitude' => (float)$parts[1], 'longitude' => (float)$parts[2], 'avg_price' => $data['avg_price'], 'top_competitor' => $data['top_competitor'], 'timestamp' => time() ]; } } } $redis->set('siro:cache:ai:hotzones', json_encode(['status' => 'success', 'data' => $hotZones], JSON_UNESCAPED_UNICODE)); echo " -> Saved " . count($hotZones) . " Hot Zones to Redis for Driver Map Guidance.\n"; } } catch (Exception $e) { echo " Error in Demand Predictor: " . $e->getMessage() . "\n"; } // ========================================== // 3. وحدة استهداف الركاب الخاملين (Smart Retention) // ========================================== echo "3. Running Smart Retention Module...\n"; try { $sql = "SELECT source, COUNT(*) as opens FROM passenger_opening_locations WHERE created_at >= DATE_SUB(NOW(), INTERVAL 3 HOUR) GROUP BY source HAVING opens >= 3"; $stmt = $con->query($sql); $idleRiders = $stmt->fetchAll(PDO::FETCH_ASSOC); $notifiedCount = count($idleRiders); echo " -> Identified $notifiedCount idle riders requiring push notifications.\n"; } catch (Exception $e) { echo " Error in Smart Retention: " . $e->getMessage() . "\n"; } echo "AI Engine finished successfully.\n"; ?>