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
@@ -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();