diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..73f69e095 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/.rakeTasks b/.idea/.rakeTasks new file mode 100644 index 000000000..f88db1a31 --- /dev/null +++ b/.idea/.rakeTasks @@ -0,0 +1,7 @@ + + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 000000000..b0db9b0fc --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 000000000..cd0b8b074 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..104be5c5f --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/oo-ride-share.iml b/.idea/oo-ride-share.iml new file mode 100644 index 000000000..656dc71df --- /dev/null +++ b/.idea/oo-ride-share.iml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/lib/driver.rb b/lib/driver.rb new file mode 100644 index 000000000..d6c92cd9a --- /dev/null +++ b/lib/driver.rb @@ -0,0 +1,56 @@ +require_relative 'csv_record' + +module RideShare + class Driver < CsvRecord + attr_reader :id, :name, :vin, :trips + attr_accessor :status + + def initialize(id:, name:, vin:, status: :AVAILABLE, trips: []) + super(id) + + @name = name + @vin = vin + raise ArgumentError.new("Invalid VIN") if (vin.length) != 17 + + @status = status + raise ArgumentError.new("Invalid status") if ![:AVAILABLE, :UNAVAILABLE].include?(@status) + + @trips = trips + + end + + def accept_new_trip(trip) + add_trip(trip) + @status = :UNAVAILABLE + end + + def add_trip(trip) + @trips << trip + end + + def average_rating + ratings_array = @trips.reject { |trip| trip.rating == nil }.map(&:rating) + return 0 if (@trips) == [] || @trips == nil + return (ratings_array.sum/ratings_array.length).to_f + end + + def total_revenue + return 0 if (@trips) == [] || @trips == nil + trip_cost = @trips.map(&:cost) + return 0 if trip_cost.sum < 1.65 + driver_revenue = (trip_cost.sum - 1.65) * 0.80 + return driver_revenue.to_f + end + + private + + def self.from_csv(record) + return new( + id: record[:id], + name: record[:name], + vin: record[:vin], + status: record[:status].to_sym + ) + end + end +end diff --git a/lib/main.rb b/lib/main.rb new file mode 100644 index 000000000..c3c366838 --- /dev/null +++ b/lib/main.rb @@ -0,0 +1,26 @@ +require_relative 'passenger' +require_relative 'trip' +require_relative 'csv_record' +require_relative 'driver' + +# passenger1 = Passenger.new(2, "Merten Noles", 8347387434, [1,20,54,2018-12-27 02:39:05 -0800,2018-12-27 03:38:08 -0800,10,4]) +# +# passenger1_expenditures = passenger1.net_expenditures +# +# pp passenger1_expenditures +# +# arr = [5,6,1] +# +# arr_sum = arr.reduce(:+) +# +# pp arr_sum +# +# @trips = +# +# def net_expenditures +# array_trip_costs = @trips.map(&:cost) +# total_expenditure = array_trip_costs.reduce(:+) +# return total_expenditure +# end + +driver_instance = Driver.new(1,"Paul Klee","WBS76FYD47DJF7206",AVAILABLE) \ No newline at end of file diff --git a/lib/passenger.rb b/lib/passenger.rb index 12ec25982..e0169133c 100644 --- a/lib/passenger.rb +++ b/lib/passenger.rb @@ -1,4 +1,5 @@ require_relative 'csv_record' +require_relative 'trip' module RideShare class Passenger < CsvRecord @@ -16,6 +17,15 @@ def add_trip(trip) @trips << trip end + def net_expenditures + total_expenditure = @trips.sum(&:cost) + return total_expenditure + end + + def total_time_spent + return @trips.sum(&:duration_trip) + end + private def self.from_csv(record) diff --git a/lib/trip.rb b/lib/trip.rb index f59464dae..901711375 100644 --- a/lib/trip.rb +++ b/lib/trip.rb @@ -1,19 +1,22 @@ 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:, passenger: nil, passenger_id: nil, start_time:, - end_time:, + end_time: nil, cost: nil, - rating: + rating: nil, + driver_id: nil, + driver: nil ) super(id) @@ -32,10 +35,18 @@ def initialize( @end_time = end_time @cost = cost @rating = rating + @driver_id = driver_id + @driver = driver - if @rating > 5 || @rating < 1 + + if @rating != nil && (@rating > 5 || @rating < 1) raise ArgumentError.new("Invalid rating #{@rating}") end + + if @end_time != nil && (@end_time < @start_time) + raise ArgumentError.new("Invalid Time") + end + end def inspect @@ -50,21 +61,31 @@ def inspect "rating=#{rating}>" end - def connect(passenger) + def connect(passenger, driver) @passenger = passenger passenger.add_trip(self) + @driver = driver + driver.add_trip(self) end + def duration_trip + duration = @end_time - @start_time + return duration + end + + private 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], + driver: record[:driver] ) end end diff --git a/lib/trip_dispatcher.rb b/lib/trip_dispatcher.rb index 5130849f8..b25d2082e 100644 --- a/lib/trip_dispatcher.rb +++ b/lib/trip_dispatcher.rb @@ -3,6 +3,7 @@ require_relative 'passenger' require_relative 'trip' +require_relative 'driver' module RideShare class TripDispatcher @@ -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 @@ -19,6 +21,45 @@ 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 driver_assigned + driver = @drivers.find { |driver| driver.status == :AVAILABLE } + return driver + end + + def request_trip(passenger_id) + driver = driver_assigned + return nil if driver == nil + + start_time = Time.now + end_time = nil + passenger = find_passenger(passenger_id) + trip_data = { + id: @trips.length + 1, + passenger: passenger, + start_time: start_time, + end_time: end_time, + cost: nil, + rating: nil, + driver_id: driver.id, + driver: driver + } + + new_trip_instance = RideShare::Trip.new(trip_data) + + + driver.accept_new_trip(new_trip_instance) + passenger.add_trip(new_trip_instance) + @trips << new_trip_instance + + return new_trip_instance + + end + def inspect # Make puts output more useful return "#<#{self.class.name}:0x#{object_id.to_s(16)} \ @@ -30,9 +71,11 @@ def inspect private 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 diff --git a/test/driver_test.rb b/test/driver_test.rb index 4e6076ec2..211fb5052 100644 --- a/test/driver_test.rb +++ b/test/driver_test.rb @@ -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( @@ -56,6 +56,7 @@ id: 3, name: "Test Driver", vin: "12345678912345678" + ) @trip = RideShare::Trip.new( id: 8, @@ -83,7 +84,7 @@ @driver = RideShare::Driver.new( id: 54, name: "Rogers Bartell IV", - vin: "1C9EVBRM0YBC564DZ" + vin: "1C9EVBRM0YBC564DZ", ) trip = RideShare::Trip.new( id: 8, @@ -128,9 +129,57 @@ expect(@driver.average_rating).must_be_close_to (5.0 + 1.0) / 2.0, 0.01 end + + it "correctly calculates the average rating including an in-progress trip" do + trip2 = RideShare::Trip.new( + id: 8, + driver: @driver, + passenger_id: 3, + start_time: Time.new(2016, 8, 8) + ) + @driver.add_trip(trip2) + + expect(@driver.average_rating).must_be_close_to (5.0) / 1.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", + trips: [] + ) + 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, + cost: 20, + ) + @driver.add_trip(trip) + end + + it "correctly calculates total_revenue" do + total = @driver.total_revenue + expect(total).must_be_close_to 14.68 + end + + it "total_revenue returns a float" do + expect(@driver.total_revenue).must_be_kind_of Float + end + + it "returns 0 if there are no trips" do + @driver = RideShare::Driver.new( + id: 32, + name: "Colorful Blob", + vin: "DKJSEKVKDKFJEKRKT" + ) + expect(@driver.total_revenue).must_equal 0 + end end end + diff --git a/test/passenger_test.rb b/test/passenger_test.rb index eb3a631df..7bec6f509 100644 --- a/test/passenger_test.rb +++ b/test/passenger_test.rb @@ -68,7 +68,36 @@ end end - describe "net_expenditures" do - # You add tests for the net_expenditures method + describe "net_expenditures PLUS TOTAL DURATION" do + before do + @passenger = RideShare::Passenger.new( + id: 9, + name: "Merl Glover III", + phone_number: "1-602-620-2330 x3723", + trips: [] + ) + trip = RideShare::Trip.new( + id: 8, + passenger: @passenger, + start_time: Time.new(2016, 8, 8), + end_time: Time.new(2016, 8, 9), + rating: 5, + cost: 4 + ) + + @passenger.add_trip(trip) + end + + it "returns net expenditures for each passenger's rides" do + expect(@passenger.net_expenditures).must_equal 4 + end + + it "returns total duration of all a passenger's trips" do + expect(@passenger.total_time_spent).must_be_close_to 86400.00 + end + + end + + end diff --git a/test/test_helper.rb b/test/test_helper.rb index bdb9bf352..082369790 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -12,4 +12,4 @@ require_relative '../lib/passenger' require_relative '../lib/trip' require_relative '../lib/trip_dispatcher' -# require_relative '../lib/driver' +require_relative '../lib/driver' diff --git a/test/trip_dispatch_test.rb b/test/trip_dispatch_test.rb index 21f4457b7..d5e9fd5ec 100644 --- a/test/trip_dispatch_test.rb +++ b/test/trip_dispatch_test.rb @@ -52,7 +52,7 @@ def build_test_dispatcher end end - describe "Passenger & Trip loader methods" do + describe "Passenger and Trip loader methods" do before do @dispatcher = build_test_dispatcher end @@ -78,8 +78,7 @@ def build_test_dispatcher end end - # TODO: un-skip for Wave 2 - xdescribe "drivers" do + describe "drivers" do describe "find_driver method" do before do @dispatcher = build_test_dispatcher @@ -95,7 +94,7 @@ def build_test_dispatcher end end - describe "Driver & Trip loader methods" do + describe "Driver and Trip loader methods" do before do @dispatcher = build_test_dispatcher end @@ -121,5 +120,33 @@ def build_test_dispatcher end end end + + describe "Request Trip Methods Testing" do + + # before do + # #### + # end + + it "creates a trip properly" do + dispatcher = build_test_dispatcher + trip = dispatcher.request_trip(8) + + expect(trip).must_be_instance_of RideShare::Trip + expect(trip.id).must_equal 6 + expect(trip.driver_id).must_equal 2 + expect(trip.driver).must_be_instance_of RideShare::Driver + expect(trip.driver.id).must_equal 2 + + expect(trip.passenger).must_be_instance_of RideShare::Passenger + expect(trip.passenger.id).must_equal 8 + expect(trip.passenger_id).must_equal 8 + + expect(trip.start_time).must_be_instance_of Time + expect(trip.end_time).must_be_nil + + expect(trip.cost).must_be_nil + expect(trip.rating).must_be_nil + end + end end end diff --git a/test/trip_test.rb b/test/trip_test.rb index 2063e28a7..b103a440a 100644 --- a/test/trip_test.rb +++ b/test/trip_test.rb @@ -15,9 +15,15 @@ start_time: start_time, end_time: end_time, cost: 23.45, - rating: 3 + rating: 3, + driver: RideShare::Driver.new( + id: 54, + name: "Test Driver", + vin: "12345678901234567", + status: :AVAILABLE + ) } - @trip = RideShare::Trip.new(@trip_data) + @trip = RideShare::Trip.new(**@trip_data) # ** spreads the hash into named parameters end it "is an instance of Trip" do @@ -29,7 +35,6 @@ end it "stores an instance of driver" do - skip # Unskip after wave 2 expect(@trip.driver).must_be_kind_of RideShare::Driver end @@ -37,9 +42,21 @@ [-3, 0, 6].each do |rating| @trip_data[:rating] = rating expect do - RideShare::Trip.new(@trip_data) + RideShare::Trip.new(**@trip_data) end.must_raise ArgumentError end end + + it "raises an error for invalid time" do + @trip_data[:end_time] = @trip_data[:start_time]-1 + expect do + RideShare::Trip.new(**@trip_data) + end.must_raise ArgumentError + end + + it "calculates duration of trip in seconds" do + expect(@trip.duration_trip).must_equal 1500 + end + end end