Files
Siro/knowledge/full_system_simulation_ar.html
2026-06-22 00:31:29 +03:00

1056 lines
42 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>محاكاة نظام Siro الكاملة - اليوم 2026-06-21</title>
<style>
@import url('https://fonts.googleapis.com/css2?family=Cairo:wght@300;400;600;700;800&display=swap');
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Cairo', sans-serif;
background: #0a0e17;
color: #e2e8f0;
padding: 2rem 1rem;
direction: rtl;
}
.container { max-width: 1300px; margin: 0 auto; }
h1 {
font-size: 2.5rem;
font-weight: 800;
background: linear-gradient(135deg, #3b82f6, #10b981, #f59e0b);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
text-align: center;
margin-bottom: 0.5rem;
}
.subtitle {
text-align: center;
color: #64748b;
margin-bottom: 2.5rem;
font-size: 1.1rem;
}
.stats-bar {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
margin-bottom: 2rem;
}
.stat-card {
background: linear-gradient(135deg, rgba(30, 41, 59, 0.8), rgba(15, 23, 42, 0.8));
border: 1px solid rgba(255,255,255,0.05);
border-radius: 16px;
padding: 1.25rem;
text-align: center;
backdrop-filter: blur(12px);
}
.stat-value { font-size: 2rem; font-weight: 800; color: #3b82f6; }
.stat-label { font-size: 0.85rem; color: #64748b; margin-top: 0.25rem; }
.flow-section {
background: linear-gradient(135deg, rgba(30, 41, 59, 0.5), rgba(15, 23, 42, 0.5));
border: 1px solid rgba(255,255,255,0.05);
border-radius: 20px;
padding: 1.5rem;
margin-bottom: 1.5rem;
backdrop-filter: blur(12px);
}
.flow-title {
font-size: 1.4rem;
font-weight: 700;
margin-bottom: 1.25rem;
display: flex;
align-items: center;
gap: 0.75rem;
padding-bottom: 0.75rem;
border-bottom: 1px solid rgba(255,255,255,0.05);
}
.flow-title .icon { font-size: 1.5rem; }
.step {
display: flex;
gap: 1rem;
padding: 0.75rem 0;
border-bottom: 1px solid rgba(255,255,255,0.03);
position: relative;
}
.step:last-child { border-bottom: none; }
.step-num {
width: 32px;
height: 32px;
min-width: 32px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-weight: 800;
font-size: 0.85rem;
background: rgba(59, 130, 246, 0.15);
color: #3b82f6;
border: 1px solid rgba(59, 130, 246, 0.3);
}
.step-desc { flex: 1; }
.step-desc .title { font-weight: 700; font-size: 1rem; color: #f1f5f9; }
.step-desc .detail { font-size: 0.9rem; color: #94a3b8; margin-top: 0.25rem; }
.step-desc .code {
background: rgba(0,0,0,0.3);
border: 1px solid rgba(255,255,255,0.05);
border-radius: 8px;
padding: 0.75rem;
margin-top: 0.5rem;
font-family: 'Courier New', monospace;
font-size: 0.8rem;
color: #a5b4fc;
direction: ltr;
text-align: left;
overflow-x: auto;
white-space: pre-wrap;
word-break: break-all;
}
.tag {
display: inline-block;
padding: 0.15rem 0.5rem;
border-radius: 6px;
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
margin-left: 0.5rem;
}
.tag-success { background: rgba(16,185,129,0.15); color: #34d399; border: 1px solid rgba(16,185,129,0.3); }
.tag-warning { background: rgba(245,158,11,0.15); color: #fbbf24; border: 1px solid rgba(245,158,11,0.3); }
.tag-info { background: rgba(59,130,246,0.15); color: #60a5fa; border: 1px solid rgba(59,130,246,0.3); }
.tag-error { background: rgba(239,68,68,0.15); color: #f87171; border: 1px solid rgba(239,68,68,0.3); }
.tag-purple { background: rgba(139,92,246,0.15); color: #a78bfa; border: 1px solid rgba(139,92,246,0.3); }
.arrow-connector {
display: flex;
justify-content: center;
padding: 0.25rem;
color: #334155;
font-size: 1.5rem;
}
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.5rem; }
@media (max-width: 768px) { .grid-2 { grid-template-columns: 1fr; } }
.timeline-bar {
background: rgba(0,0,0,0.2);
border-radius: 99px;
padding: 0.75rem 1.25rem;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 1rem;
font-size: 0.85rem;
color: #64748b;
}
.timeline-bar .time { color: #3b82f6; font-weight: 700; font-family: monospace; }
.highlight { color: #fbbf24; font-weight: 700; }
.highlight-green { color: #34d399; font-weight: 700; }
.highlight-blue { color: #60a5fa; font-weight: 700; }
.data-table {
width: 100%;
border-collapse: collapse;
margin-top: 0.75rem;
font-size: 0.85rem;
}
.data-table th {
background: rgba(59,130,246,0.1);
padding: 0.5rem 0.75rem;
text-align: right;
color: #94a3b8;
font-weight: 700;
border-bottom: 1px solid rgba(255,255,255,0.05);
}
.data-table td {
padding: 0.5rem 0.75rem;
border-bottom: 1px solid rgba(255,255,255,0.03);
color: #cbd5e1;
}
.json-block {
background: rgba(0,0,0,0.3);
border: 1px solid rgba(255,255,255,0.05);
border-radius: 12px;
padding: 1rem;
margin: 0.75rem 0;
font-family: 'Courier New', monospace;
font-size: 0.8rem;
color: #a5b4fc;
direction: ltr;
text-align: left;
overflow-x: auto;
white-space: pre-wrap;
word-break: break-all;
}
</style>
</head>
<body>
<div class="container">
<h1>🚀 محاكاة نظام Siro الكاملة</h1>
<p class="subtitle">جميع الإضافات والتغييرات التي تم العمل عليها بتاريخ 2026-06-21</p>
<div class="stats-bar">
<div class="stat-card">
<div class="stat-value" style="color:#3b82f6;">5</div>
<div class="stat-label">Commits رئيسية</div>
</div>
<div class="stat-card">
<div class="stat-value" style="color:#10b981;">74</div>
<div class="stat-label">ملف معدل/مضاف</div>
</div>
<div class="stat-card">
<div class="stat-value" style="color:#f59e0b;">8</div>
<div class="stat-label">أنظمة فرعية</div>
</div>
<div class="stat-card">
<div class="stat-value" style="color:#a78bfa;">2</div>
<div class="stat-label">لغات (Dart/Kotlin)</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 1: CRON JOB GENERATES TASKS -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon"></span>
<span>المرحلة الأولى: Cron Job يولد مهام تسعير المنافسين</span>
<span class="tag tag-warning">backend/bot/generate_price_tasks.php</span>
</div>
<div class="timeline-bar">
<span>كل <span class="time">15 دقيقة</span></span>
<span>|</span>
<span>المناطق: <span class="highlight">10 مناطق في دمشق</span></span>
<span>|</span>
<span>المنافسون: <span class="highlight">YallaGo • Zaken • Tfadal</span></span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">الاتصال بقاعدة البيانات و Redis</div>
<div class="detail">يتم تحميل <span class="highlight-blue">boostrap.php</span> لإنشاء اتصال MySQL و Redis</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">إنشاء جدول competitor_prices إن لم يكن موجوداً</div>
<div class="code">
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
);
</div>
</div>
</div>
<div class="step">
<div class="step-num">3</div>
<div class="step-desc">
<div class="title">توليد نقاط عشوائية لـ 10 مناطق رئيسية في دمشق</div>
<div class="detail">
<span class="tag tag-info">ساحة الأمويين</span>
<span class="tag tag-info">المزة</span>
<span class="tag tag-info">المالكي</span>
<span class="tag tag-info">كفرسوسة</span>
<span class="tag tag-info">الميدان</span>
<span class="tag tag-info">باب توما</span>
<span class="tag tag-info">ركن الدين</span>
<span class="tag tag-info">دمر</span>
<span class="tag tag-info">برامكة</span>
<span class="tag tag-info">المهاجرين</span>
</div>
<div class="detail" style="margin-top:0.5rem;">لكل منطقة: نقطة بداية عشوائية ضمن <span class="highlight">2 كم</span> + رحلة قصيرة <span class="highlight-green">(2-5 كم)</span> + رحلة طويلة <span class="highlight-green">(10-15 كم)</span></div>
</div>
</div>
<div class="step">
<div class="step-num">4</div>
<div class="step-desc">
<div class="title">إدراج المهام في Redis Queue</div>
<div class="detail">استخدام <span class="highlight-blue">LPUSH</span> إلى <span class="highlight">queue:bot:tasks</span></div>
<div class="code">
// 10 مناطق × رحلتين × 3 منافسين = 60 مهمة كل 15 دقيقة
$redis->lpush('queue:bot:tasks', json_encode($taskData));
echo "Successfully generated and queued $tasksCreated pricing tasks.";
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 2: BOT FETCHES TASKS -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">🤖</span>
<span>المرحلة الثانية: Android Bot يسحب المهام وينفذها</span>
<span class="tag tag-success">android_bot/</span>
</div>
<div class="timeline-bar">
<span>آلية السحب: <span class="time">Polling كل 15 ثانية</span></span>
<span>|</span>
<span>الأجهزة المسجلة: <span class="highlight">SHAM_CASH_BOT_01 • PRICE_SCRAPER_BOT_01</span></span>
</div>
<div class="grid-2">
<div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">WorkerClient.kt — التوقيع HMAC-SHA256</div>
<div class="code">
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) }
}
</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">إرسال GET إلى standalone_worker.php</div>
<div class="code">
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
}
}
}
</div>
</div>
</div>
</div>
<div>
<div class="step">
<div class="step-num">3</div>
<div class="step-desc">
<div class="title">ScraperAccessibilityService.kt — نقر آلي</div>
<div class="detail">آلة حالة متكاملة لتطبيقات المنافسين:</div>
<div class="code">
IDLE → LAUNCHING_APP → SEARCHING_START → SEARCHING_END → READING_PRICE → SUBMITTING
</div>
<div class="detail" style="margin-top:0.5rem;">
<span class="tag tag-success">YallaGo</span> البحث عن "Where to" أو "أين تريد الذهاب" والنقر عليه
<br>
<span class="tag tag-success">Zakinn</span> استخدام <span class="highlight-blue">findAccessibilityNodeInfosByViewId</span> للـ TextInput
<br>
<span class="tag tag-success">Tfadal</span> البحث بـ 7 لغات مختلفة (AR/EN/TR) عن حقول الإدخال
</div>
</div>
</div>
<div class="step">
<div class="step-num">4</div>
<div class="step-desc">
<div class="title">قراءة السعر وإرسال النتيجة</div>
<div class="code">
// قراءة السعر من النصوص التي تحتوي على 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
}
}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 3: WORKER PROCESSES RESULTS -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">⚙️</span>
<span>المرحلة الثالثة: Worker يستقبل النتائج ويخزنها</span>
<span class="tag tag-purple">backend/bot/worker.php</span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">استقبال POST مع التحقق من HMAC-SHA256</div>
<div class="code">// التحقق من التوقيع + منع Replay Attacks (صلاحية 5 دقائق)
if (abs(time() - $ts) > 300) → رفض الطلب
$expected_sig = hash_hmac('sha256', $device_id . $ts, $SECRET_KEY);
hash_equals($expected_sig, $sig) → تحقق آمن من التوقيع</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">تخزين السعر في MySQL + Redis</div>
<div class="code">
// 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);
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 4: STANDALONE DASHBOARD -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">📊</span>
<span>المرحلة الرابعة: Standalone Worker Dashboard (واجهة تحكم)</span>
<span class="tag tag-warning">standalone_worker.php</span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">واجهة مدير متكاملة (HTML/CSS)</div>
<div class="detail">نظام ملفات JSON (tasks.json / results.json) — بدون حاجة لقاعدة بيانات</div>
<div class="detail">
<span class="tag tag-info">قائمة المهام المعلقة</span>
<span class="tag tag-success">سجل النتائج المنجزة</span>
<span class="tag tag-warning">نموذج إضافة مهمة يدوية</span>
</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">عينة من البيانات المعروضة</div>
<table class="data-table">
<tr><th>#</th><th>التطبيق</th><th>المسار</th><th>السعر</th><th>الحالة</th></tr>
<tr><td>1</td><td>YallaGo</td><td>المزة → مطار دمشق</td><td>12,500 SYP</td><td><span style="color:#34d399;">✅ نجاح</span></td></tr>
<tr><td>2</td><td>Zakinn</td><td>ساحة الأمويين → دمر</td><td>8,200 SYP</td><td><span style="color:#34d399;">✅ نجاح</span></td></tr>
<tr><td>3</td><td>Tfadal</td><td>المالكي → كفرسوسة</td><td></td><td><span style="color:#f87171;">❌ فشل</span></td></tr>
<tr><td>4</td><td>YallaGo</td><td>برامكة → المهاجرين</td><td>15,000 SYP</td><td><span style="color:#34d399;">✅ نجاح</span></td></tr>
<tr><td>5</td><td>Zakinn</td><td>الميدان → باب توما</td><td>6,750 SYP</td><td><span style="color:#34d399;">✅ نجاح</span></td></tr>
</table>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 5: MARKETING + AI -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">🧠</span>
<span>المرحلة الخامسة: نظام التسويق الذكي بالذكاء الاصطناعي (Gemini AI)</span>
<span class="tag tag-purple">SiroGeminiService.php + trigger_campaign.php</span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">المدير يضغط "إطلاق حملة استعادة ذكية فوراً"</div>
<div class="detail">من <span class="highlight-blue">siro_admin → Marketing Page</span></div>
<div class="code">
// Flutter Controller: marketing_controller.dart
Future<void> triggerAICampaign() async {
var res = await CRUD().post(link: AppLink.triggerCampaign, payload: params);
// → POST /Admin/marketing/trigger_campaign.php
}
</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">PHP يسحب آخر أسعار المنافسين ويرسلها إلى Gemini AI</div>
<div class="code">
$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
);
</div>
</div>
</div>
<div class="step">
<div class="step-num">3</div>
<div class="step-desc">
<div class="title">Gemini AI يحلل ويكتب حملة تسويقية كاملة</div>
<div class="code">
// 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\"
}"
</div>
</div>
</div>
<div class="step">
<div class="step-num">4</div>
<div class="step-desc">
<div class="title">إرسال الإشعارات والحملات الترويجية</div>
<div class="detail">
<span class="tag tag-success">FCM Push</span> للمستخدمين النشطين (بدون حدود سبام)
<br>
<span class="tag tag-warning">WhatsApp</span> للمستخدمين المنقطعين (مع anti-spam 24 ساعة)
<br>
<span class="tag tag-info">SMS</span> كخيار احتياطي إذا فشل WhatsApp
</div>
<div class="code">
// 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++;
}
}
}
</div>
</div>
</div>
<div class="step">
<div class="step-num">5</div>
<div class="step-desc">
<div class="title">تسجيل الحملة في سجل التدقيق</div>
<div class="code">
// 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
}
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 6: PRICING ENGINE -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">💰</span>
<span>المرحلة السادسة: محرك التسعير الديناميكي يستخدم بيانات المنافسين</span>
<span class="tag tag-warning">backend/ride/pricing/get.php</span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">حساب السعر مع الـ Surge Multiplier من Redis</div>
<div class="code">
// قراءة الطلب (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
}
}
</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">تطبيق التسعير التنافسي (Competitor Undercut — أقل بـ 8%)</div>
<div class="code">
// البحث عن أسعار منافسين لنفس المنطقة الجغرافية
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; // تطبيق السعر التنافسي
}
}
</div>
</div>
</div>
<div class="step">
<div class="step-num">3</div>
<div class="step-desc">
<div class="title">تطبيق الخصم (Promo Code) + الديون السابقة + التوقيع المشفر</div>
<div class="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
]));
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 7: SOCKET SYSTEM -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">🔌</span>
<span>المرحلة السابعة: WebSocket — الاتصال المباشر مع السائقين</span>
<span class="tag tag-purple">socket_intaleq/driver_socket.php</span>
</div>
<div class="timeline-bar">
<span>🚀 المستوى الثاني (Level 2 Architecture)</span>
<span>|</span>
<span>بورت <span class="highlight">2020</span> WebSocket</span>
<span>|</span>
<span>بورت <span class="highlight">2021</span> HTTP Internal</span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">اتصال السائق بالـ Socket</div>
<div class="code">
// 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];
</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">تحديث الموقع مع Redis Pipeline Buffering (Level 2)</div>
<div class="code">
// السائق يرسل موقعه ← يتم تجميع الأحداث كل 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 = [];
});
</div>
<div class="detail" style="margin-top:0.5rem;">
<span class="tag tag-success">تحسين أداء</span> بدلاً من 3 عمليات Redis لكل تحديث → <span class="highlight">عملية واحدة كل 500ms</span> لكل السائقين
</div>
</div>
</div>
<div class="step">
<div class="step-num">3</div>
<div class="step-desc">
<div class="title">إرسال الطلبات الجديدة (Dispatch + Market)</div>
<div class="code">
// 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);
}
</div>
</div>
</div>
<div class="step">
<div class="step-num">4</div>
<div class="step-desc">
<div class="title">تحديث موقع السائق إلى الراكب (Forward to Passenger Socket)</div>
<div class="code">
// 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]]);
}
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 8: DRIVER APP -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">📍</span>
<span>المرحلة الثامنة: تطبيق السائق — الوجهة المقترحة والخلفية</span>
<span class="tag tag-info">siro_driver/</span>
</div>
<div class="grid-2">
<div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">DestinationController — إدارة الوجهة</div>
<div class="code">
// حفظ الوجهة (حد أقصى مرتين في اليوم)
Future<void> 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()
</div>
</div>
</div>
</div>
<div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">Background Service — استقبال الطلبات في الخلفية</div>
<div class="code">
// 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, "طلب رحلة جديد 🚖", ...);
});
</div>
</div>
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 9: ADMIN APP -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">📱</span>
<span>المرحلة التاسعة: Admin App — لوحة التسويق الذكي</span>
<span class="tag tag-info">siro_admin/</span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">MarketingController — التحكم بالأسواق والحملات</div>
<div class="detail">يدير كل من:
<span class="tag tag-warning">Anomalies</span>
<span class="tag tag-success">Campaigns Log</span>
<span class="tag tag-purple">Telemetry</span>
<span class="tag tag-info">Price Comparison</span>
<span class="tag tag-error">What-If Simulator</span>
</div>
<div class="code">
// دوال رئيسية:
fetchAnomalies() // شواذ الأسعار
fetchCampaignsLog() // سجل الحملات
fetchTelemetry() // استهلاك API والتكاليف
fetchPriceComparison() // مقارنة الأسعار + PCI
fetchPriceGapHeatmap() // خارطة الفجوات السعرية
fetchMarketShareAnalytics() // تطور الحصة السوقية
fetchAiPricePrediction() // توقعات AI
fetchWinbackTargets() // أهداف الاستعادة
triggerAICampaign() // إطلاق حملة AI
runWhatIfSimulation(price) // محاكي تغيير الأسعار
</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">واجهة MarketingPage متكاملة بـ 3 تبويبات</div>
<div class="detail">
<span class="tag tag-info">التبويب 1: شواذ الأسعار والمنافسين</span><br>
- بطاقة التحكم بالـ AI (Gemini)<br>
- توقعات الذكاء الاصطناعي (Siro AI Prediction)<br>
- محاكي تغيير الأسعار الذكي (What-If Simulator)<br>
- رسم بياني لتطور الحصة السوقية (آخر 12 أسبوع)<br>
- رسم بياني لمقارنة تقلبات الأسعار اللحظية<br>
- خارطة الفجوات ومؤشر التنافسية السعري (PCI)<br>
- أهداف استعادة العملاء (Win-Back)
<br><br>
<span class="tag tag-success">التبويب 2: سجل الحملات المنجزة</span><br>
- عرض الحملات المرسلة (Push / WhatsApp / SMS)
<br><br>
<span class="tag tag-warning">التبويب 3: إعدادات الأتمتة والتحكم</span><br>
- مراقب استهلاك الرموز API Telemetry<br>
- تفعيل/تعطيل الـ Autopilot<br>
- تعديل System Prompt للذكاء الاصطناعي
</div>
</div>
</div>
<div class="step">
<div class="step-num">3</div>
<div class="step-desc">
<div class="title">What-If Simulator — محاكي السيناريوهات</div>
<div class="code">
// مثلاً: المدير يقترح سعر 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/كم سيجعلنا أرخص من جميع المنافسين!"
}
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- PHASE 10: RIDER APP -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">🗣️</span>
<span>المرحلة العاشرة: تطبيق الراكب — الملاحة والـ TTS</span>
<span class="tag tag-info">siro_rider/</span>
</div>
<div class="step">
<div class="step-num">1</div>
<div class="step-desc">
<div class="title">NavigationView + NavigationController — الملاحة</div>
<div class="detail">واجهة ملاحة كاملة مع: معلومات المسار، وقت الوصول، المسافة المتبقية</div>
</div>
</div>
<div class="step">
<div class="step-num">2</div>
<div class="step-desc">
<div class="title">TTS (Text-to-Speech) Controller</div>
<div class="detail">تحويل إرشادات الملاحة إلى صوت بالعربية — إعلانات صوتية للمنعطفات</div>
<div class="code">
// siro_rider/lib/controller/functions/tts.dart
class TextToSpeechController extends GetxController {
Future<void> speakText(String text) async {
await flutterTts.setLanguage("ar-SA");
await flutterTts.setSpeechRate(0.5);
await flutterTts.speak(text);
}
}
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- DATA FLOW DIAGRAM -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">🔁</span>
<span>مخطط تدفق البيانات الكامل — دورة متكاملة</span>
</div>
<div style="text-align:center; padding:1rem; font-size:0.95rem; line-height:2;">
<span style="color:#fbbf24;">⏰ Cron Job (15 دقيقة)</span><br>
<span style="color:#334155;">↓ يولد</span><br>
<span style="color:#60a5fa;">📋 60 مهمة تسعير → Redis Queue</span><br>
<span style="color:#334155;">↓ يسحب</span><br>
<span style="color:#34d399;">🤖 Android Bot (Accessibility Service)</span><br>
<span style="color:#334155;">↓ يفتح التطبيق وينقر آلياً ويقرأ</span><br>
<span style="color:#a78bfa;">📱 YallaGo • Zakinn • Tfadal</span><br>
<span style="color:#334155;">↓ يرسل النتائج</span><br>
<span style="color:#60a5fa;">📊 Worker → MySQL (competitor_prices) + Redis</span><br>
<span style="color:#334155;">↓ يستخدم في</span><br>
<span style="color:#34d399;">💰 محرك التسعير الديناميكي (Undercut 8%)</span><br>
<span style="color:#334155;">↓ ويستخدم في</span><br>
<span style="color:#f59e0b;">🧠 Gemini AI Campaign Generator</span><br>
<span style="color:#334155;">↓ يرسل</span><br>
<span style="color:#10b981;">📣 FCM Push + WhatsApp + SMS → الركاب</span><br>
<span style="color:#334155;">↓ وأيضاً</span><br>
<span style="color:#f87171;">📊 Admin Dashboard يعرض التحليلات</span><br>
</div>
</div>
<!-- ============================== -->
<!-- FILE STRUCTURE -->
<!-- ============================== -->
<div class="flow-section">
<div class="flow-title">
<span class="icon">📁</span>
<span>هيكلية الملفات المضافة والمعدلة اليوم</span>
</div>
<div class="grid-2">
<div>
<div style="font-weight:700; margin-bottom:0.5rem; color:#3b82f6;">📱 siro_driver/</div>
<div style="font-size:0.8rem; color:#94a3b8; line-height:1.8;">
├── lib/constant/links.dart<br>
├── lib/controller/functions/background_service.dart<br>
├── lib/controller/functions/location_controller.dart<br>
├── lib/controller/home/captin/<br>
│ ├── destination_controller.dart<br>
│ ├── home_captain_controller.dart<br>
│ └── order_request_controller.dart<br>
├── lib/controller/local/ar_eg.dart<br>
├── lib/controller/local/ar_jo.dart<br>
├── lib/controller/local/ar_sy.dart<br>
├── lib/controller/local/en.dart<br>
├── lib/views/home/Captin/home_captain/<br>
│ ├── home_captin.dart<br>
│ └── widget/destination_bottom_sheet.dart<br>
└── lib/views/home/Captin/mapDriverWidgets/passenger_info_window.dart
</div>
</div>
<div>
<div style="font-weight:700; margin-bottom:0.5rem; color:#10b981;">⚙️ backend/</div>
<div style="font-size:0.8rem; color:#94a3b8; line-height:1.8;">
├── bot/<br>
│ ├── generate_price_tasks.php (Cron Job)<br>
│ ├── worker.php (Redis Worker Endpoint)<br>
│ └── standalone_worker.php (Dashboard)<br>
├── core/Services/SiroGeminiService.php<br>
├── Admin/marketing/<br>
│ ├── trigger_campaign.php<br>
│ ├── get_price_comparison.php<br>
│ ├── get_market_anomalies.php<br>
│ ├── get_telemetry.php<br>
│ └── get_campaigns_log.php<br>
├── ride/pricing/get.php<br>
├── ride/location/save_driver_destination.php<br>
└── ride/rides/add_ride.php, acceptRide.php, cancel*.php
</div>
<div style="font-weight:700; margin-top:1rem; margin-bottom:0.5rem; color:#a78bfa;">🤖 android_bot/</div>
<div style="font-size:0.8rem; color:#94a3b8; line-height:1.8;">
├── service/ScraperAccessibilityService.kt<br>
├── service/AppLauncher.kt<br>
├── network/WorkerClient.kt<br>
└── MainActivity.kt
</div>
</div>
</div>
</div>
<!-- ============================== -->
<!-- FINAL REMARKS -->
<!-- ============================== -->
<div class="flow-section" style="border-color: rgba(16,185,129,0.3);">
<div class="flow-title" style="border-bottom-color: rgba(16,185,129,0.15);">
<span class="icon"></span>
<span>الخلاصة — ماذا أنجزنا اليوم؟</span>
</div>
<div style="padding:0.5rem 0; line-height:2;">
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Android Bot</span> — نقر آلي ذكي (Accessibility Service) مع آلة حالة متكاملة لـ 3 تطبيقات منافسة<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Cron Job</span> — توليد 60 مهمة تسعير كل 15 دقيقة لـ 10 مناطق في دمشق<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Worker Endpoint</span> — استقبال نتائج البوت مع HMAC Authentication + MySQL/Redis<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Gemini AI</span> — خدمة تحليل أسعار وصياغة حملات تسويقية بالعربية (لهجات محلية)<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Marketing Campaign</span> — إطلاق حملات عبر FCM + WhatsApp + SMS مع Anti-Spam<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Pricing Engine</span> — تسعير ديناميكي مع Undercut 8% عن المنافسين + Surge Pricing<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">WebSocket Level 2</span> — Redis Pipeline Buffering كل 500ms + Forward للموقع<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Destination System</span> — وجهة السائق مع حد يومي + خلفية مع Overlay للطلبات<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Admin Dashboard</span> — لوحة تسويق ذكية مع PCI, Heatmap, What-If Simulator, Telemetry<br>
<span class="tag tag-success">مكتمل</span> <span class="highlight-green">Standalone Dashboard</span> — واجهة تحكم كاملة للبوت بدون حاجة Redis/MySQL
</div>
</div>
</div>
</body>
</html>