// lib/features/routes/domain/entities/route_entities.dart // Capa de dominio — cero dependencias externas. class RoutePosition { final int positionId; final double lat; final double lng; final double speed; final DateTime timestamp; const RoutePosition({ required this.positionId, required this.lat, required this.lng, required this.speed, required this.timestamp, }); factory RoutePosition.fromJson(Map json) => RoutePosition( positionId: json['positionId'] as int, lat: (json['lat'] as num).toDouble(), lng: (json['lng'] as num).toDouble(), speed: (json['speed'] as num).toDouble(), timestamp: DateTime.parse(json['timestamp'] as String), ); } class TruckRoute { final String routeId; final String name; final int truckId; final String status; final List positions; const TruckRoute({ required this.routeId, required this.name, required this.truckId, required this.status, required this.positions, }); factory TruckRoute.fromJson(Map json) => TruckRoute( routeId: json['routeId'] as String, name: json['name'] as String, truckId: json['truckId'] as int, status: json['status'] as String, positions: (json['positions'] as List) .map((p) => RoutePosition.fromJson(p)) .toList(), ); /// Posición actual del camión (última del array, excluyendo el regreso) RoutePosition get currentPosition => positions[positions.length ~/ 2]; /// ETA estimado en minutos desde la posición actual hasta el final int etaFromPosition(int positionIndex) { if (positionIndex >= positions.length - 1) return 0; final current = positions[positionIndex]; final last = positions[positions.length - 2]; // penúltima = fin de ruta return last.timestamp.difference(current.timestamp).inMinutes.abs(); } } /// Resultado de asignación de ruta por Haversine class RouteAssignment { final TruckRoute route; final double distanceKm; const RouteAssignment({required this.route, required this.distanceKm}); }