Class: Dscf::Marketplace::RouteOptimizationService
- Inherits:
-
Object
- Object
- Dscf::Marketplace::RouteOptimizationService
- Defined in:
- app/services/dscf/marketplace/route_optimization_service.rb
Instance Attribute Summary collapse
-
#delivery_order ⇒ Object
readonly
Returns the value of attribute delivery_order.
Instance Method Summary collapse
-
#initialize(delivery_order) ⇒ RouteOptimizationService
constructor
A new instance of RouteOptimizationService.
- #optimize! ⇒ Object
Constructor Details
#initialize(delivery_order) ⇒ RouteOptimizationService
Returns a new instance of RouteOptimizationService.
6 7 8 |
# File 'app/services/dscf/marketplace/route_optimization_service.rb', line 6 def initialize(delivery_order) @delivery_order = delivery_order end |
Instance Attribute Details
#delivery_order ⇒ Object (readonly)
Returns the value of attribute delivery_order.
4 5 6 |
# File 'app/services/dscf/marketplace/route_optimization_service.rb', line 4 def delivery_order @delivery_order end |
Instance Method Details
#optimize! ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'app/services/dscf/marketplace/route_optimization_service.rb', line 10 def optimize! return unless delivery_order.pickup_address && delivery_order.delivery_stops.any? # 1. Collect Coordinates # Format: [[pickup_lat, pickup_lng], [stop1_lat, stop1_lng], ...] pickup_coords = [delivery_order.pickup_address.latitude.to_f, delivery_order.pickup_address.longitude.to_f] # We map stops to their dropoff coordinates. # We need to keep track of the mapping between original index and stop ID to re-order later. stops = delivery_order.delivery_stops.includes(:dropoff_address).to_a stop_coords = stops.map { |stop| [stop.dropoff_address.latitude.to_f, stop.dropoff_address.longitude.to_f] } all_locations = [pickup_coords] + stop_coords # 2. Call Gebeta API response = GebetaService.new.tsp(all_locations) # 3. Process Response # New Response Format: # { # "best_order": [ # {"lat":..., "lon":...}, # Start (Pickup) # {"lat":..., "original_index": 2}, # Stop A # {"lat":..., "original_index": 1} # Stop B # ], # "total_distance": 13.474, # In KM? Diagnostic showed 13.474 for small distance. Need to verify unit. # "time_taken": 1033.263, # "Direction": [[lat,lon], ...] # } # 'best_order' includes the start point at index 0 (usually without original_index or it's 0/1 based?) # Based on diagnostic: "original_index": 2 for the 3rd point (index 2). # So original_index is 0-based index from the input array. best_order = response["best_order"] # Filter out the pickup location (which should be the first one, or original_index == 0) # We only want to re-sequence the STOPS. # Stops in 'stops' array correspond to input indices 1..N. ordered_stops_data = best_order.select { |node| node["original_index"].to_i > 0 } ActiveRecord::Base.transaction do ordered_stops_data.each_with_index do |node, seq_num| original_idx = node["original_index"] # stops array is 0-indexed, corresponding to input indices 1, 2, 3... # If original_idx is 1, it means stops[0]. If 2, stops[1]. stop = stops[original_idx - 1] if stop stop.update!(sequence_number: seq_num + 1) end end # Update DeliveryOrder metrics # Check units: # time_taken: 1033.263 (likely seconds ~ 17 mins for decent distance). # total_distance: 13.474. If this is KM, it's reasonable. (Distance between 9.02,38.80 and 9.028,38.75 is ~ small). # If meters, 13 meters is too small. 1000 seconds for 13 meters is wrong. # So total_distance is likely KM. distance_km = response["total_distance"].to_f delivery_order.update!( estimated_delivery_time: Time.current + response["time_taken"].to_f.seconds, estimated_delivery_price: calculate_price(distance_km * 1000), # pass meters to calc optimized_route: response["Direction"] ) end end |