Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Earth - Ting-Yi and Sophie - OO Ride Share #3

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
3 changes: 3 additions & 0 deletions .floo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"url": "https://floobits.com/SophieMess/oo-ride-share"
}
6 changes: 6 additions & 0 deletions .flooignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
extern
node_modules
tmp
vendor
.idea/workspace.xml
.idea/misc.xml
73 changes: 73 additions & 0 deletions lib/driver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require_relative 'csv_record'

module RideShare
class Driver < CsvRecord
attr_reader :name, :vin, :status, :trips

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

@name = name

raise ArgumentError.new("Invalid VIN: #{ vin }") if vin.length != 17
@vin = vin

raise ArgumentError.new("Invalid status: #{ status }") unless [:AVAILABLE, :UNAVAILABLE].include? (status.to_sym)
@status = status.to_sym

@trips = trips
end

def add_trip(trip)
@trips << trip
end

def average_rating
length = @trips.length
return 0 if length == 0

total = 0

@trips.each do |trip|
total += trip.rating unless trip.rating.nil?
if trip.rating.nil?
length -= 1
end
end
average = total.to_f / length
return average.round(1)
end

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

total = 0

@trips.each do |trip|
if trip.cost.nil?
next
elsif trip.cost <= 1.65
total += (trip.cost * 0.8)
elsif
total += ((trip.cost - 1.65) * 0.8)
end
end
return total.round(2)
end

def trip_in_progress
@status = :UNAVAILABLE
end

private

def self.from_csv(record)
return new(
id: record[:id],
name: record[:name],
vin: record[:vin],
status: record[:status]
)
end
end
end
13 changes: 13 additions & 0 deletions lib/passenger.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,19 @@ def add_trip(trip)
@trips << trip
end

def net_expenditures
total = 0
@trips.each do |trip|
total += trip.cost unless trip.cost.nil?
end
return total
end

def total_time_spent
total = @trips.sum { |trip| trip.duration }
return total
end

private

def self.from_csv(record)
Expand Down
35 changes: 28 additions & 7 deletions lib/trip.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
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,:driver, :driver_id, :start_time, :end_time, :cost, :rating

def initialize(
id:,
passenger: nil,
passenger_id: nil,
driver: nil,
driver_id: nil,
start_time:,
end_time:,
cost: nil,
Expand All @@ -28,14 +31,28 @@ def initialize(
raise ArgumentError, 'Passenger or passenger_id is required'
end

raise ArgumentError, 'Driver or driver_id is required' unless driver || driver_id
@driver = driver
@driver.nil? ? @driver_id = driver_id : @driver_id = driver.id

@start_time = start_time
@end_time = end_time
raise ArgumentError.new("Start time should occur before the end time") if @start_time > @end_time unless @end_time.nil?

@cost = cost

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

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

def duration
if @end_time.nil?
duration = 0
else
duration = @end_time - @start_time
end
return duration.to_i
end

def inspect
Expand All @@ -44,15 +61,18 @@ def inspect
"#<#{self.class.name}:0x#{self.object_id.to_s(16)} " +
"id=#{id.inspect} " +
"passenger_id=#{passenger&.id.inspect} " +
"driver_id=#{driver&.id.inspect} " +
"start_time=#{start_time} " +
"end_time=#{end_time} " +
"cost=#{cost} " +
"cost=#{cost} " +
"rating=#{rating}>"
end

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

private
Expand All @@ -61,8 +81,9 @@ 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],
driver_id: record[:driver_id],
start_time: Time.parse(record[:start_time]),
end_time: Time.parse(record[:end_time]),
cost: record[:cost],
rating: record[:rating]
)
Expand Down
35 changes: 33 additions & 2 deletions lib/trip_dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,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 +20,36 @@ 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 intelligent_dispatch
drivers_available = @drivers.select { |driver| driver.status == :AVAILABLE }
raise ArgumentError.new("No available drivers") if drivers_available.empty?

if drivers_available.any? { |candidate| candidate.trips.count == 0 }
driver = drivers_available.find { |candidate| candidate.trips.count == 0 }
else
driver = drivers_available.min_by { |candidate| candidate.trips.last.end_time }
end
return driver
end

def request_trip(passenger_id)
passenger = find_passenger(passenger_id)
driver = intelligent_dispatch

trip = Trip.new(id: @trips.last.id + 1, passenger: passenger, passenger_id: passenger_id, driver: driver, driver_id: driver.id, start_time: Time.now, end_time: nil, cost: nil, rating: nil)

@trips << trip
passenger.add_trip(trip)
driver.add_trip(trip)
driver.trip_in_progress
return trip
end

def inspect
# Make puts output more useful
return "#<#{self.class.name}:0x#{object_id.to_s(16)} \
Expand All @@ -32,9 +63,9 @@ 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
end
end
Expand Down
83 changes: 76 additions & 7 deletions test/driver_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
require_relative 'test_helper'

xdescribe "Driver class" do
describe "Driver class" do
describe "Driver instantiation" do
before do
@driver = RideShare::Driver.new(
Expand Down Expand Up @@ -84,15 +84,15 @@
id: 54,
name: "Rogers Bartell IV",
vin: "1C9EVBRM0YBC564DZ"
)
)
trip = RideShare::Trip.new(
id: 8,
driver: @driver,
passenger_id: 3,
start_time: Time.new(2016, 8, 8),
end_time: Time.new(2016, 8, 8),
rating: 5
)
)
@driver.add_trip(trip)
end

Expand All @@ -111,26 +111,95 @@
id: 54,
name: "Rogers Bartell IV",
vin: "1C9EVBRM0YBC564DZ"
)
)
expect(driver.average_rating).must_equal 0
end

it "correctly calculates the average rating" do
it "correctly calculates the average rating for a driver" do
trip2 = RideShare::Trip.new(
id: 8,
driver: @driver,
passenger_id: 3,
start_time: Time.new(2016, 8, 8),
end_time: Time.new(2016, 8, 9),
rating: 1
)
)
@driver.add_trip(trip2)

expect(@driver.average_rating).must_be_close_to (5.0 + 1.0) / 2.0, 0.01
end

it "correctly calculates the average rating for a driver with an in-progress trip" do
trip2 = RideShare::Trip.new(
id: 8,
driver: @driver,
passenger_id: 3,
start_time: Time.new(2016, 8, 8),
end_time: Time.new(2016, 8, 9),
rating: 1
)
trip3 = RideShare::Trip.new(
id: 9,
driver: @driver,
passenger_id: 6,
start_time: Time.now,
end_time: nil,
rating: nil,
cost: nil
)

@driver.add_trip(trip2)
@driver.add_trip(trip3)

expect(@driver.average_rating).must_be_close_to (5.0 + 1.0) / 2.0, 0.01
end
end

describe "total_revenue" do
# You add tests for the total_revenue method
before do
@driver = RideShare::Driver.new(
id: 54,
name: "Rogers Bartell IV",
vin: "1C9EVBRM0YBC564DZ"
)
trip = RideShare::Trip.new(
id: 8,
driver: @driver,
passenger_id: 3,
start_time: Time.new(2016, 8, 8),
end_time: Time.new(2016, 8, 8),
cost: 1,
rating: 5
)
trip_2 = RideShare::Trip.new(
id: 9,
driver: @driver,
passenger_id: 3,
start_time: Time.new(2016, 8, 8),
end_time: Time.new(2016, 8, 8),
cost: 10,
rating: 5
)
@driver.add_trip(trip)
@driver.add_trip(trip_2)
end
it "can calculate the total revenue for each driver" do
expect(@driver.total_revenue).must_equal 7.48
end

it "can calculate the total revenue for a driver with a trip in-progress" do
trip_3 = RideShare::Trip.new(
id: 10,
driver: @driver,
passenger_id: 6,
start_time: Time.now,
end_time: nil,
rating: nil,
cost: nil
)
@driver.add_trip(trip_3)

expect(@driver.total_revenue).must_equal 7.48
end
end
end
Loading