getMessage() . "\n"); } echo "Starting AI Formula Discovery Engine...\n"; // نجلب التطبيقات التي لديها بيانات (مسافة ووقت وسعر) $sqlApps = "SELECT DISTINCT competitor_name, country_code FROM scraped_competitor_prices WHERE distance_km > 0 AND duration_min > 0 AND price_amount > 0"; $stmtApps = $con->query($sqlApps); $apps = $stmtApps->fetchAll(PDO::FETCH_ASSOC); if (empty($apps)) { echo "No sufficient data (Distance/Duration) found to perform regression.\n"; exit; } // دالة لحل نظام معادلات خطية (Gaussian Elimination) function solveLinearSystem($A, $B) { $n = count($A); for ($i = 0; $i < $n; $i++) { // Search for maximum in this column $maxEl = abs($A[$i][$i]); $maxRow = $i; for ($k = $i + 1; $k < $n; $k++) { if (abs($A[$k][$i]) > $maxEl) { $maxEl = abs($A[$k][$i]); $maxRow = $k; } } // Swap maximum row with current row for ($k = $i; $k < $n; $k++) { $tmp = $A[$maxRow][$k]; $A[$maxRow][$k] = $A[$i][$k]; $A[$i][$k] = $tmp; } $tmp = $B[$maxRow]; $B[$maxRow] = $B[$i]; $B[$i] = $tmp; // Make all rows below this one 0 in current column for ($k = $i + 1; $k < $n; $k++) { if ($A[$i][$i] == 0) continue; $c = -$A[$k][$i] / $A[$i][$i]; for ($j = $i; $j < $n; $j++) { if ($i == $j) { $A[$k][$j] = 0; } else { $A[$k][$j] += $c * $A[$i][$j]; } } $B[$k] += $c * $B[$i]; } } // Solve equation Ax=b for an upper triangular matrix A $x = array_fill(0, $n, 0); for ($i = $n - 1; $i >= 0; $i--) { if ($A[$i][$i] == 0) continue; $x[$i] = $B[$i] / $A[$i][$i]; for ($k = $i - 1; $k >= 0; $k--) { $B[$k] -= $A[$k][$i] * $x[$i]; } } return $x; } foreach ($apps as $app) { $competitor = $app['competitor_name']; $countryCode = $app['country_code']; echo "Analyzing: $competitor ($countryCode)...\n"; // سحب أحدث 5000 رحلة لتكوين نموذج رياضي دقيق $sqlData = "SELECT distance_km, duration_min, price_amount FROM scraped_competitor_prices WHERE competitor_name = :comp AND country_code = :country AND distance_km > 0 AND duration_min > 0 AND price_amount > 0 ORDER BY id DESC LIMIT 5000"; $stmtData = $con->prepare($sqlData); $stmtData->execute([':comp' => $competitor, ':country' => $countryCode]); $samples = $stmtData->fetchAll(PDO::FETCH_ASSOC); $N = count($samples); if ($N < 10) { echo " -> Not enough samples ($N). Skipping.\n"; continue; } // بناء مصفوفات Least Squares (X^T X) * Beta = (X^T Y) // Beta = [Base_Fare, KM_Price, Min_Price] $sum_x1 = 0; $sum_x2 = 0; $sum_y = 0; $sum_x1_sq = 0; $sum_x2_sq = 0; $sum_x1_x2 = 0; $sum_x1_y = 0; $sum_x2_y = 0; foreach ($samples as $s) { $x1 = (float)$s['distance_km']; $x2 = (float)$s['duration_min']; $y = (float)$s['price_amount']; $sum_x1 += $x1; $sum_x2 += $x2; $sum_y += $y; $sum_x1_sq += ($x1 * $x1); $sum_x2_sq += ($x2 * $x2); $sum_x1_x2 += ($x1 * $x2); $sum_x1_y += ($x1 * $y); $sum_x2_y += ($x2 * $y); } $matrixA = [ [$N, $sum_x1, $sum_x2], [$sum_x1, $sum_x1_sq, $sum_x1_x2], [$sum_x2, $sum_x1_x2, $sum_x2_sq] ]; $matrixB = [ $sum_y, $sum_x1_y, $sum_x2_y ]; // حل المصفوفة try { $beta = solveLinearSystem($matrixA, $matrixB); $baseFare = round(max(0, $beta[0]), 3); // Base fare cannot be negative $kmPrice = round(max(0, $beta[1]), 3); $minPrice = round(max(0, $beta[2]), 3); echo " -> [DISCOVERED] Base Fare: $baseFare, KM: $kmPrice, Min: $minPrice\n"; // حفظ في جدول المعادلات السرية $sqlUpsert = "INSERT INTO competitor_secret_formulas (competitor_name, country_code, base_fare, price_per_km, price_per_min, sample_size) VALUES (:comp, :country, :base, :km, :min, :size) ON DUPLICATE KEY UPDATE base_fare = :base, price_per_km = :km, price_per_min = :min, sample_size = :size, last_updated = NOW()"; $stmtUp = $con->prepare($sqlUpsert); $stmtUp->execute([ ':comp' => $competitor, ':country' => $countryCode, ':base' => $baseFare, ':km' => $kmPrice, ':min' => $minPrice, ':size' => $N ]); echo " -> Saved successfully.\n"; } catch (Exception $e) { echo " -> Error solving matrix: " . $e->getMessage() . "\n"; } } echo "Done.\n"; ?>