Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
066fe24
WIP: initial set up
botrethewey Mar 7, 2017
cff0299
WIP: added #initialize tests
botrethewey Mar 7, 2017
026da93
#initialize method passes the test
botrethewey Mar 7, 2017
5983af1
removed simplecov for now
botrethewey Mar 7, 2017
de39fee
WIP: test for #initialize finished for all classes
botrethewey Mar 7, 2017
b952fe8
WIP: added tests for #find_driver,and #find_rider methods in trip class
botrethewey Mar 7, 2017
c81a43a
Completed tests for trip class
botrethewey Mar 8, 2017
a542fbc
Added tests for methods in driver class
botrethewey Mar 8, 2017
7d2e076
Finished tests for driver class
botrethewey Mar 8, 2017
b462a58
Fixed tests for #trips in driver class
botrethewey Mar 8, 2017
74cf122
Fixed spelling error
botrethewey Mar 8, 2017
323a997
Finished tests for rider class
botrethewey Mar 8, 2017
b7fc72b
Fixed up spelling errors
botrethewey Mar 8, 2017
cd559c1
Fixed spelling errors
botrethewey Mar 8, 2017
2edbcaf
Finished baseline tests
botrethewey Mar 8, 2017
27aebc2
Added some tests for optional work using costs and duration data
botrethewey Mar 8, 2017
9ad8239
Added tests for #drivers to account for repeated driver instances
botrethewey Mar 8, 2017
b149ab6
Added code for #drivers in rider class
botrethewey Mar 8, 2017
12b692e
Used an enumerator for #drivers
botrethewey Mar 8, 2017
a2e74f5
Removed redundant code
botrethewey Mar 8, 2017
e0cccce
Finished tests for optionals in driver class
botrethewey Mar 12, 2017
3d7e442
Reformulated tests for trip class
botrethewey Mar 12, 2017
1ce68c1
Finished tests for optionals in rider class
botrethewey Mar 12, 2017
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/coverage/
10 changes: 9 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
# Fill me in!
require 'rake/testtask'

Rake::TestTask.new do |t|
t.libs = ["lib"]
t.warning = true
t.test_files = FileList['specs/*_spec.rb']
end

task default: :test
74 changes: 74 additions & 0 deletions lib/driver.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
require 'csv'

module RideShare
class Driver
attr_reader :id, :name, :vin

def initialize(driver_hash)
raise ArgumentError.new("Invalid argument type: must be a hash object") if driver_hash.class != Hash

[:id, :name, :vin].each { |sym_key|
raise ArgumentError.new("Invalid argument type: must have #{sym_key} value") if !driver_hash.keys.include?(sym_key)
}

@id = driver_hash[:id].to_i
@name = driver_hash[:name].to_s

@vin = driver_hash[:vin].to_s
# The length of the vehicle_id(:vin) must equal 17, to be considered valid
raise ArgumentError.new("Invalid argument type: vin(String) number must be 17 chracters, mix of letters and numerals") if driver_hash[:vin] !~ /^([a-zA-Z]|\d){17}$/
end

# Retrieve the list of trip instances that only this driver has taken
def trips
trips = RideShare::Trip.trips_by_driver(id)
if trips != nil
return trips
else
return []
end
end

# Retrieve an average rating for that driver based on all trips taken
def avg_rating
all_trips_by_driver_array = trips
sum_rate = 0.0
if all_trips_by_driver_array == []
return sum_rate
else
all_trips_by_driver_array.each { |trip| sum_rate += trip.rating }
return (sum_rate / all_trips_by_driver_array.length).round(2)
end
end

# Calculate the driver's total revenue for all trips
# Each driver gets 80% of the trip cost after a fee of $1.65 is subtracted.
def revenue
all_trips_by_driver_array = trips
sum_cost = 0
if all_trips_by_driver_array == []
return sum_cost
else
all_trips_by_driver_array.each { |trip| sum_cost += ( ( trip.cost - 165 ) * 0.8 ).to_i }
return sum_cost
end
end

# Retrieve all drivers from the CSV file
def self.all
all_drivers_array= []
CSV.foreach("support/drivers.csv", {:headers => true}) do |line|
all_drivers_array << RideShare::Driver.new({ id: line[0].to_i, name: line[1], vin: line[2] })
end
return all_drivers_array
end

# Find a specific driver using their numeric ID
def self.find(driver_id)
raise ArgumentError.new ("Driver id must be a positive integer value") if ( driver_id.class != Integer || driver_id < 0 )
all_drivers_array = RideShare::Driver.all
return nil if !all_drivers_array.any? { |driver| driver.id == driver_id }
return (all_drivers_array.select { |driver| driver.id == driver_id })[0]
end
end
end
66 changes: 66 additions & 0 deletions lib/rider.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require 'csv'

module RideShare
class Rider
attr_reader :id, :name, :phone_number

def initialize(rider_hash)
raise ArgumentError.new("Invalid argument type: must be a hash object") if rider_hash.class != Hash

[:id, :name, :phone_number].each { |sym_key|
raise ArgumentError.new("Invalid argument type: must have #{sym_key} value") if !rider_hash.keys.include?(sym_key)
}

@id = rider_hash[:id].to_i
@name = rider_hash[:name].to_s
@phone_number = rider_hash[:phone_number].to_s
end

# Retrieve the list of trip instances that only this rider has taken
def trips
trips = RideShare::Trip.trips_by_rider(@id)
if trips != nil
return trips
else
return []
end
end

# Retrieve the list of all previous driver instances
def drivers
drivers = (trips.map { |trip| RideShare::Driver.find(trip.driver_id) }).compact
return drivers.uniq { |driver| driver.id }
end

# Retrives the total amount cost of all trips by this rider
def total_cost
costs = 0
trips.each { |trip| costs += trip.cost }
return costs
end

# Retrieves the total time spent traveling on all trips by this rider
def total_duration
duration = 0
trips.each { |trip| duration += trip.duration }
return duration
end

# Retrieve all riders from the CSV file
def self.all
all_riders_array= []
CSV.foreach("support/riders.csv", {:headers => true}) do |line|
all_riders_array << RideShare::Rider.new({id: line[0].to_i, name: line[1], phone_number: line[2]})
end
return all_riders_array
end

# Find a specific rider using their numeric ID
def self.find(rider_id)
raise ArgumentError.new ("Rider id must be a positive integer value") if ( rider_id.class != Integer || rider_id < 0 )
all_riders_array = RideShare::Rider.all
return nil if !all_riders_array.any? { |rider| rider.id == rider_id }
return all_riders_array.select { |rider| rider.id == rider_id }[0]
end
end
end
73 changes: 73 additions & 0 deletions lib/trip.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
require 'csv'

module RideShare
class Trip
attr_reader :id, :driver_id, :rider_id, :date, :rating, :cost, :duration

def initialize(trip_hash)
raise ArgumentError.new("Invalid argument type: must be a hash object") if trip_hash.class != Hash

[:id, :rider_id, :driver_id, :date, :rating, :cost, :duration].each { |sym_key|
raise ArgumentError.new("Invalid argument type: must have #{sym_key} value") if !trip_hash.keys.include?(sym_key)
}

@id = trip_hash[:id].to_i
@rider_id = trip_hash[:rider_id].to_i
@driver_id = trip_hash[:driver_id].to_i
@date = trip_hash[:date].to_s

@rating = trip_hash[:rating].to_i
# Each rating should be within an acceptable range (1-5)
raise ArgumentError.new("Invalid argument type: rating(Integer) value must be in the range (1-5)") if trip_hash[:rating] < 1 || trip_hash[:rating] > 5

@cost = trip_hash[:cost].to_i
# Each cost should be a positive amount in cents
raise ArgumentError.new("Invalid argument type: cost(Integer) value must be at list $1.65 in cents") if trip_hash[:cost] < 165

@duration = trip_hash[:duration].to_i
# Each duration should be a positive amount in minutes
raise ArgumentError.new("Invalid argument type: duration(Integer) value must be a positive amount in minutes") if trip_hash[:duration] < 0
end

# Retrieve the associated driver instance through the driver ID
def find_driver
return Driver.find(driver_id)
end

# Retrieve the associated rider instance through the rider ID
def find_rider
return Rider.find(rider_id)
end

# Find all trip instances for a given driver ID
def self.all
all_trips_array= []
CSV.foreach("support/trips.csv", {:headers => true}) do |line|
all_trips_array << RideShare::Trip.new( id: line[0].to_i, driver_id: line[1].to_i, rider_id: line[2].to_i, date: line[3], rating: line[4].to_i, cost: line[5].to_i, duration: line[6].to_i)
end
return all_trips_array
end

# Find all trip instances for a given rider ID
def self.trips_by_driver(driver_id)
raise ArgumentError.new ("Driver id must be a positive integer value") if ( driver_id.class != Integer || driver_id < 0 )
all_trips_array = Trip.all
if all_trips_array.any? { |trip| trip.driver_id == driver_id }
return all_trips_array.select { |trip| trip.driver_id == driver_id }
else
return nil
end
end

# Retrieve all trips from the CSV file
def self.trips_by_rider(rider_id)
raise ArgumentError.new ("Rider id must be a positive integer value") if ( rider_id.class != Integer || rider_id < 0 )
all_trips_array = Trip.all
if all_trips_array.any? { |trip| trip.rider_id == rider_id }
return all_trips_array.select { |trip| trip.rider_id == rider_id }
else
return nil
end
end
end
end
156 changes: 156 additions & 0 deletions specs/driver_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
require_relative 'spec_helper'
require_relative '../lib/driver'

describe "Driver class" do
let (:driver_hash) { { id: 6, name: "Mr. Hyman Wolf", vin: "L1CXMYNZ3MMGTTYWU" } }
let (:driver) { RideShare::Driver.new(driver_hash) }

describe "#initialize method" do
it "Initializes a new driver instance from the parameter" do
driver.must_be_instance_of RideShare::Driver
driver.must_respond_to :id
driver.id.must_equal driver_hash[:id]
driver.must_respond_to :name
driver.name.must_equal driver_hash[:name]
driver.must_respond_to :vin
driver.vin.must_equal driver_hash[:vin]
end

it "Raises an argument error if the parameter is not hash" do
proc {
RideShare::Driver.new()
}.must_raise ArgumentError

proc {
RideShare::Driver.new("6, Mr. Hyman Wolf, L1CXMYNZ3MMGTTYWU")
}.must_raise ArgumentError
end

it "Raises an argument error if the driver_hash parameter is incomplete" do
proc {
RideShare::Driver.new({})
}.must_raise ArgumentError

proc {
RideShare::Driver.new({ name: "Mr. Hyman Wolf", vin: "L1CXMYNZ3MMGTTYWU" })
}.must_raise ArgumentError

proc {
RideShare::Driver.new({ nick_name: "Betsy", vin: "L1CXMYNZ3MMGTTYWU" })
}.must_raise ArgumentError
end

it "Raises an argument error if the vin number is invalid: must have length 17" do
proc {
RideShare::Driver.new({ id: 6, name: "Mr. Hyman Wolf", vin: "L1CXMYNZ3MMGTTYWUXXX" })
}.must_raise ArgumentError
end
end

describe "#trips method" do
let (:trips_by_driver) { driver.trips }

it "Retrieve the list of trip instances that only this driver has taken" do
trips_by_driver.must_be_instance_of Array
trips_by_driver.length.must_equal 3
trips_by_driver.each { |trip| trip.must_be_instance_of RideShare::Trip }
end

it "First element inside the returned array matches the CSV file" do
trip = trips_by_driver.first
trip.id.must_equal 162
trip.driver_id.must_equal 6
trip.rider_id.must_equal 93
trip.date.must_equal "2015-03-09"
trip.rating.must_equal 4
end

it "The last element inside the returned array matches the CSV file" do
trip = trips_by_driver.last
trip.id.must_equal 295
trip.driver_id.must_equal 6
trip.rider_id.must_equal 87
trip.date.must_equal "2015-08-14"
trip.rating.must_equal 1
end

it "Returns an empty array if the driver has't made any trips yet" do
RideShare::Driver.new({ id: 100, name: "Minnie Dach", vin: "XF9Z0ST7X18WD41HT" }).trips.must_equal []
end
end

describe "#avg_rating method" do
it "Retrieve an average rating for that driver based on all trips taken" do
average = driver.avg_rating
average.must_be_instance_of Float
average.must_equal 3.0
end

it "Returned value is in the range 1 - 5" do
average = RideShare::Driver.new({ id: 23, name: "Bo Stroman DVM", vin: "1F8C93JX5D62SYRYY" }).avg_rating
average.must_be :>=, 1.0
average.must_be :<=, 5.0
end

it "Returns 0.0 if the driver hasn't made any trips yet" do
RideShare::Driver.new({ id: 100, name: "Minnie Dach", vin: "XF9Z0ST7X18WD41HT" }).avg_rating.must_equal 0.0
end
end

describe "#revenue method" do
it "Calculate the total revenue for all trips by the driver" do
driver.revenue.must_be_instance_of Integer
driver.revenue.must_be :>=, 0
driver.revenue.must_equal 5568
end

it "Returns zero if the driver hasn't made any trips yet" do
RideShare::Driver.new({ id: 100, name: "Minnie Dach", vin: "XF9Z0ST7X18WD41HT" }).revenue.must_equal 0
end
end

let (:all_drivers_array) { RideShare::Driver.all }

describe "#self.all method" do

it "Retrieve all drivers from the CSV file" do
all_drivers_array.must_be_instance_of Array
all_drivers_array.length.must_equal 100
all_drivers_array.each { |driver| driver.must_be_instance_of RideShare::Driver }
end

it "First element inside the returned array matches the CSV file" do
driver = all_drivers_array.first
driver.id.must_equal 1
driver.name.must_equal "Bernardo Prosacco"
driver.vin.must_equal "WBWSS52P9NEYLVDE9"
end

it "Last element inside the returned array matches the CSV file" do
driver = all_drivers_array.last
driver.id.must_equal 100
driver.name.must_equal "Minnie Dach"
driver.vin.must_equal "XF9Z0ST7X18WD41HT"
end
end

describe "#self.find method" do
it "Find a specific driver using their numeric ID" do
driver = RideShare::Driver.find(6)
driver.must_be_instance_of RideShare::Driver
driver.id.must_equal 6
driver.name.must_equal "Mr. Hyman Wolf"
driver.vin.must_equal "L1CXMYNZ3MMGTTYWU"
end

it "Raises an argument error when invalid driver id is passed" do
proc{
RideShare::Driver.find("six")
}.must_raise ArgumentError
end

it "Returns nil if the driver id does not have a match in the driver.csv" do
RideShare::Driver.find(123456789).must_be_nil
end
end
end
Loading