Vehicle Rental Service
Part of the Object Oriented Programming section of Coddy's GDScript journey. Lesson 65 of 65.
Challenge
MediumBuild a vehicle rental service: vehicles of two kinds, rentals, and the agency that manages both. Prices are whole dollars (int).
Vehicle in vehicle.gd:
- The constructor takes
vin,make,modelanddaily_rate;availablestarts astrue. start_rental() -> bool: returnsfalsewhen the vehicle is not available; otherwise marks it unavailable and returnstrue.end_rental()makes it available again._to_string()returnsMAKE MODEL (VIN: VIN) - Available, or- Rentedat the end.
Car in car.gd and Motorcycle in motorcycle.gd extend Vehicle. Their constructors take the four vehicle values plus seats (car) or engine_size (motorcycle). Their _to_string() builds on the parent's text: Car: + vehicle text + - 5 seats, and Motorcycle: + vehicle text + - 600cc.
Rental in rental.gd:
- The constructor takes
rental_id, thevehicleobject,customer_nameanddays;is_activestarts astrue. calculate_cost() -> int: the daily rate times the days.end_rental() -> bool:falsefor a rental that already ended; otherwise ends it, ends the vehicle's rental and returnstrue._to_string():Rental ID: MAKE MODEL for CUSTOMER, D days, $COST - Active, or- Completed.
RentalAgency in rental_agency.gd:
- The constructor takes
agency_name.vehiclesis a dictionary from VIN to vehicle,rentalsa dictionary from rental id to rental, andnext_rental_idstarts at1. add_vehicle(vehicle)stores a vehicle under its VIN.rent_vehicle(vin, customer_name, days) -> String: returns""for an unknown VIN, fewer than1day, or a vehicle that is not available. Otherwise it starts the vehicle's rental, creates aRentalwith the idR1,R2... (the counter goes up only for a successful rental), stores it and returns the id.return_vehicle(rental_id) -> bool:falsefor an unknown id; otherwise returns what the rental'send_rental()returns.available_vehicles() -> Array[Vehicle]: the available vehicles, in the order they were added.total_revenue() -> int: the sum of the costs of all rentals, active or completed.
A rental stores its vehicle, but a vehicle does not store its rental, so no two objects point at each other. For this input:
Speedy Rentals
car C1|Toyota|Camry|50|5
moto M1|Honda|CBR|40|600
rent C1|Ana|3
rent C1|Ben|2
available
kind M1
rentals
revenuethe output is:
Rented C1 as R1: $150
Cannot rent C1
Available at Speedy Rentals:
- Motorcycle: Honda CBR (VIN: M1) - Available - 600cc
M1: Vehicle true, Car false, Motorcycle true
Rental R1: Toyota Camry for Ana, 3 days, $150 - Active
Revenue: $150Your code goes in vehicle.gd, car.gd, motorcycle.gd, rental.gd and rental_agency.gd. main.gd holds the supplied input/output code and cannot be edited.
Try it yourself
extends Node
func _ready():
# Supplied input/output code: keep it as it is
var agency := RentalAgency.new(OS.read_string_from_stdin())
var line := OS.read_string_from_stdin()
while line != "":
var parts := line.split(" ", true, 1)
var f: PackedStringArray = parts[1].split("|") if parts.size() > 1 else PackedStringArray()
match parts[0]:
"vehicle":
agency.add_vehicle(Vehicle.new(f[0], f[1], f[2], int(f[3])))
"car":
agency.add_vehicle(Car.new(f[0], f[1], f[2], int(f[3]), int(f[4])))
"moto":
agency.add_vehicle(Motorcycle.new(f[0], f[1], f[2], int(f[3]), int(f[4])))
"rent":
var rental_id: String = agency.rent_vehicle(f[0], f[1], int(f[2]))
if rental_id == "":
print("Cannot rent ", f[0])
else:
var rental: Rental = agency.rentals[rental_id]
print("Rented %s as %s: $%d" % [f[0], rental_id, rental.calculate_cost()])
"return":
print("Return ", f[0], ": ", agency.return_vehicle(f[0]))
"available":
print("Available at ", agency.agency_name, ":")
for vehicle in agency.available_vehicles():
print("- ", vehicle)
"fleet":
for vin in agency.vehicles:
print(agency.vehicles[vin])
"kind":
var vehicle: Vehicle = agency.vehicles[f[0]]
print("%s: Vehicle %s, Car %s, Motorcycle %s" % [f[0], vehicle is Vehicle, vehicle is Car, vehicle is Motorcycle])
"rentals":
for rental_id in agency.rentals:
print(agency.rentals[rental_id])
"revenue":
print("Revenue: $", agency.total_revenue())
line = OS.read_string_from_stdin()
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe self KeywordMethodsPropertiesConstructor (_init)Recap - Simple Calculator4Polymorphism
Method Overriding RevisitedDuck TypingAbstract Classes and MethodsInterface DesignRecap - Shape Calculator2Class Properties
Instance vs Static VariablesStatic FunctionsProperty SettersProperty GettersPrivate by ConventionRecap - Bank Account Manager5Encapsulation
Public and Private MembersValidation with SettersInformation HidingRead-Only PropertiesRecap - Student Records System8Advanced OOP Concepts
Composition vs InheritanceInner ClassesNodes as ComponentsRefCounted vs NodeEnums in Classes11Project: Library Management
Project OverviewBook and User Classes3Inheritance
Basic InheritanceThe super KeywordMethod OverridingInheritance ChainsType Checks with isRecap - Employee Hierarchy6Special Methods
Virtual Methods IntroductionThe _to_string MethodCustom IteratorsRecap - Custom List9Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy PatternPractice on your own: Online GDScript compiler