# 🚗 دورة حياة الرحلة - تطبيق السائق (Driver Ride Lifecycle)
هذا الملف هو مرجع هندسي شامل ودقيق (Source of Truth) يوضح كافة تفاصيل دورة حياة الرحلة (Ride Lifecycle) في تطبيق السائق (Siro Driver). تمت كتابته وتوثيقه ليكون دليلاً استرشادياً كاملاً لأي مهندس برمجي أو نموذج ذكاء اصطناعي (AI Agent) يرغب في فهم أو تعديل منطق الرحلات، تتبع المواقع، أو معالجة الحالات الفعالة.
--- ## 1. بنية مزود الموقع المركزي (LocationController)
يعد الكنترولر [LocationController](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_driver/lib/controller/functions/location_controller.dart) هو المصدر الوحيد والمركزى (Single Source of Truth) لكافة تحديثات نظام التموضع العالمي (GPS). يُمنع منعاً باتاً إنشاء اشتراكات أو فتح قنوات استماع موازية مع Geolocator أو Location في أي مكان آخر.
### 1.1 التهيئة والتحكم في دورة الحياة (Initialization & Lifecycle)
* دالة التهيئة:
```dart Future onInit() async ```
تقوم بالخطوات التالية: 1. تسجيل الكنترولر كمراقب لدورة حياة التطبيق العامة عبر `WidgetsBinding.instance.addObserver(this)`. 2. الاستماع للمفتاح `BoxName.statusDriverLocation` للتحقق من حالة السائق (مثال: محظور `blocked`). إذا تم حظره، يتم إيقاف تتبع الموقع فوراً وتحديث السيرفر وفصل الاتصال. 3. انتظار تحميل الكنترولرات المعتمد عليها (`HomeCaptainController` و `CaptainWalletController`) عبر الدالة المساعدة `_awaitDependencies()`. 4. تهيئة الاتصال بالسوكيت عبر `initSocket()` وتهيئة إعدادات تحديد الموقع عبر `_initLocationSettings()` والبدء الفوري ببث الموقع في حال لم يكن السائق محظوراً.
* مراقبة تغيير حالة التطبيق:
```dart void didChangeAppLifecycleState(AppLifecycleState state) ```
1. في حالة **Resumed** (التطبيق في الواجهة): يتم إيقاف تشغيل خدمة الخلفية للأندرويد عبر `BackgroundServiceHelper.stopService()`، وإعادة تهيئة السوكيت إذا تم قطعه. 2. في حالة **Paused** أو **Detached** (التطبيق في الخلفية): يتم حفظ الحالة محلياً وتشغيل خدمة الخلفية `BackgroundServiceHelper.startService()` لضمان استمرارية البث.
### 1.2 الاتصال بالويب سوكيت (WebSocket & Socket.io)
* تهيئة السوكيت:
```dart void initSocket() ```
تقوم بفتح قناة اتصال مع خادم المواقع (`https://location.intaleq.xyz`) وتجهيز معلمات الاتصال (`driver_id`, `token`). تحتوي الدالة على حماية ضد الاستدعاءات المتداخلة (Debounce Flag: `_isInitializingSocket`).
* إعداد المستمعين:
```dart void _setupSocketListeners() ```
تقوم بربط الأحداث القادمة من السيرفر كالتالي: 1. `connect`: تفعيل مؤشر الاتصال وتدشين الـ Heartbeat عبر الـ Timer. 2. `new_ride_request`: عند وصول طلب رحلة جديد، يتم معالجته فوراً وتوجيهه للواجهة عبر دالة `handleIncomingOrder()`. 3. `cancel_ride`: عند إلغاء الراكب للطلب، يتم إبلاغ `MapDriverController` فوراً لإيقاف وضع الملاحة والعودة للرئيسية عبر `processRideCancelledByPassenger()`.
* إرسال الموقع الفوري للشبكة:
```dart void emitLocationToSocket(LatLng pos, double head, double spd) ```
تقوم بإرسال حزمة بيانات البث الفعلي (Latitude, Longitude, Heading, Speed, Distance, Status). في حال وجود رحلة نشطة بالحالة `Apply`, `Arrived`, أو `Begin` وبوجود معرف الراكب في الذاكرة، يتم حقن `passenger_id` و `ride_id` تلقائياً لتمكين الراكب من التتبع الحي.
### 1.3 معالجة الطلبات الواردة (Incoming Order Handler)
* معالجة الطلب المستلم:
```dart Future handleIncomingOrder(Map rideData, String source) ```
تتم معالجة الطلب بطريقتين بناءً على حالة التطبيق: 1. **خلفية التطبيق (Background)**: * على **iOS**: يتم إرسال إشعار محلي فوري (Ding Tone) ليدعو السائق لفتح التطبيق. * على **Android**: يتم إظهار واجهة التراكب السريعة (Overlay View). 2. **واجهة التطبيق (Foreground)**: * يتم التحقق من عدم وجود رحلة جارية حالياً (Guard Clause: لمنع تداخل الأحداث أثناء تنفيذ رحلة نشطة). * إخفاء أي تراكبات (Overlay Views) مفعلة. * التوجيه الفوري للسائق نحو صفحة الطلب المخصصة `/OrderRequestPage` وتمرير معطيات الرحلة المستلمة.
### 1.4 الاستماع لتدفق الموقع المباشر (GPS Stream Listener)
* الاستماع المباشر:
```dart Future _subscribeLocationStream() ```
يقوم الكنترولر بالاستماع لتغيرات الموقع من الـ GPS، وبثها محلياً للجهات المعنية كالتالي: 1. تحديث إحداثيات السائق الحالية (`myLocation`) والسرعة والاتجاه وتخزينها محلياً في الـ Storage. 2. حساب تراكم المسافة الكلية المقطوعة (`totalDistance`). 3. تحديث خريطة السائق الرئيسية إذا كانت واجهة `HomeCaptain` نشطة. 4. إرسال الإحداثيات وتمريرها مباشرة إلى دالة `handleLocationUpdateFromCentral()` المتواجدة داخل `MapDriverController` (أثناء الذهاب للراكب أو الوجهة). 5. إرسال الإحداثيات وتمريرها مباشرة إلى دالة `handleLocationUpdateFromCentral()` المتواجدة داخل `NavigationController` (أثناء التوجيه خطوة بخطوة).
--- ## 2. إدارة الرحلة النشطة (MapDriverController)
يتحكم [MapDriverController](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_driver/lib/controller/home/captin/map_driver_controller.dart) في مراحل تنفيذ الطلب بعد القبول، ورسم المسارات، وعمليات الوصول والإنهاء.
### 2.1 تحميل المعطيات واستعادة الحالة (Startup Argument Loading)
* تحميل المعطيات:
```dart Future argumentLoading() ```
تعمل هذه الدالة عند فتح الخريطة النشطة، وتقوم بالآتي: 1. قراءة بيانات الرحلة من المتغيرات المستلمة أو استعادتها من التخزين المحلي في حالات انقطاع التطبيق (`BoxName.rideArguments`). 2. تحليل ومعالجة إحداثيات الراكب والوجهة عبر دالة `latlng()`. 3. التحقق من حالة الرحلة المخزنة في الـ Box: * إذا كانت الحالة **Begin**: تعني أن الرحلة قد بدأت بالفعل، فيتم تفعيل الأعلام (`isRideStarted = true` و `isRideBegin = true`)، ورسم خط المسار باللون **الأسود/الأزرق** باتجاه **الوجهة النهائية (Passenger Destination)**، وتشغيل عدادات الرحلة وتتبع الخطوات خطوة بخطوة. * إذا كانت الحالة غير ذلك: يتم رسم خط المسار باللون **الأصفر** باتجاه **موقع الراكب (Passenger Location)**، وتشغيل محرك التوجيه لتتبع حركة السائق نحو نقطة الالتقاء.
### 2.2 تحديثات الموقع الواردة من المركز (Location Processing)
* استقبال الموقع المركزي:
```dart void handleLocationUpdateFromCentral(LatLng newLoc, double posSpeed, double posHeading) ```
يتم استدعاء هذه الدالة دورياً من قبل `LocationController` عند كل إحداثي جديد: 1. استخدام آلية التنعيم الفوري لحركة الكاميرا والسيارة على الخريطة عبر الـ `AnimationController` لعمل interpolation سلس ومنع القفزات المفاجئة. 2. استدعاء فحص الملاحة والمسارات التفصيلية عبر `_checkNavigationStep()`. 3. التحقق من اقتراب السائق من وجهته عبر `checkDestinationProximity()`.
### 2.3 الانتقال بين حالات الرحلة (State Transitions)
الحالات كالتالي:
``` OrderRequestPage: Accept -> Apply -> PassengerLocationMapPage (Yellow Polyline) -> Arrived (Distance < 100m) -> Begin (Distance < 150m) -> Trip to Destination (Blue/Black Polyline) -> Finished -> RatePassenger Page ```
* مرحلة وصول السائق للراكب (Arrive):
```dart Future markDriverAsArrived() ```
1. التحقق من المسافة الفاصلة بين السائق والراكب؛ يجب أن تكون أقل من 100 متر. 2. إرسال طلب تفعيل حالة الوصول لخادم الرحلات عبر `arrive_ride.php`. 3. بدء تشغيل مؤشر احتساب زمن انتظار السائق للراكب عبر `startTimerToShowDriverWaitPassengerDuration()`. 4. إعادة رسم المسار الجديد للوجهة مباشرة باللون الأزرق استعداداً للمرحلة القادمة.
* مرحلة بدء الرحلة الفعلية (Begin):
```dart Future startRideFromDriver() ```
1. التحقق من قرب السائق من الراكب (يجب أن يكون أقل من 150 متر للسماح بالبدء). 2. إيقاف وإعادة ضبط مؤقتات انتظار الراكب. 3. كتابة حالة الرحلة محلياً في الـ Storage وتعيينها إلى `Begin`. 4. مسح الخطوط الصفراء السابقة ورسم مسار الرحلة الفعلي باللون **الأسود/الأزرق** للوجهة. 5. تشغيل عداد الرحلة النشط (`rideIsBeginPassengerTimer`) لتحديث عداد السعر التفاعلي. 6. تشغيل بث التوجيه والملاحة عبر `startListeningStepNavigation()`. 7. بدء تسجيل الصوت لتوثيق الرحلة لأسباب أمنية عبر `AudioRecorderController`. 8. إخطار السيرفر عبر API مخصص `start_ride.php` مع وجود منطق تراجع تلقائي (Rollback) في حال فشل الطلب لإعادة الحالة إلى `Apply`.
* مرحلة إنهاء الرحلة بنجاح (Finish):
```dart Future finishRideFromDriver({bool isFromSlider = false}) Future finishRideFromDriver1({bool isFromSlider = false}) ```
1. **فحص التحقق المادي للرحلة**: حساب المسافة الإجمالية المخططة للرحلة، والتحقق من أن المسافة التي قطعتها السيارة بالفعل تتجاوز خمس (1/5) المسافة الكلية المطلوبة لمنع الإغلاقات الوهمية أو الخاطئة. 2. في حال مطابقة الشروط، يتم إيقاف تسجيل الصوت وحفظ الملف. 3. تحديث الحالات محلياً في الـ Storage إلى `Finished` وإيقاف تحديثات الموقع وإزالة معرفات الراكب المؤقتة. 4. إرسال حزمة بيانات موحدة ومتكاملة تشتمل على المسافة والوقت والتحقق المالي وخيارات المحفظة لخادم الرحلات عبر API المعاملات الموحد `finish_ride_updates.php`. 5. معالجة وتحديث محفظة السائق بالكامل وإرسال تقرير السلوك الفردي للسائق عبر `DriverBehaviorController`. 6. التوجيه النهائي لصفحة تقييم الراكب `RatePassenger` وتمرير الفاتورة المالية المحسوبة بدقة من السيرفر.
--- ## 3. التوجيه الصوتي والملاحة التفصيلية (Navigation Engine)
* الاستماع لتدفق خط الملاحة:
```dart void checkForNextStep(LatLng currentPosition) void _checkNavigationStep(LatLng pos) ```
تقوم بمطابقة الموقع الحالي للسائق مع قائمة النقاط والخطوات التوجيهية للرحلة: 1. تحديد الخطوة والمناورة التوجيهية الحالية بناءً على النقطة الأقرب. 2. إذا اقترب السائق من نقطة الانعطاف القادمة (أقل من 30-50 متر)، يتم تفعيل الخطوة التالية وتحديث النصوص الإرشادية. 3. استدعاء محرك التوجيه الصوتي `TextToSpeechController` لنطق التوجيه الجديد باللغة العربية تلقائياً لمنع تشتت السائق أثناء القيادة. 4. قص الأجزاء التي تم قطعها وتجاوزها من المسار المرسوم عبر `_updateTraveledPolylineSmart()` للحفاظ على وضوح ونظافة خط الرحلة على الخريطة.