chore: استيراد أولي من سيرو (ecfe7568) — بلا أي تعديل

نسخة كاملة من مستودع سيرو عند ecfe7568 لتكون أساس تطبيق «انطلق».
نُسخ المتعقَّب في git فقط (12,509 ملفاً / 302 م.ب) بـ git archive، لا
`cp -r` — فاستُثنيت تلقائياً مخلفات البناء (build · node_modules ·
.dart_tool · .gradle · Pods ≈ 10.7 غ.ب) وكل ما يستثنيه .gitignore.

هذا الكوميت **بلا أي تعديل عمداً** حتى يكون كل ما يليه فرقاً مقروءاً
مقابل سيرو الأصلي. سيرو نفسه لم يُمسّ.

⚠️ لا يبني بعد: `.env` و`lib/env/env.g.dart` غير متعقَّبين في سيرو (وهذا
صحيح — أسرار لكل مستأجر). كل تطبيق فلاتر هنا يحتاج .env خاصاً بانطلق ثم
توليد env.g.dart عبر build_runner. لا تُنسخ أسرار سيرو.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hamza-Ayed
2026-07-27 05:10:29 +03:00
co-authored by Claude Opus 5
commit 92dc6b3641
3654 changed files with 896478 additions and 0 deletions
+138
View File
@@ -0,0 +1,138 @@
<?php
/**
* cron_empty_results_to_db.php
* سكربت لتفريغ نتائج البوت من ملف results.json إلى قاعدة بيانات MySQL
* يُفضل تشغيله برمجياً كل ساعة أو حسب الحاجة
*/
// Allow script to run indefinitely
set_time_limit(0);
ini_set('memory_limit', '256M');
// Mock request to satisfy connect.php dependencies if any
$_SERVER['REQUEST_METHOD'] = 'POST';
require_once __DIR__ . '/../core/bootstrap.php';
require_once __DIR__ . '/../functions.php';
try {
$con = Database::get('main');
} catch (Exception $e) {
die("Database connection failed: " . $e->getMessage() . "\n");
}
$resultsFile = __DIR__ . '/results.json';
if (!file_exists($resultsFile)) {
die("No results file found.\n");
}
$content = file_get_contents($resultsFile);
$data = json_decode($content, true);
if (empty($data) || !is_array($data)) {
die("No data to process or invalid JSON.\n");
}
$insertedCount = 0;
$stmt = $con->prepare("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, distance_km, duration_min, currency, country_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
foreach ($data as $row) {
if (isset($row['status']) && $row['status'] !== 'success') {
continue;
}
$taskId = $row['task_id'] ?? null;
$resultData = $row['result_data'] ?? [];
$appName = $resultData['app'] ?? $row['app'] ?? 'Unknown';
$competitorName = $appName; // Assuming app_name is competitor_name for now
$startLoc = $resultData['start_location'] ?? $row['start_location'] ?? '';
if (empty($startLoc) && !empty($resultData['start_lat'])) {
$startLoc = "Lat: {$resultData['start_lat']}, Lng: {$resultData['start_lng']}";
}
$endLoc = $resultData['end_location'] ?? $row['end_location'] ?? '';
if (empty($endLoc) && !empty($resultData['end_lat'])) {
$endLoc = "Lat: {$resultData['end_lat']}, Lng: {$resultData['end_lng']}";
}
$priceRaw = $resultData['price'] ?? $row['price'] ?? 0;
$amount = 0.0;
$currency = 'JOD';
if (is_numeric($priceRaw)) {
$amount = (float)$priceRaw;
} else {
$priceStr = (string)$priceRaw;
// Match numeric parts (including decimals) and text parts
if (preg_match('/([\d\.]+)\s*([A-Za-z]+|د\.ا)/', $priceStr, $matches)) {
$amount = (float)$matches[1];
$currency = $matches[2];
if ($currency === 'د.ا') {
$currency = 'JOD';
}
} else {
$amount = (float)$priceStr;
}
}
// Ignore invalid entries without an amount
if ($amount <= 0) {
continue;
}
$distanceKm = (float)($resultData['distance_km'] ?? 1);
$durationMin = isset($resultData['duration_min']) ? (int)$resultData['duration_min'] : null;
$startLat = $resultData['start_lat'] ?? null;
$startLng = $resultData['start_lng'] ?? null;
$endLat = $resultData['end_lat'] ?? null;
$endLng = $resultData['end_lng'] ?? null;
$countryCode = $row['country_code'] ?? 'JO'; // Default
// --- OSRM Integration (Dynamic Distance & Duration) ---
require_once __DIR__ . '/../core/osrm_routing.php';
if ($startLat && $endLat && (!$durationMin || $durationMin <= 0)) {
$osrmResult = getOsrmRouteDetails($startLat, $startLng, $endLat, $endLng, $countryCode);
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
if ($stmt->execute([
$taskId,
$appName,
$competitorName,
$startLoc,
$endLoc,
$startLat,
$startLng,
$endLat,
$endLng,
$amount,
$pricePerKm,
$distanceKm,
$durationMin,
$currency,
$countryCode
])) {
$insertedCount++;
} else {
echo "Failed to insert task_id: $taskId. Error: " . implode(" ", $stmt->errorInfo()) . "\n";
}
}
// Clear the JSON file after successfully inserting data
file_put_contents($resultsFile, json_encode([], JSON_PRETTY_PRINT));
echo "Successfully inserted $insertedCount records into the database and cleared results.json.\n";