-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add functionality to get route duration for commuting the rides from …
…address
- Loading branch information
Showing
7 changed files
with
147 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# frozen_string_literal: true | ||
|
||
module Rides | ||
module Commands | ||
# Computes the duration of the commute for the ride. | ||
# This is used in the ranking for the rides that the driver will | ||
# choose from. | ||
# Returns a list of objects where the origin is the driver's current address(home) | ||
class GetCommuteDuration < BaseCommand | ||
def call(rides:, driver:) | ||
commute_rides = convert_rides(rides, driver) | ||
GetRoutesData.call(rides: commute_rides) | ||
end | ||
|
||
# Converts the Driver's current home address and | ||
# the Ride#from_address into structs that can be used to | ||
# obtain the route information | ||
private def convert_rides(rides, driver) | ||
rides.each_with_object([]) do |ride, acc| | ||
acc << OpenStruct.new(origin_place_id: driver.origin_place_id, destination_place_id: ride.origin_place_id) | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# frozen_string_literal: true | ||
|
||
module Rides | ||
module Commands | ||
# Makes a request to the Google API to obtain the route information | ||
class GetRoutesData < BaseCommand | ||
DIRECTIONS_API_URL = "https://routes.googleapis.com/distanceMatrix/v2:computeRouteMatrix" | ||
DEFAULT_HEADERS = { | ||
"X-Goog-FieldMask" => "originIndex,destinationIndex,status,condition,distanceMeters,duration", | ||
"X-goog-api-key" => ENV["GOOGLE_API_KEY"], | ||
"Content-Type" => "application/json" | ||
}.freeze | ||
|
||
def call(rides:) | ||
data = get_direction_data_for_ride(rides) | ||
results(data, rides) | ||
end | ||
|
||
# Returns a list of objects, with attributes of | ||
# @param[:distance_in_meters] = Integer | ||
# @param[:duration] = String, e.g., "577s" | ||
# Duration is in seconds | ||
private def results(data, rides) | ||
# The response keeps the array positioning on the return. Since we're getting a matrix | ||
# of routes back, we only want the ones where we explicitly have a 'Ride'. This means that | ||
# we want the computations where the indicies match. | ||
data = data.select { _1[:originIndex] == _1[:destinationIndex] } | ||
data = transform_keys!(data) | ||
|
||
data.map.with_index { OpenStruct.new(ride: rides[_2], **_1) } | ||
end | ||
|
||
private def connection | ||
@connection ||= Client::Request.connection( | ||
url: DIRECTIONS_API_URL, | ||
headers: DEFAULT_HEADERS | ||
) | ||
end | ||
|
||
private def get_direction_data_for_ride(rides) | ||
body = build_request_body(rides) | ||
|
||
response = connection.post( | ||
DIRECTIONS_API_URL, | ||
body.merge(routingPreference: "TRAFFIC_AWARE", travelMode: "DRIVE") | ||
) | ||
|
||
JSON.parse(response.body, symbolize_names: true) | ||
end | ||
|
||
private def build_request_body(rides) | ||
rides.each_with_object({}) do |ride, acc| | ||
acc[:origins] ||= [] | ||
acc[:destinations] ||= [] | ||
|
||
acc[:origins] << { waypoint: { placeId: ride.origin_place_id } } | ||
acc[:destinations] << { waypoint: { placeId: ride.destination_place_id } } | ||
end | ||
end | ||
|
||
private def transform_keys!(data) | ||
data.map { |d| d.transform_keys { |k| k.to_s.underscore.to_sym } } | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe Rides::Commands::GetCommuteDuration do | ||
it "gets data for an address" do | ||
VCR.use_cassette("first_commute") do | ||
from_address = create( | ||
:address, :with_out_place_id, line_1: "4705 Weitzel Street", city: "Timnath", state: "CO", | ||
zip_code: "80547" | ||
) | ||
to_address = create( | ||
:address, :with_out_place_id, line_1: "151 N College Ave", city: "Fort Collins", state: "CO", | ||
zip_code: "80524" | ||
) | ||
create_list(:ride, 2, from_address:, to_address:) | ||
driver = create(:driver, current_address: from_address) | ||
rides = Ride.selectable | ||
data = described_class.call(rides:, driver:) | ||
|
||
expect(data.length).to eq(2) | ||
expect(data.all? { _1.duration == "577s" }) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe Rides::Commands::GetRoutesData do | ||
it "gets data for an address" do | ||
VCR.use_cassette("first_ride_directions") do | ||
from_address = create( | ||
:address, :with_out_place_id, line_1: "711 Oval Drive", city: "Fort Collins", state: "CO", | ||
zip_code: "80521" | ||
) | ||
to_address = create( | ||
:address, :with_out_place_id, line_1: "151 N College Ave", city: "Fort Collins", state: "CO", | ||
zip_code: "80524" | ||
) | ||
create_list(:ride, 2, from_address:, to_address:) | ||
rides = Ride.selectable | ||
data = described_class.call(rides:) | ||
|
||
expect(data.length).to eq(2) | ||
expect(data.all? { _1.distance_in_meters == 3105 && _1.duration == "577s" }) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters