🚀 محاكاة نظام Siro الكاملة

جميع الإضافات والتغييرات التي تم العمل عليها بتاريخ 2026-06-21

5
Commits رئيسية
74
ملف معدل/مضاف
8
أنظمة فرعية
2
لغات (Dart/Kotlin)
المرحلة الأولى: Cron Job يولد مهام تسعير المنافسين backend/bot/generate_price_tasks.php
كل 15 دقيقة | المناطق: 10 مناطق في دمشق | المنافسون: YallaGo • Zaken • Tfadal
1
الاتصال بقاعدة البيانات و Redis
يتم تحميل boostrap.php لإنشاء اتصال MySQL و Redis
2
إنشاء جدول competitor_prices إن لم يكن موجوداً
CREATE TABLE IF NOT EXISTS competitor_prices ( id INT AUTO_INCREMENT PRIMARY KEY, competitor_name VARCHAR(50), from_latitude VARCHAR(30), from_longitude VARCHAR(30), to_latitude VARCHAR(30), to_longitude VARCHAR(30), distance_km DECIMAL(8,2), total_price DECIMAL(10,2), price_per_km DECIMAL(8,2), country_code VARCHAR(5) DEFAULT 'SY', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );
3
توليد نقاط عشوائية لـ 10 مناطق رئيسية في دمشق
ساحة الأمويين المزة المالكي كفرسوسة الميدان باب توما ركن الدين دمر برامكة المهاجرين
لكل منطقة: نقطة بداية عشوائية ضمن 2 كم + رحلة قصيرة (2-5 كم) + رحلة طويلة (10-15 كم)
4
إدراج المهام في Redis Queue
استخدام LPUSH إلى queue:bot:tasks
// 10 مناطق × رحلتين × 3 منافسين = 60 مهمة كل 15 دقيقة $redis->lpush('queue:bot:tasks', json_encode($taskData)); echo "Successfully generated and queued $tasksCreated pricing tasks.";
🤖 المرحلة الثانية: Android Bot يسحب المهام وينفذها android_bot/
آلية السحب: Polling كل 15 ثانية | الأجهزة المسجلة: SHAM_CASH_BOT_01 • PRICE_SCRAPER_BOT_01
1
WorkerClient.kt — التوقيع HMAC-SHA256
fun generateSignature(deviceId: String, ts: Long): String { val message = "$deviceId$ts" val algorithm = "HmacSHA256" val mac = Mac.getInstance(algorithm) val secretKeySpec = SecretKeySpec(SECRET_KEY.toByteArray(), algorithm) mac.init(secretKeySpec) val hashBytes = mac.doFinal(message.toByteArray()) return hashBytes.joinToString("") { "%02x".format(it) } }
2
إرسال GET إلى standalone_worker.php
GET /standalone_worker.php?device_id=ANDROID_ID&ts=1718970000&sig=abc123... → Response (JSON): { "status": "success", "has_task": true, "task": { "task_id": "prc_667b8e2f", "type": "price_check", "app": "com.zakinn.app", "payload": { "start_lat": 33.5138, "start_lng": 36.2765, "end_lat": 33.5350, "end_lng": 36.2950 } } }
3
ScraperAccessibilityService.kt — نقر آلي
آلة حالة متكاملة لتطبيقات المنافسين:
IDLE → LAUNCHING_APP → SEARCHING_START → SEARCHING_END → READING_PRICE → SUBMITTING
YallaGo البحث عن "Where to" أو "أين تريد الذهاب" والنقر عليه
Zakinn استخدام findAccessibilityNodeInfosByViewId للـ TextInput
Tfadal البحث بـ 7 لغات مختلفة (AR/EN/TR) عن حقول الإدخال
4
قراءة السعر وإرسال النتيجة
// قراءة السعر من النصوص التي تحتوي على SYP, ل.س, AED, SP searchPriceByCurrency(node) → "ل.س 12,500" → submitPriceToServer → POST /standalone_worker.php { "device_id": "...", "ts": 1718970000, "sig": "...", "task_id": "prc_667b8e2f", "type": "price_check", "status": "success", "result_data": { "app": "com.zakinn.app", "distance_km": 4.8, "price": 12500, "start_lat": 33.5138, "start_lng": 36.2765, "end_lat": 33.5350, "end_lng": 36.2950 } }
⚙️ المرحلة الثالثة: Worker يستقبل النتائج ويخزنها backend/bot/worker.php
1
استقبال POST مع التحقق من HMAC-SHA256
// التحقق من التوقيع + منع Replay Attacks (صلاحية 5 دقائق) if (abs(time() - $ts) > 300) → رفض الطلب $expected_sig = hash_hmac('sha256', $device_id . $ts, $SECRET_KEY); hash_equals($expected_sig, $sig) → تحقق آمن من التوقيع
2
تخزين السعر في MySQL + Redis
// MySQL: حفظ البيانات للتقارير اللاحقة $stmt = $con->prepare("INSERT INTO competitor_prices (...) VALUES (...?)"); $stmt->execute([$app_name, $start_lat, $start_lng, $end_lat, $end_lng, $distance_km, $price, $pricePerKm, $country_code]); // Redis: حفظ آخر 50 سعر لكل تطبيق للتسعير الديناميكي $redis->lpush("competitor:price_history:$app_name", $pricePerKm); $redis->ltrim("competitor:price_history:$app_name", 0, 49);
📊 المرحلة الرابعة: Standalone Worker Dashboard (واجهة تحكم) standalone_worker.php
1
واجهة مدير متكاملة (HTML/CSS)
نظام ملفات JSON (tasks.json / results.json) — بدون حاجة لقاعدة بيانات
قائمة المهام المعلقة سجل النتائج المنجزة نموذج إضافة مهمة يدوية
2
عينة من البيانات المعروضة
#التطبيقالمسارالسعرالحالة
1YallaGoالمزة → مطار دمشق12,500 SYP✅ نجاح
2Zakinnساحة الأمويين → دمر8,200 SYP✅ نجاح
3Tfadalالمالكي → كفرسوسة❌ فشل
4YallaGoبرامكة → المهاجرين15,000 SYP✅ نجاح
5Zakinnالميدان → باب توما6,750 SYP✅ نجاح
🧠 المرحلة الخامسة: نظام التسويق الذكي بالذكاء الاصطناعي (Gemini AI) SiroGeminiService.php + trigger_campaign.php
1
المدير يضغط "إطلاق حملة استعادة ذكية فوراً"
من siro_admin → Marketing Page
// Flutter Controller: marketing_controller.dart Future triggerAICampaign() async { var res = await CRUD().post(link: AppLink.triggerCampaign, payload: params); // → POST /Admin/marketing/trigger_campaign.php }
2
PHP يسحب آخر أسعار المنافسين ويرسلها إلى Gemini AI
$sqlPrices = "SELECT competitor_name, total_price, distance_km FROM competitor_prices WHERE country_code = :country ORDER BY created_at DESC LIMIT 10"; // البيانات تسحب من جدول competitor_prices الذي ملأه البوت! $geminiService = new SiroGeminiService(); $aiCampaign = $geminiService->analyzeMarketAndDraftCampaign( $competitorPrices, $siroBasePrice, $regionName, $countryCode );
3
Gemini AI يحلل ويكتب حملة تسويقية كاملة
// SiroGeminiService.php — إرسال prompt إلى Gemini API $prompt = " أنت خبير تسويق ذكي لتطبيق Siro... 1. أسعار المنافسين: " . json_encode($competitorPrices) . " 2. سعر Siro الأساسي: 10000 SYP الخرج المطلوب JSON: { \"opportunity_detected\": true, \"recommended_price\": 8500, \"discount_percentage\": 15, \"promo_code\": \"SIRODM15\", \"push_title\": \"🔥 وفر 15% على رحلتك!\", \"push_body\": \"خصم خاص لسكان دمشق! استخدم كود SIRODM15\", \"sms_body\": \"اشتقنا لك يا ${passenger_name}! عد إلينا ووفر 15% مع كود SIRODM15\" }"
4
إرسال الإشعارات والحملات الترويجية
FCM Push للمستخدمين النشطين (بدون حدود سبام)
WhatsApp للمستخدمين المنقطعين (مع anti-spam 24 ساعة)
SMS كخيار احتياطي إذا فشل WhatsApp
// trigger_campaign.php foreach ($targets as $target) { if ($fcmToken) { sendFcmNotification($fcmToken, $pushTitle, $pushBody, $fcmData); $sentFcm++; } else { if ($spamCount === 0) { // anti-spam sendWhatsAppFromServer($decryptedPhone, $smsBody); $sentWhatsApp++; } } }
5
تسجيل الحملة في سجل التدقيق
// Audit Log logAudit($con, $user_id, 'trigger_marketing_campaign', 'promos', $promoCode, [ 'promo_code' => $promoCode, 'targets_count' => count($dispatchedPassengers) ]); // Response للمدير: { "campaign_created": true, "promo_code": "SIRODM15", "push_notification": { "sent_count": 34 }, "whatsapp_sms": { "whatsapp_sent_count": 12, "sms_sent_count": 5 }, "total_dispatched": 51 }
💰 المرحلة السادسة: محرك التسعير الديناميكي يستخدم بيانات المنافسين backend/ride/pricing/get.php
1
حساب السعر مع الـ Surge Multiplier من Redis
// قراءة الطلب (demand) من Redis الرئيسي $demandCount = (int)$redis->get("demand:grid:" . $grid_id); // قراءة السائقين المتاحين من Redis الموقع $drivers = $redisLocation->georadius('geo:drivers:available', $lng, $lat, 0.75, 'km'); if ($demandCount > 0 && $availableDrivers > 0) { $surgeRatio = $demandCount / $availableDrivers; if ($surgeRatio > 1.2) { $surgeMultiplier = 1.0 + ($surgeRatio - 1.2) * 0.5; // Capped at 3.0 } }
2
تطبيق التسعير التنافسي (Competitor Undercut — أقل بـ 8%)
// البحث عن أسعار منافسين لنفس المنطقة الجغرافية SELECT total_price, distance_km FROM competitor_prices WHERE country_code = 'SY' AND (from_latitude + 0.0) BETWEEN :min_flat AND :max_flat AND created_at >= DATE_SUB(NOW(), INTERVAL 24 HOUR) // إذا وجدنا تطابق → نخفض سعرنا ليكون أقل من المنافس بـ 8% if ($competitorTarget !== null) { $undercutPrice = $competitorTarget * 0.92; // أقل بــ 8% 🎯 if ($price > $targetAdjustedPrice) { $price = $targetAdjustedPrice; // تطبيق السعر التنافسي } }
3
تطبيق الخصم (Promo Code) + الديون السابقة + التوقيع المشفر
// التحقق من صلاحية الكود الترويجي $sqlPromo = "SELECT amount FROM promos WHERE promo_code = :code AND ..."; $discount = (float) $promoData['amount']; // إضافة الديون السابقة $redisDebt = $redisInstance->get("passenger_debt_" . $passenger_id); $finalPrice += (float) $redisDebt; // توقيع السعر بشكل مشفر لمنع التلاعب $priceToken = $encryptionHelper->encryptData(json_encode([ 'passenger_id' => $passenger_id, 'distance' => $distance, 'duration' => $duration, 'expires' => time() + 420, // 7 دقائق فقط 'prices' => $pricesRaw ]));
🔌 المرحلة السابعة: WebSocket — الاتصال المباشر مع السائقين socket_intaleq/driver_socket.php
🚀 المستوى الثاني (Level 2 Architecture) | بورت 2020 WebSocket | بورت 2021 HTTP Internal
1
اتصال السائق بالـ Socket
// siro_driver → background_service.dart → Socket.IO socket = IO.io(AppLink.locationSocketUrl, OptionBuilder() .setQuery({'driver_id': driverId, 'token': token})); // server side: driver_socket.php $socket->join('driver_' . $driverId); $connectedDrivers[$driverId] = ['conn' => $socket, 'platform' => $platform, 'token' => $token];
2
تحديث الموقع مع Redis Pipeline Buffering (Level 2)
// السائق يرسل موقعه ← يتم تجميع الأحداث كل 500ms $socket->on('update_location', function($data) use (&$eventBuffer) { // حساب التغيير الفعال (تجنب عمليات Redis غير الضرورية) if (!$didMove && !$speedChanged && !$headingChanged && !$statusChanged) return; // التخزين المؤقت → Redis Pipeline $eventBuffer[$driverId] = [ 'hmset' => ['heading' => $heading, 'speed' => $speed, 'status' => $status], 'geoadd' => ['status' => $status, 'lng' => $lng, 'lat' => $lat], 'status_change' => ['old' => $oldStatus, 'new' => $newStatus] ]; }); // Timer كل 500ms: تنفيذ Pipeline Timer::add(0.5, function() { $pipe = $redis->pipeline(); foreach ($eventBuffer as $driverId => $ops) { /* تنفيذ مجمع */ } $pipe->execute(); $eventBuffer = []; });
تحسين أداء بدلاً من 3 عمليات Redis لكل تحديث → عملية واحدة كل 500ms لكل السائقين
3
إرسال الطلبات الجديدة (Dispatch + Market)
// HTTP Internal → dispatch_order $io->to('driver_' . $driverId)->emit('new_ride_request', $payload); if ($platform === 'ios') sendFCM_Async($token, 'طلب جديد', 'لديك رحلة جديدة'); // Market New Ride $redis->geoadd('geo:rides:waiting', $lng, $lat, $rideId); $nearbyDrivers = $redis->georadius('geo:drivers:available', $lng, $lat, 50, 'km'); foreach ($nearbyDrivers as $driverId) { $io->to('driver_' . $driverId)->emit('market_new_ride', $payload); }
4
تحديث موقع السائق إلى الراكب (Forward to Passenger Socket)
// Throttle: إرسال الموقع للراكب فقط إذا تحرك >15 متر أو مر >3 ثواني function forwardLocationToPassengerSocket(...) { if ($dist < FORWARD_MIN_METERS && $timeDiff < FORWARD_MAX_SECONDS) return; $http = new AsyncHttp(); $http->request($passengerSocketUrl, ['method' => 'POST', 'data' => $payload, 'headers' => ['x-internal-key' => $internalKey]]); }
📍 المرحلة الثامنة: تطبيق السائق — الوجهة المقترحة والخلفية siro_driver/
1
DestinationController — إدارة الوجهة
// حفظ الوجهة (حد أقصى مرتين في اليوم) Future saveDestination(LatLng position, String name) async { final response = await CRUD().post(link: AppLink.saveDriverDestination, payload: { 'action': 'set', 'destination_lat': position.latitude.toString(), 'destination_lng': position.longitude.toString(), 'destination_name': name, }); // تحقق من رسالة "الحد الأقصى لتعديل الوجهة" if (msg.contains("الحد الأقصى") || msg.contains("limit")) { mySnackbarWarning('You have reached the daily limit'); } } // جلب الوجهة الحالية + مسحها fetchActiveDestination() / clearDestination()
2
Background Service — استقبال الطلبات في الخلفية
// Socket في الخلفية ← عند وصول new_ride_request socket.on('new_ride_request', (data) async { if (isAppInForeground || overlayActive) return; // لا نكرر // أندرويد: نعرض Overlay فوق أي تطبيق await FlutterOverlayWindow.showOverlay( overlayTitle: "طلب جديد 🚖", overlayContent: "لديك طلب رحلة جديد!", flag: OverlayFlag.focusPointer, ); // iOS: نعرض Local Notification flutterLocalNotificationsPlugin.show(1002, "طلب رحلة جديد 🚖", ...); });
📱 المرحلة التاسعة: Admin App — لوحة التسويق الذكي siro_admin/
1
MarketingController — التحكم بالأسواق والحملات
يدير كل من: Anomalies Campaigns Log Telemetry Price Comparison What-If Simulator
// دوال رئيسية: fetchAnomalies() // شواذ الأسعار fetchCampaignsLog() // سجل الحملات fetchTelemetry() // استهلاك API والتكاليف fetchPriceComparison() // مقارنة الأسعار + PCI fetchPriceGapHeatmap() // خارطة الفجوات السعرية fetchMarketShareAnalytics() // تطور الحصة السوقية fetchAiPricePrediction() // توقعات AI fetchWinbackTargets() // أهداف الاستعادة triggerAICampaign() // إطلاق حملة AI runWhatIfSimulation(price) // محاكي تغيير الأسعار
2
واجهة MarketingPage متكاملة بـ 3 تبويبات
التبويب 1: شواذ الأسعار والمنافسين
- بطاقة التحكم بالـ AI (Gemini)
- توقعات الذكاء الاصطناعي (Siro AI Prediction)
- محاكي تغيير الأسعار الذكي (What-If Simulator)
- رسم بياني لتطور الحصة السوقية (آخر 12 أسبوع)
- رسم بياني لمقارنة تقلبات الأسعار اللحظية
- خارطة الفجوات ومؤشر التنافسية السعري (PCI)
- أهداف استعادة العملاء (Win-Back)

التبويب 2: سجل الحملات المنجزة
- عرض الحملات المرسلة (Push / WhatsApp / SMS)

التبويب 3: إعدادات الأتمتة والتحكم
- مراقب استهلاك الرموز API Telemetry
- تفعيل/تعطيل الـ Autopilot
- تعديل System Prompt للذكاء الاصطناعي
3
What-If Simulator — محاكي السيناريوهات
// مثلاً: المدير يقترح سعر 8500 لكل كم POST /Admin/marketing/what_if_simulator.php?speed_price=8500&country_code=SY → Response: { "simulated_pci": 0.89, "market_share_percent": 72.5, "recommendation_status": "success", "recommendation_message": "✅ السعر المقترح 8500 SYP/كم سيجعلنا أرخص من جميع المنافسين!" }
🗣️ المرحلة العاشرة: تطبيق الراكب — الملاحة والـ TTS siro_rider/
1
NavigationView + NavigationController — الملاحة
واجهة ملاحة كاملة مع: معلومات المسار، وقت الوصول، المسافة المتبقية
2
TTS (Text-to-Speech) Controller
تحويل إرشادات الملاحة إلى صوت بالعربية — إعلانات صوتية للمنعطفات
// siro_rider/lib/controller/functions/tts.dart class TextToSpeechController extends GetxController { Future speakText(String text) async { await flutterTts.setLanguage("ar-SA"); await flutterTts.setSpeechRate(0.5); await flutterTts.speak(text); } }
🔁 مخطط تدفق البيانات الكامل — دورة متكاملة
⏰ Cron Job (15 دقيقة)
↓ يولد
📋 60 مهمة تسعير → Redis Queue
↓ يسحب
🤖 Android Bot (Accessibility Service)
↓ يفتح التطبيق وينقر آلياً ويقرأ
📱 YallaGo • Zakinn • Tfadal
↓ يرسل النتائج
📊 Worker → MySQL (competitor_prices) + Redis
↓ يستخدم في
💰 محرك التسعير الديناميكي (Undercut 8%)
↓ ويستخدم في
🧠 Gemini AI Campaign Generator
↓ يرسل
📣 FCM Push + WhatsApp + SMS → الركاب
↓ وأيضاً
📊 Admin Dashboard يعرض التحليلات
📁 هيكلية الملفات المضافة والمعدلة اليوم
📱 siro_driver/
├── lib/constant/links.dart
├── lib/controller/functions/background_service.dart
├── lib/controller/functions/location_controller.dart
├── lib/controller/home/captin/
│ ├── destination_controller.dart
│ ├── home_captain_controller.dart
│ └── order_request_controller.dart
├── lib/controller/local/ar_eg.dart
├── lib/controller/local/ar_jo.dart
├── lib/controller/local/ar_sy.dart
├── lib/controller/local/en.dart
├── lib/views/home/Captin/home_captain/
│ ├── home_captin.dart
│ └── widget/destination_bottom_sheet.dart
└── lib/views/home/Captin/mapDriverWidgets/passenger_info_window.dart
⚙️ backend/
├── bot/
│ ├── generate_price_tasks.php (Cron Job)
│ ├── worker.php (Redis Worker Endpoint)
│ └── standalone_worker.php (Dashboard)
├── core/Services/SiroGeminiService.php
├── Admin/marketing/
│ ├── trigger_campaign.php
│ ├── get_price_comparison.php
│ ├── get_market_anomalies.php
│ ├── get_telemetry.php
│ └── get_campaigns_log.php
├── ride/pricing/get.php
├── ride/location/save_driver_destination.php
└── ride/rides/add_ride.php, acceptRide.php, cancel*.php
🤖 android_bot/
├── service/ScraperAccessibilityService.kt
├── service/AppLauncher.kt
├── network/WorkerClient.kt
└── MainActivity.kt
الخلاصة — ماذا أنجزنا اليوم؟
مكتمل Android Bot — نقر آلي ذكي (Accessibility Service) مع آلة حالة متكاملة لـ 3 تطبيقات منافسة
مكتمل Cron Job — توليد 60 مهمة تسعير كل 15 دقيقة لـ 10 مناطق في دمشق
مكتمل Worker Endpoint — استقبال نتائج البوت مع HMAC Authentication + MySQL/Redis
مكتمل Gemini AI — خدمة تحليل أسعار وصياغة حملات تسويقية بالعربية (لهجات محلية)
مكتمل Marketing Campaign — إطلاق حملات عبر FCM + WhatsApp + SMS مع Anti-Spam
مكتمل Pricing Engine — تسعير ديناميكي مع Undercut 8% عن المنافسين + Surge Pricing
مكتمل WebSocket Level 2 — Redis Pipeline Buffering كل 500ms + Forward للموقع
مكتمل Destination System — وجهة السائق مع حد يومي + خلفية مع Overlay للطلبات
مكتمل Admin Dashboard — لوحة تسويق ذكية مع PCI, Heatmap, What-If Simulator, Telemetry
مكتمل Standalone Dashboard — واجهة تحكم كاملة للبوت بدون حاجة Redis/MySQL