-
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.
* Generate drivers controller * Add jsonapi-serializer * Add spec showing driver return * Add routes for rides * Add rank command to rank rides based on provided formula * remove unneeded generator * Work on creating spec for ranked rides * Work on serialization * work on serialization * Add expectations for api return * Fix return specs * remove controllers for now * fix rubocop * fix rubocop errors * fix flaky spec
- Loading branch information
Showing
22 changed files
with
1,194 additions
and
11 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
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 |
---|---|---|
@@ -1,4 +1,14 @@ | ||
# frozen_string_literal: true | ||
|
||
class ApplicationController < ActionController::API | ||
private def pagination_params | ||
params.permit(:limit, :offset) | ||
end | ||
private def limit | ||
pagination_params[:limit] || 2 | ||
end | ||
|
||
private def offset | ||
pagination_params[:offset] || 0 | ||
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,19 @@ | ||
# frozen_string_literal: true | ||
|
||
module Drivers | ||
class SelectableRidesController < ApplicationController | ||
def index | ||
rides = Rides::Commands::RankRides.call(driver:)[offset, limit] | ||
opts = { include: %i[from_address to_address] } | ||
render json: RidePojoSerializer.new(rides, opts) | ||
end | ||
|
||
private def driver | ||
@driver ||= Driver.find(ride_params[:driver_id]) | ||
end | ||
|
||
private def ride_params | ||
params.permit(:driver_id, :limit, :offset) | ||
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,12 @@ | ||
# frozen_string_literal: true | ||
|
||
class DriversController < ApplicationController | ||
def index | ||
drivers = Driver.limit(limit).offset(offset) | ||
render json: DriverSerializer.new(drivers, is_collection: true) | ||
end | ||
|
||
private def pagination_params | ||
params.permit(:limit, :offset) | ||
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,7 @@ | ||
# frozen_string_literal: true | ||
|
||
class AddressSerializer | ||
include JSONAPI::Serializer | ||
set_type :address | ||
attributes :id, :line_1, :line_2, :city, :state, :zip_code, :full_address | ||
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,8 @@ | ||
# frozen_string_literal: true | ||
|
||
class DriverSerializer | ||
include JSONAPI::Serializer | ||
set_type :driver | ||
attributes :id, :full_name | ||
has_one :current_address, serializer: AddressSerializer | ||
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,32 @@ | ||
# frozen_string_literal: true | ||
|
||
class RidePojoSerializer | ||
include JSONAPI::Serializer | ||
extend ActionView::Helpers::DateHelper | ||
extend ActionView::Helpers::NumberHelper | ||
|
||
set_id do |struct, _params| | ||
struct.ride_id | ||
end | ||
|
||
set_type "pre-ride" | ||
|
||
attribute :distance do |struct, _params| | ||
number_to_human((struct.distance_meters / 1609.34).round(2), units: :distance) | ||
end | ||
|
||
attribute :duration do |struct, _params| | ||
distance_of_time_in_words(struct.duration.to_f) | ||
end | ||
|
||
attribute :commute_duration do |struct, _params| | ||
distance_of_time_in_words(struct.commute_duration.to_f) | ||
end | ||
|
||
attribute :ride_earnings do |struct, _params| | ||
struct.ride_amount.format | ||
end | ||
|
||
belongs_to :from_address, serializer: AddressSerializer | ||
belongs_to :to_address, serializer: AddressSerializer | ||
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
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 |
---|---|---|
|
@@ -29,3 +29,10 @@ | |
|
||
en: | ||
hello: "Hello world" | ||
distance: | ||
centi: | ||
one: "foot" | ||
other: "feet" | ||
unit: | ||
one: "mile" | ||
other: "miles" |
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
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
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,88 @@ | ||
# frozen_string_literal: true | ||
|
||
module Rides | ||
module Commands | ||
class RankRides < BaseCommand | ||
def call(driver:) | ||
rank!(driver) | ||
end | ||
|
||
# How the Sorting Works | ||
# 1. Calculate the Key: For each ride, calculate the earnings per hour using rank_key. | ||
# 2. Negate the Key: By using -rank_key, we convert the highest earnings per hour to the smallest negative | ||
# number, and the smallest earnings per hour to the largest negative number. | ||
# 3. Sort in Ascending Order: Ruby's sort_by method will then sort the rides based on these negative values, | ||
# effectively putting the rides with the highest earnings per hour first. | ||
private def rank!(driver) | ||
rides = combined_ride_data(driver) | ||
return [] if rides.empty? | ||
|
||
rides.sort_by { |ride| -rank_key(ride) } | ||
end | ||
|
||
# (ride earnings) / (commute duration + ride duration) | ||
private def rank_key(ride) | ||
earnings = ride.ride_amount.amount | ||
ride_duration_hours = duration_to_hours(ride.duration) | ||
commute_duration_hours = duration_to_hours(ride.commute_duration) | ||
total_duration_hours = ride_duration_hours + commute_duration_hours | ||
|
||
# Earnings per hour | ||
earnings / total_duration_hours | ||
end | ||
|
||
private def duration_to_hours(duration) | ||
duration.to_i / 3600.0 | ||
end | ||
|
||
# Once we get the data, we want to combine them into one struct | ||
# to more easily compute the ride earnings and assign a rank | ||
private def combined_ride_data(driver) | ||
commutes = commute_durations(driver) | ||
rides = route_data(driver) | ||
|
||
if commutes.count != rides.count | ||
raise RideCountMismatchError, | ||
"The number of rides doesn't match the number of commute rides." \ | ||
"Please check the ride(s) configuration and try again." | ||
end | ||
|
||
combine_rides!(rides, commutes) | ||
end | ||
|
||
# Combines the duration data for the driver to get to the start of the ride | ||
# with that of the ride's data, e.g., duration, distance | ||
private def combine_rides!(rides, commutes) | ||
rides.map.with_index do |ride, idx| | ||
commute = commutes.fetch(idx) | ||
commute_duration = commute.duration | ||
commute_distance = commute.distance_meters | ||
ride_amount = ComputeAmount.call(ride:) | ||
|
||
ride.commute_duration = commute_duration | ||
ride.commute_distance = commute_distance | ||
ride.ride_amount = ride_amount | ||
ride | ||
end | ||
end | ||
|
||
# Get the driving duration to the Ride#from_address, | ||
# to get the duration of the commute to start the ride | ||
private def commute_durations(driver) | ||
rides = selectable_rides_near_driver(driver) | ||
@commute_durations ||= GetCommuteDuration.call(rides:, driver:) | ||
end | ||
|
||
# Get route data for the ride, the duration and the distance between | ||
# the from and to addresses | ||
private def route_data(driver) | ||
rides = selectable_rides_near_driver(driver) | ||
@route_data ||= GetRoutesData.call(rides:) | ||
end | ||
|
||
private def selectable_rides_near_driver(driver) | ||
@selectable_rides_near_driver ||= Ride.selectable.nearby_driver(driver) | ||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.