import 'dart:convert'; import 'dart:math'; import 'package:get/get.dart'; import 'package:sefer_driver/constant/box_name.dart'; import 'package:sefer_driver/constant/links.dart'; import 'package:sefer_driver/controller/functions/crud.dart'; import '../../../constant/table_names.dart'; import '../../../main.dart'; import '../../../print.dart'; class DriverBehaviorController extends GetxController { Future>> getAllData() async { return await sql.getAllData(TableName.behavior); } var isLoading = false.obs; var overallScore = 100.0.obs; var lastTrips = [].obs; Future fetchDriverBehavior() async { isLoading.value = true; try { final response = await CRUD().get( link: AppLink.get_driver_behavior, payload: {"driver_id": box.read(BoxName.driverID).toString()}, ); if (response != 'failure') { final json = jsonDecode(response); overallScore.value = double.parse(json['message']['overall_behavior_score'].toString()); lastTrips.value = json['message']['last_10_trips']; } else { // Get.snackbar("Error", json['message'] ?? "Unknown error"); } } catch (e) { // Get.snackbar("Error", "Exception: $e"); Log.print('e: ${e}'); } finally { isLoading.value = false; } } Future> analyzeData() async { final data = await getAllData(); if (data.isEmpty) return {}; double maxSpeed = 0; double totalSpeed = 0; int hardBrakes = 0; double totalDistance = 0; // متغيرات للمقارنة مع النقطة السابقة double? prevLat, prevLng; DateTime? prevTime; // ترتيب البيانات حسب الوقت لضمان دقة الحساب (اختياري لكن مفضل) // data.sort((a, b) => a['created_at'].compareTo(b['created_at'])); for (var item in data) { // 1. قراءة البيانات بالأسماء الصحيحة من الجدول double lat = item['latitude'] ?? item['lat'] ?? 0.0; double lng = item['longitude'] ?? item['lng'] ?? 0.0; double acc = item['acceleration'] ?? 0.0; // قراءة الوقت لحساب السرعة DateTime currentTime = DateTime.tryParse(item['created_at'].toString()) ?? DateTime.now(); double currentSpeed = 0; // 2. حساب السرعة والمسافة إذا وجدت نقطة سابقة if (prevLat != null && prevLng != null && prevTime != null) { double distKm = _calculateDistance(prevLat, prevLng, lat, lng); int timeDiffSeconds = currentTime.difference(prevTime).inSeconds; if (timeDiffSeconds > 0) { // السرعة (كم/س) = (المسافة بالكيلومتر * 3600) / الزمن بالثواني currentSpeed = (distKm * 3600) / timeDiffSeconds; } totalDistance += distKm; } // تحديث القيم الإحصائية if (currentSpeed > maxSpeed) maxSpeed = currentSpeed; totalSpeed += currentSpeed; // حساب الفرملة القوية (يعتمد على التسارع المحفوظ مسبقاً) if (acc.abs() > 3.0) hardBrakes++; // حفظ النقطة الحالية لتكون هي "السابقة" في الدورة التالية prevLat = lat; prevLng = lng; prevTime = currentTime; } // تجنب القسمة على صفر double avgSpeed = (data.length > 1) ? totalSpeed / (data.length - 1) : 0; // حساب تقييم السلوك double behaviorScore = 100 - (hardBrakes * 5) - ((maxSpeed > 100) ? 10 : 0); behaviorScore = behaviorScore.clamp(0.0, 100.0); return { 'max_speed': maxSpeed, 'avg_speed': avgSpeed, 'hard_brakes': hardBrakes, 'total_distance': totalDistance, 'behavior_score': behaviorScore, }; } Future sendSummaryToServer(String driverId, String tripId) async { final summary = await analyzeData(); if (summary.isEmpty) return; final Map body = { 'driver_id': driverId, 'trip_id': tripId, ...summary, // فيه doubles }; // اجبر كل القيم على String final payload = body.map((k, v) => MapEntry(k, v?.toString() ?? '')); await CRUD().post(link: AppLink.saveBehavior, payload: payload); await clearData(); } Future clearData() async { await sql.deleteAllData(TableName.behavior); } double _calculateDistance( double lat1, double lon1, double lat2, double lon2) { const p = 0.017453292519943295; final a = 0.5 - cos((lat2 - lat1) * p) / 2 + cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2; return 12742 * asin(sqrt(a)); // distance in km } }