chore: update dependency versions, downgrade Flutter SDK, and add project documentation
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
# 🌍 التوثيق الشامل لمشروع الخرائط (Map SaaS Complete Documentation)
|
||||
|
||||
هذا المستند يعتبر المرجع الشامل لكامل البنية التحتية لمشروع الخرائط. يشرح جميع الأجزاء (الخريطة، البحث، التوجيه)، كيف تتصل ببعضها البعض، وكيف يتم تكاملها مع واجهات الفلاتر (Flutter) الخاصة بالمستخدم.
|
||||
|
||||
---
|
||||
|
||||
## 🏛️ البنية التحتية للمشروع (Architecture Overview)
|
||||
|
||||
يتكون النظام من ثلاثة محركات رئيسية تعمل بتناغم تام لتقديم تجربة تضاهي جوجل ماب:
|
||||
1. **محرك رسم الخرائط (Tile Server - Martin)**: مسؤول عن رسم الخريطة الجغرافية والشوارع.
|
||||
2. **محرك البحث الجغرافي (Geocoding Engine)**: مسؤول عن البحث، الإكمال التلقائي، وتصحيح الأخطاء.
|
||||
3. **محرك التوجيه والمسارات (Routing Engine - GraphHopper)**: مسؤول عن رسم مسار الرحلات واحتساب الوقت مع الأخذ بعين الاعتبار الازدحام المروري.
|
||||
|
||||
---
|
||||
|
||||
## 🗺️ 1. محرك رسم الخرائط (Martin Tile Server)
|
||||
|
||||
### ❓ ما هو Martin وكيف يعمل؟
|
||||
Martin هو خادم سريع جداً (مكتوب بلغة Rust) متصل مباشرة بقاعدة بيانات `PostgreSQL / PostGIS`. وظيفته هي تحويل الإحداثيات والحدود الجغرافية الموجودة في قاعدة البيانات إلى **Vector Tiles** (مربعات شعاعية بصيغة `pbf`).
|
||||
|
||||
### 🎨 كيف ترسم الخريطة (Rendering)؟
|
||||
بدلاً من إرسال صور (Images) ثقيلة للمستخدم كما في الخرائط القديمة، يرسل Martin بيانات هندسية خفيفة جداً (أرقام وإحداثيات).
|
||||
المتصفح أو تطبيق الجوال (Flutter) يقوم بأخذ هذه البيانات، ويمررها إلى كرت الشاشة (GPU) ليقوم برسم الشوارع، المباني، والحدائق بسلاسة فائقة بمعدل 60 إطاراً في الثانية (60fps) بناءً على ملف تصميم يسمى `style.json`.
|
||||
|
||||
### 📱 استخدام الخريطة في Flutter
|
||||
لرسم الخريطة داخل تطبيق Flutter الخاص بك، ستحتاج إلى مكتبة [maplibre_gl](https://pub.dev/packages/maplibre_gl):
|
||||
```dart
|
||||
MaplibreMap(
|
||||
styleString: 'http://SERVER_IP:3000/public/style.json', // رابط الـ Style الخاص بالخادم
|
||||
initialCameraPosition: CameraPosition(
|
||||
target: LatLng(31.95, 35.91), // عمّان
|
||||
zoom: 14.0,
|
||||
),
|
||||
onMapCreated: (MaplibreMapController controller) {
|
||||
// الخريطة أصبحت جاهزة للرسم عليها
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔍 2. محرك البحث الجغرافي (Geocoding Engine)
|
||||
|
||||
محرك ذكي جداً مكتوب بـ `NestJS`، يتفهم لغة الشارع العربي والأخطاء الإملائية.
|
||||
|
||||
### أ. الإكمال التلقائي (Autocomplete API)
|
||||
يستدعى مع كل حرف يكتبه المستخدم لتقديم اقتراحات فورية بأقل من 50 ملي ثانية (باستخدام فهارس `varchar_pattern_ops`).
|
||||
- **الرابط:** `GET /api/geocoding/autocomplete?q=مستش`
|
||||
- **الاستخدام في Flutter:** ربطه بـ `TypeAheadField`، لعرض أسماء المستشفيات بمجرد كتابة "مستش".
|
||||
|
||||
### ب. البحث الدقيق (Search API)
|
||||
يستدعى عند ضغط زر "بحث" أو اختيار نتيجة. يقوم بترتيب الأماكن بناءً على خوارزمية ذكية: (50% تشابه نصي، 30% أهمية/شعبية المكان، 20% المسافة).
|
||||
- **الرابط:** `GET /api/geocoding/search?q=السيتي مول`
|
||||
- **ميزات النظام الداخلية المدعومة هنا:**
|
||||
1. **التطبيع العربي:** يعالج (إ/ا/أ/ة/ه).
|
||||
2. **الاستعلامات النسبية:** يفهم (قرب المستشفى، بجانب البنك).
|
||||
3. **بوابات المجمعات (POI Gates):** للمولات الكبرى، يرجع المحرك إحداثيات (البوابة الرئيسية، بوابة الطوارئ) ضمن مصفوفة `gates`.
|
||||
4. **هل تقصد (Did you mean):** إذا كتب المستخدم مصطلحاً خاطئاً بالكامل ("السمساني") وعاد بـ 0 نتائج، يقوم المحرك ببحث `KNN` لإرجاع اقترح للتصحيح.
|
||||
|
||||
**الاستخدام في Flutter:**
|
||||
عند نجاح البحث، نأخذ الـ `latitude` و `longitude` للنتيجة، ونقوم بتحريك الكاميرا:
|
||||
```dart
|
||||
controller.animateCamera(CameraUpdate.newLatLng(LatLng(lat, lng)));
|
||||
```
|
||||
وإذا كان الرد يحتوي على `gates`، يمكن إظهار نافذة منبثقة للسائق: *"أي بوابة تقصد؟"*.
|
||||
|
||||
---
|
||||
|
||||
## 🚗 3. محرك التوجيه والمسارات (Routing & Traffic Engine)
|
||||
|
||||
يعتمد هذا النظام على محرك `GraphHopper` المدموج بتعديلات `NestJS` لحساب الازدحام المروري وتوفير المسار الأسرع.
|
||||
|
||||
### طلب مسار (Route API)
|
||||
يقوم هذا الـ API بحساب المسار من نقطة (A) إلى نقطة (B)، مع إرجاع المسار البديل وتوجيهات الملاحة، مع أخذ "عامل الازدحام" بعين الاعتبار حسب ساعة ويوم الطلب.
|
||||
- **الرابط:** `GET /api/maps/route?start=lat,lng&end=lat,lng&profile=car`
|
||||
|
||||
- **شكل الرد (Response Overview):**
|
||||
يُرجع الرد المسار الأفضل `points` مشفراً بصيغة (Polyline)، والوقت `duration`، والمسافة `distance`.
|
||||
|
||||
### 📱 رسم المسار في Flutter
|
||||
بما أننا ألغينا توليد الـ `GeoJSON` الثقيل من السيرفر لتخفيف العبء، فإن تطبيق الفلاتر سيتكفل بفك التشفير.
|
||||
1. استقبل الـ `points` (الـ Polyline) من الـ API.
|
||||
2. استخدم مكتبة مثل [flutter_polyline_points](https://pub.dev/packages/flutter_polyline_points) لفك تشفيرها إلى قائمة من إحداثيات (List of LatLng).
|
||||
3. ارسمها على خريطة MapLibre كـ `LineLayer`:
|
||||
```dart
|
||||
// فك التشفير
|
||||
List<PointLatLng> decodedPoints = polylinePoints.decodePolyline(apiResponse['points']);
|
||||
|
||||
// تحويلها لصيغة يفهمها MapLibre
|
||||
final lineString = {
|
||||
"type": "Feature",
|
||||
"geometry": {
|
||||
"type": "LineString",
|
||||
"coordinates": decodedPoints.map((p) => [p.longitude, p.latitude]).toList()
|
||||
}
|
||||
};
|
||||
|
||||
// رسم المسار بخط أزرق على الخريطة
|
||||
await controller.addSource("route-source", GeojsonSourceProperties(data: lineString));
|
||||
await controller.addLineLayer(
|
||||
"route-source",
|
||||
"route-layer",
|
||||
LineLayerProperties(
|
||||
lineColor: "#007AFF",
|
||||
lineWidth: 5.0,
|
||||
lineJoin: "round",
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 ملخص دورة حياة الطلب (User Flow in App)
|
||||
|
||||
1. **الفتح الأولي:**
|
||||
يفتح الراكب تطبيق Flutter ⬅️ تقوم أداة `MapLibre` بتحميل خريطة الـ Vector السريعة من خادم `Martin`.
|
||||
2. **البحث:**
|
||||
يكتب الراكب في صندوق البحث ⬅️ يتم مناداة `/autocomplete` لعرض الاقتراحات فوراً.
|
||||
3. **الاختيار:**
|
||||
يختار الراكب (مثلاً: سيتي مول) ⬅️ يتم مناداة `/search` ⬅️ الخادم يرجع البوابات المتاحة للمول ⬅️ الراكب يختار "البوابة الرئيسية".
|
||||
4. **طلب الرحلة:**
|
||||
التطبيق يرسل موقع الراكب وموقع البوابة إلى `/api/maps/route` ⬅️ الخادم يحسب المسار، يطبق خوارزمية الازدحام المروري، ويرجع خط سير (Polyline) ⬅️ الفلاتر يفك تشفير الخط ويرسمه على الخريطة باللون الأزرق.
|
||||
|
||||
بذلك نكون قد غطينا البنية المعمارية الكاملة بأدق تفاصيلها من السيرفر وحتى واجهة التطبيق! 🚀
|
||||
@@ -0,0 +1,114 @@
|
||||
# 🗺️ نظام البحث الجغرافي المتقدم (Google-Level Geocoding Engine)
|
||||
|
||||
هذا المستند يشرح بالتفصيل محرك البحث الجغرافي الذي تم تصميمه وبناؤه خصيصاً ليتفوق على الخرائط التقليدية من خلال فهم لغة الشارع العربي ومعالجة الأخطاء بذكاء.
|
||||
|
||||
---
|
||||
|
||||
## 🌟 الميزات الجوهرية (Core Features)
|
||||
|
||||
1. **التطبيع العربي (Arabic Normalization):**
|
||||
يتعامل مع الفروقات الإملائية كأنها غير موجودة (أ، إ، آ، ا / ة، هـ / الـ التعريف). المستخدم يكتب بالطريقة التي تريحه والمحرك يفهم القصد.
|
||||
|
||||
2. **إكمال تلقائي فائق السرعة (Ultra-fast Autocomplete):**
|
||||
محسّن ليعمل في أقل من 50 ملي ثانية باستخدام فهارس `varchar_pattern_ops` المخصصة للبحث المقطعي (Prefix Matching).
|
||||
|
||||
3. **الترتيب بالشعبية (Smart Popularity Ranking):**
|
||||
النتائج تُرتّب بناءً على مزيج ذكي يجمع بين:
|
||||
- 50% التشابه النصي.
|
||||
- 30% أهمية المكان وشعبيته (المستشفيات، المولات تتصدر النتائج).
|
||||
- 20% المسافة الفعلية عن المستخدم.
|
||||
|
||||
4. **الاستعلامات النسبية (Relative Queries):**
|
||||
فهم طبيعة الوصف في الشارع الأردني والعربي. عندما يبحث المستخدم عن `"قرب مستشفى التخصصي"`, يقوم النظام بفلترة كلمة "قرب"، ويبحث عن المستشفى، ويعيد إحداثياته الدقيقة تحت اسم "قرب مستشفى التخصصي".
|
||||
|
||||
5. **بوابات المجمعات (POI Gates Clustering):**
|
||||
لا توجيه إلى مراكز المباني بعد اليوم! الأماكن الكبرى مثل المولات تعود بقائمة من البوابات الفعلية (مثال: البوابة الرئيسية، بوابة كارفور) لتوجيه السائق بدقة متناهية.
|
||||
|
||||
6. **هل تقصد؟ (Safety Net & Spell Checker):**
|
||||
محرك تعويض الأخطاء (Fallback). إذا أدخل المستخدم مصطلحاً مستحيلاً وأسفر عن 0 نتائج، يتدخل استعلام `KNN` لاقتراح أقرب مصطلح منطقي أو تصحيحه تلقائياً.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 واجهة برمجة التطبيقات (API Endpoints)
|
||||
|
||||
جميع الروابط أدناه تتطلب إرسال مفتاح الـ API كـ Header:
|
||||
`x-api-key: [YOUR_API_KEY]`
|
||||
|
||||
### 1. البحث الجغرافي (Geocoding Search)
|
||||
يبحث عن الأماكن مع أخذ المسافة والشعبية والتشابه بعين الاعتبار.
|
||||
|
||||
**الرابط:** `GET /api/geocoding/search`
|
||||
|
||||
**المعطيات (Query Parameters):**
|
||||
- `q` *(مطلوب)*: نص البحث (مثال: "قرب السيتي مول" أو "الشميساني").
|
||||
- `lat` *(اختياري)*: خط العرض للمستخدم (لإعطاء أولوية للأماكن القريبة).
|
||||
- `lng` *(اختياري)*: خط الطول للمستخدم.
|
||||
- `radius` *(اختياري)*: دائرة البحث بالأمتار (الافتراضي 20000 متر / 20 كم).
|
||||
- `country` *(اختياري)*: فلترة البحث لدولة معينة (مثال: `jordan`, `syria`).
|
||||
|
||||
**شكل الرد (Response):**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "places_jordan_123",
|
||||
"name": "قرب السيتي مول",
|
||||
"name_ar": "قرب السيتي مول",
|
||||
"category": "mall",
|
||||
"latitude": 31.9803,
|
||||
"longitude": 35.8378,
|
||||
"distance_km": "3.50",
|
||||
"full_address": "شارع الملك عبدالله، عمان",
|
||||
"totalScore": 0.95,
|
||||
"gates": [
|
||||
{
|
||||
"name_ar": "البوابة الرئيسية",
|
||||
"name_en": "Main Gate",
|
||||
"latitude": 31.9806,
|
||||
"longitude": 35.8380,
|
||||
"is_main_gate": true
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"did_you_mean": null
|
||||
}
|
||||
```
|
||||
|
||||
### 2. الإكمال التلقائي (Autocomplete)
|
||||
مخصص لتقديم اقتراحات سريعة جداً أثناء طباعة المستخدم في مربع البحث.
|
||||
|
||||
**الرابط:** `GET /api/geocoding/autocomplete`
|
||||
|
||||
**المعطيات (Query Parameters):**
|
||||
- `q` *(مطلوب)*: نص البحث التدريجي (مثال: "مستش").
|
||||
- `country` *(اختياري)*: فلترة لدولة معينة (مثال: `jordan`).
|
||||
|
||||
**شكل الرد (Response):**
|
||||
```json
|
||||
{
|
||||
"results": [
|
||||
{
|
||||
"id": "places_jordan_456",
|
||||
"name": "مستشفى التخصصي",
|
||||
"category": "hospital",
|
||||
"region": "jordan",
|
||||
"address": "شارع جابر بن حيان"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🛠️ كيف يعمل النظام من الداخل؟ (Architecture)
|
||||
|
||||
- **Unified Search Index (المؤشر الموحد):**
|
||||
عبارة عن `Materialized View` في PostgreSQL يجمع بيانات (الأردن، سوريا، مصر، و OpenStreetMap) في جدول واحد سريع جداً.
|
||||
- **pg_trgm:**
|
||||
تقنية في قاعدة البيانات تستخدم (Trigrams) لتحطيم الكلمات إلى مقاطع من 3 أحرف ومقارنتها بدقة رهيبة للتغلب على الأخطاء الإملائية.
|
||||
- **تحديثات شعبية الأماكن (Future Sero Trips Sync):**
|
||||
المحرك مجهز لاستقبال بيانات رحلات السائقين وتحديث نقاط `popularity_score` واستنتاج بوابات المجمعات تلقائياً.
|
||||
|
||||
---
|
||||
**المستند محدث بتاريخ:** يوليو 2026
|
||||
Reference in New Issue
Block a user