Update: 2026-07-04 04:05:08

This commit is contained in:
Hamza-Ayed
2026-07-04 04:05:08 +03:00
parent e4ba962ab6
commit c7bd644b88
14 changed files with 807 additions and 26 deletions
+3
View File
@@ -145,6 +145,9 @@ class AppLink {
static String get getSurgeHeatmap =>
"$server/ride/heatmap/get_surge_heatmap.php";
static String get getPredictiveDemand =>
"$server/api/demand/getPredictiveDemandZones.php";
///mapOSM = 'https://routesy.intaleq.xyz'
static String get mapOSM {
switch (currentCountry) {
@@ -61,8 +61,13 @@ class HomeCaptainController extends GetxController {
double widthMapTypeAndTraffic = 50;
// === متغيرات الهيت ماب الجديدة ===
bool isHeatmapVisible = false;
Set<Polygon> heatmapPolygons =
{}; // سنستخدم Polygon لرسم المربعات على جوجل مابس
Set<Polygon> heatmapPolygons = {};
// === متغيرات التنبؤ الذكي بالطلب ===
bool isPredictiveVisible = false;
Set<Polygon> predictivePolygons = {};
List<Map<String, dynamic>> predictiveZones = [];
Timer? _predictiveTimer;
// Inject the LocationController class
// final locationController = Get.put(LocationController());
@@ -198,6 +203,97 @@ class HomeCaptainController extends GetxController {
});
}
// ════════════════════════════════════════════════════════
// 🔮 التنبؤ الذكي بالطلب
// ════════════════════════════════════════════════════════
/// تبديل عرض/إخفاء طبقة التنبؤ الذكي
void togglePredictiveDemand() {
isPredictiveVisible = !isPredictiveVisible;
if (isPredictiveVisible) {
_startPredictiveCycle();
} else {
_predictiveTimer?.cancel();
predictivePolygons.clear();
predictiveZones.clear();
}
update();
}
void _startPredictiveCycle() {
_predictiveTimer?.cancel();
fetchAndDrawPredictiveDemand();
// تحديث كل 30 دقيقة (يتوافق مع دورة الـ cron)
_predictiveTimer = Timer.periodic(const Duration(minutes: 30), (_) {
if (isPredictiveVisible) fetchAndDrawPredictiveDemand();
});
}
Future<void> fetchAndDrawPredictiveDemand() async {
print("🔮 [Predictive] Fetching demand zones...");
try {
final myLat = locationController.myLocation.latitude;
final myLng = locationController.myLocation.longitude;
final response = await http.get(
Uri.parse(
"${AppLink.getPredictiveDemand}?lat=$myLat&lng=$myLng&radius=10"
"&t=${DateTime.now().millisecondsSinceEpoch}",
),
);
if (response.statusCode == 200) {
final body = json.decode(response.body);
if (body['success'] == true) {
final zones = List<Map<String, dynamic>>.from(body['zones'] ?? []);
predictiveZones = zones;
_drawPredictivePolygons(zones);
print("✅ [Predictive] ${zones.length} zones loaded.");
}
}
} catch (e) {
print("❌ [Predictive] Error: $e");
}
}
void _drawPredictivePolygons(List<Map<String, dynamic>> zones) {
const double offset = 0.008; // أكبر قليلاً من الهيتماب (0.005) ليكون مميزاً
final Set<Polygon> temp = {};
for (final zone in zones) {
final double lat = (zone['lat'] as num).toDouble();
final double lng = (zone['lng'] as num).toDouble();
final int score = (zone['demand_score'] as num).toInt();
// ألوان التنبؤ: أزرق/سماوي (مختلف تماماً عن الهيتماب)
final Color fill = score >= 8
? const Color(0xFF0EA5E9).withOpacity(0.35) // أزرق قوي
: score >= 4
? const Color(0xFF38BDF8).withOpacity(0.30) // أزرق فاتح
: const Color(0xFF7DD3FC).withOpacity(0.25); // سماوي خفيف
final Color stroke = score >= 8
? const Color(0xFF0369A1).withOpacity(0.9)
: const Color(0xFF0EA5E9).withOpacity(0.8);
temp.add(Polygon(
polygonId: PolygonId("pred_${lat}_$lng"),
points: [
LatLng(lat - offset, lng - offset),
LatLng(lat + offset, lng - offset),
LatLng(lat + offset, lng + offset),
LatLng(lat - offset, lng + offset),
],
fillColor: fill,
strokeColor: stroke,
strokeWidth: 2,
));
}
predictivePolygons = temp;
update();
}
void goToWalletFromConnect() {
Get.back();
Get.back();
@@ -803,6 +803,7 @@ final Map<String, String> ar_eg = {
"Heading your way now. Please be ready.": "قاعد يجيك دلوقتي. من فضلك استعد.",
"Health Insurance": "التأمين الصحي",
"Heatmap": "خريطة الحرارة",
"Predictive Demand": "🔮 توقعات الطلب",
"Height:": "الطول:",
"Hello": "أهلاً",
"Hello this is Captain": "أهلاً، ده الكابتن",
@@ -803,6 +803,7 @@ final Map<String, String> ar_jo = {
"Heading your way now. Please be ready.": "في طريقه إليك الآن. يرجى الاستعداد.",
"Health Insurance": "التأمين الصحي",
"Heatmap": "خريطة الحرارة",
"Predictive Demand": "🔮 توقعات الطلب",
"Height:": "الطول:",
"Hello": "مرحباً",
"Hello this is Captain": "مرحباً، هذا الكابتن",
@@ -803,6 +803,7 @@ final Map<String, String> ar_sy = {
"Heading your way now. Please be ready.": "عم ييجي لعندك هلق. تفضّل جهّز حالك.",
"Health Insurance": "التأمين الصحي",
"Heatmap": "خريطة حرارية",
"Predictive Demand": "🔮 توقعات الطلب",
"Height:": "الطول:",
"Hello": "أهلاً",
"Hello this is Captain": "أهلاً، أنا الكابتن",
+1
View File
@@ -803,6 +803,7 @@ final Map<String, String> en = {
"Heading your way now. Please be ready.": "Heading your way now. Please be ready.",
"Health Insurance": "Health Insurance",
"Heatmap": "Heatmap",
"Predictive Demand": "Predictive Demand",
"Height:": "Height:",
"Hello": "Hello",
"Hello this is Captain": "Hello this is Captain",
@@ -326,6 +326,42 @@ class _AppBarControls extends StatelessWidget {
onTap: c.toggleHeatmap,
),
),
// Predictive Demand
GetBuilder<HomeCaptainController>(
builder: (c) => Stack(
clipBehavior: Clip.none,
children: [
_IconBtn(
icon: Icons.auto_awesome_rounded,
color: c.isPredictiveVisible
? const Color(0xFF0EA5E9)
: Colors.grey.shade600,
tooltip: 'Predictive Demand'.tr,
onTap: c.togglePredictiveDemand,
),
if (c.isPredictiveVisible && c.predictiveZones.isNotEmpty)
Positioned(
top: -4,
right: -4,
child: Container(
padding: const EdgeInsets.all(3),
decoration: const BoxDecoration(
color: Color(0xFF0EA5E9),
shape: BoxShape.circle,
),
child: Text(
'${c.predictiveZones.length}',
style: const TextStyle(
color: Colors.white,
fontSize: 8,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
// Center on me
_IconBtn(
icon: Icons.my_location_rounded,
@@ -398,7 +434,10 @@ class _MapView extends StatelessWidget {
mapType: s.isMapDarkMode
? IntaleqMapType.normal
: IntaleqMapType.light,
polygons: ctrl.heatmapPolygons,
polygons: {
...ctrl.heatmapPolygons,
...ctrl.predictivePolygons,
},
markers: {
Marker(
markerId: MarkerId('MyLocation'.tr),
+1 -1
View File
@@ -2,7 +2,7 @@ name: siro_driver
description: "A new Flutter project."
publish_to: "none" # Remove this line if you wish to publish to pub.dev
version: 1.0.0+2
version: 1.0.0+3
environment:
sdk: ">=3.0.5 <4.0.0"