Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
source 'http://rubygems.org'

ruby '2.5.5'
ruby '2.6.5'

gem 'rake'

Expand Down
34 changes: 34 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
GEM
remote: http://rubygems.org/
specs:
ansi (1.5.0)
awesome_print (1.8.0)
builder (3.2.4)
csv (3.1.2)
minitest (5.14.0)
minitest-reporters (1.4.2)
ansi
builder
minitest (>= 5.0)
ruby-progressbar
minitest-skip (0.0.1)
minitest (~> 5.0)
rake (13.0.1)
ruby-progressbar (1.10.1)

PLATFORMS
ruby

DEPENDENCIES
awesome_print
csv
minitest
minitest-reporters
minitest-skip
rake

RUBY VERSION
ruby 2.6.5p114

BUNDLED WITH
2.1.4
82 changes: 82 additions & 0 deletions lib/driver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
require_relative 'csv_record'

module RideShare
class Driver < CsvRecord

attr_reader :id, :name, :vin, :status, :trips

def initialize(id:, name:, vin:, status: :AVAILABLE, trips: nil)
super(id)

@name = name
@vin = vin

if @vin.to_s.length != 17
raise ArgumentError.new("Wrong length of vin!")
end

@status = status.to_sym

if ![:AVAILABLE, :UNAVAILABLE].include?@status.upcase.to_sym
raise ArgumentError.new("Invalid status.")
end

@trips = [] || trips
end

def self.from_csv(record)
return new(
id: record[:id],
name: record[:name],
vin: record[:vin],
status: record[:status]
)
end

def add_trip(trip)
@trips << trip
end

def average_rating
sum_of_ratings = 0.0
trips_in_progress = 0
return 0 if @trips.length == 0

@trips.each do |trip|
if trip.end_time != nil
sum_of_ratings += trip.rating
else
trips_in_progress += 1
end
end

return (sum_of_ratings / (@trips.length - trips_in_progress))
end

def total_revenue
return 0.0 if @trips.length == 0

sum_of_trip_costs = 0.0

@trips.each do |trip|
if trip.end_time != nil
if trip.cost < 1.65
net_trip = trip.cost
else
net_trip = trip.cost - 1.65
end

sum_of_trip_costs += net_trip
end
end

return (sum_of_trip_costs * 0.80)
end

def update_status(trip)
add_trip(trip)
@status = :UNAVAILABLE
end

end
end
25 changes: 25 additions & 0 deletions lib/passenger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ def add_trip(trip)
@trips << trip
end

def net_expenditures
sum = 0

@trips.each do |trip|
if trip.end_time != nil
sum += trip.cost
end
end

return sum
end


def total_time_spent
time_spent = 0

@trips.each do |trip|
if trip.end_time != nil
time_spent += trip.calculate_duration
end
end

return time_spent
end

private

def self.from_csv(record)
Expand Down
48 changes: 39 additions & 9 deletions lib/trip.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
require 'csv'
require 'time'

require_relative 'csv_record'

module RideShare
class Trip < CsvRecord
attr_reader :id, :passenger, :passenger_id, :start_time, :end_time, :cost, :rating
attr_reader :id, :passenger, :passenger_id, :start_time, :end_time, :cost, :rating, :driver_id, :driver

def initialize(
id:,
Expand All @@ -13,7 +14,9 @@ def initialize(
start_time:,
end_time:,
cost: nil,
rating:
rating:,
driver_id: nil,
driver: nil
)
super(id)

Expand All @@ -28,13 +31,32 @@ def initialize(
raise ArgumentError, 'Passenger or passenger_id is required'
end

if driver
@driver = driver
@driver_id = driver.id

elsif driver_id
@driver_id = driver_id

else
raise ArgumentError, 'Driver or driver_id is required'
end

if end_time != nil
if end_time < start_time
raise ArgumentError.new("End time cannot be less than the Start time")
end
end

@start_time = start_time
@end_time = end_time
@cost = cost
@rating = rating

if @rating > 5 || @rating < 1
raise ArgumentError.new("Invalid rating #{@rating}")
if @rating != nil
if @rating > 5 || @rating < 1
raise ArgumentError.new("Invalid rating #{@rating}")
end
end
end

Expand All @@ -46,9 +68,16 @@ def inspect
"PassengerID=#{passenger&.id.inspect}>"
end

def connect(passenger)
def connect(passenger, driver)
@passenger = passenger
passenger.add_trip(self)

@driver = driver
driver.add_trip(self)
end

def calculate_duration
return (end_time - start_time)
end

private
Expand All @@ -57,11 +86,12 @@ def self.from_csv(record)
return self.new(
id: record[:id],
passenger_id: record[:passenger_id],
start_time: record[:start_time],
end_time: record[:end_time],
start_time: Time.parse(record[:start_time]),
end_time: Time.parse(record[:end_time]),
cost: record[:cost],
rating: record[:rating]
)
rating: record[:rating],
driver_id: record[:driver_id]
)
end
end
end
71 changes: 70 additions & 1 deletion lib/trip_dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

require_relative 'passenger'
require_relative 'trip'
require_relative 'driver'

module RideShare
class TripDispatcher
Expand All @@ -11,6 +12,7 @@ class TripDispatcher
def initialize(directory: './support')
@passengers = Passenger.load_all(directory: directory)
@trips = Trip.load_all(directory: directory)
@drivers = Driver.load_all(directory: directory)
connect_trips
end

Expand All @@ -19,6 +21,72 @@ def find_passenger(id)
return @passengers.find { |passenger| passenger.id == id }
end

def find_driver(id)
Driver.validate_id(id)
return @drivers.find { |driver| driver.id == id }
end

def find_available_drivers
available_drivers = @drivers.select do |driver|
driver.status == :AVAILABLE
end

return available_drivers
end

def select_driver(available_drivers)
available_drivers.each do |driver|
if driver.trips.length == 0
return driver
end
end

available_drivers.each do |driver|

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great use of enumerable method .sort_by!

driver.trips.sort_by! do |trip|
trip.end_time
end
end

available_drivers.sort_by! do |driver|
driver.trips.last.end_time
end

return available_drivers.first
end

def request_trip(passenger_id)
# Find list of available drivers.
available_drivers = find_available_drivers

# If no available drivers are found
if available_drivers.length == 0
raise ArgumentError.new("No available drivers!")
end

# Find a driver with no trips ever or the oldest trip.
available_driver = select_driver(available_drivers)

current_passenger = find_passenger(passenger_id)

id = trips.length + 1

new_trip = RideShare::Trip.new(
id: id,
passenger_id: passenger_id,
start_time: Time.now,
end_time: nil,
cost: nil,
rating: nil,
driver: available_driver
)

available_driver.update_status(new_trip) # Updates driver status to unavailable.
current_passenger.add_trip(new_trip) # Adds current trip to current passenger's list of trips.
@trips << new_trip # Adds current trip to list of all trips in system.

return new_trip
end

def inspect
# Make puts output more useful
return "#<#{self.class.name}:0x#{object_id.to_s(16)} \
Expand All @@ -32,7 +100,8 @@ def inspect
def connect_trips
@trips.each do |trip|
passenger = find_passenger(trip.passenger_id)
trip.connect(passenger)
driver = find_driver(trip.driver_id)
trip.connect(passenger, driver)
end

return trips
Expand Down
Loading