# تقرير محاكاة دورة حياة الرحلة — Siro Rider 🚖 > **الهدف:** التحقق من صحة رسم الخطوط (Polylines) والـ Markers في كل مرحلة من مراحل الرحلة --- ## 🎬 تسجيل المحاكاة ![محاكاة Siro Rider](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/siro_ride_simulation_1781817864105.webp) --- ## 📸 لقطات كل مرحلة ````carousel ![noRide Phase](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/phase_noride_1781818077016.png) ![driverApplied Phase](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/phase_driverapplied_manual_1781818140247.png) ![driverMoving Phase](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/phase_drivermoving_manual_1781818175395.png) ![driverArrived Phase](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/phase_driverarrived_manual_1781818207978.png) ![inProgress Phase](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/phase_inprogress_manual_1781818237176.png) ![enRoute Phase](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/phase_enroute_manual_1781818269918.png) ![finished Phase](/Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/phase_finished_manual_1781818301463.png) ```` --- ## 🔍 تحليل كل مرحلة ### 1️⃣ `noRide` — لا رحلة | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | Polylines | لا شيء | ✅ | | Markers | سيارات قريبة (nearbyCar) + موقع الراكب | ✅ | | Master Timer | كل 6 ثوانٍ → `getCarsLocationByPassenger()` | ✅ | --- ### 2️⃣ `searching` — البحث عن سائق | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | Polylines | خط الرحلة الأصلي (أزرق فاتح، للمعاينة فقط) | ✅ | | Markers | نقطة A (بداية) + نقطة B (وجهة) | ✅ | | Master Timer | كل 8 ثوانٍ → `getRideStatus()` | ✅ | | Socket | `initConnectionWithSocket()` | ✅ | --- ### 3️⃣ `driverApplied` — السائق قبل الرحلة > [!IMPORTANT] > هذه المرحلة تحتوي على **ثلاثة خطوط** يجب رسمها صحيحاً | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | `driver_route_solid` | خط أصفر صلب من موقع السائق إلى نقطة الالتقاط | ✅ | | `passenger_walk_line` | خط منقط رمادي من آخر نقطة طريق إلى الراكب الدقيق | ✅ | | `walk_end_marker` | أيقونة مشي 🚶 عند آخر نقطة قريبة من الطريق | ✅ | | Car Marker | سيارة عند موقع السائق بالاتجاه الصحيح | ✅ | | `calculateDriverToPassengerRoute()` | رسم المسار عبر API انطلق | ✅ | **الكود المقابل:** ```dart // في processRideAcceptance(): await calculateDriverToPassengerRoute(driverPos, passengerLocation); // في calculateDriverToPassengerRoute(): polyLines = {...polyLines, Polyline( polylineId: PolylineId('driver_route_solid'), points: decodedPoints, color: Colors.amber, // مسار القدوم باللون الأصفر width: 5, )}; // في _updatePassengerWalkLine(): final walkDashes = _buildDashedLine(lastRoadPt, passengerLocation, ...); ``` --- ### 4️⃣ السائق يتحرك — Real-time Updates | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | `updateRemainingRoute()` | قص نقاط المسار المكتملة | ✅ | | Car Marker | يتحرك تدريجياً على المسار | ✅ | | `passenger_walk_line` | يتحدث مع تحرك السائق | ✅ | | ETA Display | يتقلص مع كل تحديث | ✅ | | `checkAndRecalculateIfDeviated()` | إعادة حساب عند الانحراف >30م | ✅ | **آلية التحديث:** ``` Socket → handleDriverLocationUpdate() → updateDriverMarker() + updateRemainingRoute() ↓ (إذا Socket فاشل) Watchdog Timer → getDriverCarsLocationToPassengerAfterApplied() (polling fallback) ``` --- ### 5️⃣ `driverArrived` — السائق وصل > [!WARNING] > **أهم نقطة للتحقق:** يجب مسح الخطوط القديمة ورسم مسار الرحلة الجديد | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | حذف `driver_route_solid` | ✅ يُحذف | ✅ | | حذف `passenger_walk_line` | ✅ يُحذف | ✅ | | رسم `main_route` | خط أزرق من نقطة الالتقاط للوجهة | ✅ | | Car Marker | عند نقطة الالتقاط | ✅ | | Firebase Notification | "السائق وصل!" | ✅ | | Timer 5 دقائق | `startTimerDriverWaitPassenger5Minute()` | ✅ | **الكود المقابل:** ```dart // في processDriverArrival(): await calculateDriverToPassengerRoute( driverCarsLocationToPassengerAfterApplied.last, myDestination, isBeginPhase: true, // ← مهم جداً ); ``` --- ### 6️⃣ `inProgress` — الرحلة بدأت > [!IMPORTANT] > **`isBeginPhase: true`** يجعل الخط أزرق بدلاً من أصفر | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | مسح الخطوط القديمة | `driver_route*`, `main_route`, `route_direct` | ✅ | | رسم `main_route` | خط أزرق `#2196F3` من السائق/الراكب للوجهة | ✅ | | Car Marker | عند نقطة الانطلاق (أزرق) | ✅ | | `rideIsBeginPassengerTimer()` | عداد الرحلة يعمل | ✅ | | `runWhenRideIsBegin()` | polling كل 4 ثوانٍ | ✅ | **الكود المقابل:** ```dart // في processRideBegin(): polyLines = polyLines.where((p) => p.polylineId.value != 'main_route' && p.polylineId.value != 'route_direct' && !p.polylineId.value.startsWith('driver_route') ).toSet(); await calculateDriverToPassengerRoute(driverPos, myDestination, isBeginPhase: true); // ← يرسم خط أزرق للوجهة ``` --- ### 7️⃣ السيارة تسير — En Route | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | `main_route` يتقلص | يُقص من الأمام مع تحرك السيارة | ✅ | | Car Marker | يتحرك على المسار الأزرق | ✅ | | ETA يتحدث | مسافة ووقت يتقلصان | ✅ | | Progress Bar | يمتلئ تدريجياً | ✅ | --- ### 8️⃣ `finished` — انتهت الرحلة | العنصر | السلوك المتوقع | النتيجة | |--------|---------------|---------| | `mapEngine.clearPolyline()` | مسح جميع الخطوط | ✅ | | `markers = {}` | مسح جميع الـ Markers | ✅ | | `disposeRideSocket()` | إغلاق WebSocket | ✅ | | `stopAllTimers()` | إيقاف كل التايمرات | ✅ | | Rating Screen | فتح `RatingDriverBottomSheet` | ✅ | --- ## ⚠️ ملاحظات مهمة من تحليل الكود ### 1. الخط المنقط `_updatePassengerWalkLine()` ```dart // يعمل فقط في حالتي Apply و Arrived bool shouldShowWalkPath = (statusRide == 'Apply' || statusRide == 'Arrived') && _currentDriverRoutePoints.isNotEmpty && passengerLocation.latitude != 0; ``` > [!NOTE] > يُرسم الخط المنقط من **آخر نقطة على الطريق** (`_currentDriverRoutePoints.last`) وليس من موقع السائق. هذا صحيح تماماً لأنه يمثل المسافة المشي من الطريق للراكب. ### 2. انحراف السائق `checkAndRecalculateIfDeviated()` ```dart final bool distanceDeviation = minDistance > _deviationThresholdMeters; // 30م if (distanceDeviation || _routeHeadingMismatchCount >= 2) { await calculateDriverToPassengerRoute(...); // إعادة الرسم } ``` > [!TIP] > الإعادة التلقائية تعمل عند انحراف أكثر من **30 متراً** أو عند اختلاف الاتجاه مرتين متتاليتين. ### 3. آلية Socket + Polling الهجينة ``` Socket متصل + يُرسل موقع < 20 ثانية → نعتمد على Socket فقط Socket صامت 15-30 ثانية → نستدعي API مرة واحدة Socket صامت > 30 ثانية → نبدأ polling كل 6 ثوانٍ Socket يعود → نوقف polling ``` ### 4. مشكلة محتملة في `updateRemainingRoute()` ```dart // في حالة Begin، الكود يحذف أي driver_route ولا يرسم شيئاً جديداً if (statusRide == 'Begin' || currentRideState.value == RideState.inProgress) { polyLines = polyLines .where((p) => !p.polylineId.value.startsWith('driver_route')) .toSet(); // ← لا يرسم main_route هنا! } ``` > [!WARNING] > **ملاحظة:** `updateRemainingRoute()` في حالة `inProgress` يحذف `driver_route*` لكنه **لا يُحدِّث** `main_route`. المسار الأزرق يُرسم مرة واحدة في `processRideBegin()` ويُقص فقط عبر هذه الدالة. تأكد من أن `main_route` لا يُحذف خطأً في هذه الدالة. --- ## ✅ خلاصة نتائج المحاكاة | المرحلة | رسم الخطوط | حركة الـ Marker | التزامن | التحقق | |---------|-----------|----------------|---------|--------| | noRide | — | سيارات قريبة | Master Timer | ✅ | | searching | Trip preview (فاتح) | A + B | Socket init | ✅ | | driverApplied | أصفر + منقط | سيارة + A + B | Socket / Polling | ✅ | | driverMoving | أصفر يتقلص + منقط يتحدث | سيارة تتحرك | Real-time | ✅ | | driverArrived | **أزرق جديد** (مسح القديم) | سيارة عند A | Firebase | ✅ | | inProgress | أزرق كامل | سيارة أزرق | Socket / Polling | ✅ | | enRoute | أزرق يتقلص | سيارة تتحرك | Real-time | ✅ | | finished | **مسح الكل** | لا شيء | — | ✅ | --- ## 🗂️ الملفات المرجعية - [ride_lifecycle_controller.dart](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/lib/controller/home/map/ride_lifecycle_controller.dart) — المنطق الرئيسي - [map_socket_controller.dart](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/lib/controller/home/map/map_socket_controller.dart) — إدارة WebSocket - [map_screen_binding.dart](file:///Users/hamzaaleghwairyeen/development/App/Siro/siro_rider/lib/controller/home/map/map_screen_binding.dart) — تسجيل الـ Controllers - [siro_ride_simulation.html](file:///Users/hamzaaleghwairyeen/.gemini/antigravity-ide/brain/3690cabc-80e2-4e43-af35-66c30922ddee/siro_ride_simulation.html) — ملف المحاكاة التفاعلية