Hello, dear friend, you can consult us at any time if you have any questions, add WeChat: daixieit

ASSIGNMENT 04

CAR RENTAL SYSTEM

Due Date:

April 5, 2024 23:55:59

1 Introduction

In this assignment, you will practice the following programming concepts:

Creating classes and functions.

Using data structures (e.g. Dictionary, Set, List).

writing to files.

Applying exception handling.

Adhering to specifications.

Applying programming concpets learned in the course so far (e.g. if, for, while, etc.)

In this assignment, you are asked to develop a menu-driven program that represents a car rental system. This car rental system consists of three classes: Company, Customer, and Vehicle.

In addition to the three classes, you will also implement a function named start() that is the entry point for your program. The function start() does not take any parameters and does not return anything.

All your code will be in one file named car.py .

Invoke the function start() in the global scope of car.py , so that when the file is executed, by running the terminal command python car.py, the function start() is called and the program starts.

The function start() is responsible for displaying a menu that offers users several options to choose from and handling the user's input.

The specifications of the three classes and the start() function are provided below. You are also allowed to add any other functions you need to implement the menu options.

ASSIGNMENT WALKTHROUGH!

The following video provides a demo of the menu-driven program that you are required to implement in this assignment. In the demo, the car.py file is executed and all the available menu options are tested before a summary is written to a file named summary.txt

NOTES

1 In this assignment, the term "method" refers to a class function, while the term "function" refers to a function that exists independently (not associated with a class).

2 Adhere precisely to the provided names for classes, variables, methods, and functions. Capitalize the first character of class names, while keeping the names of functions, methods, and variables in lowercase.

3 All class attributes/variables are private, and should be accessed only with setter and getter functions.

4 You are not allowed to import any python library in this assignment.

5 Kindly note that since this assignment has interconnected components, you may want to read it more than once.

2 Required File

For this assignment, you are asked to submit one file named car.py containing the implementation of the three classes: Company, Customer, and Vehicle, and the start() function described below. You may add additional functions to facilitate your implementation. However, only the start() should be invoked/called in the global scope of the file.

Company class

The Company class represents a Car Rental company. It stores a dictionary of Vehicle objects, vehicles can be added to a Company object using the add_vehicle() method. The Company class also has a list of customers. A company can rent a vehicle to a customer using the rent_vehicle() method, and the customer will be able to return a rented vehicle using the Customer's return_rented_vehicle() method.

Attributes

_name: (type: string) The name of the company.

_income: (type: float) The total income of the company.

_vehicles: (type: dictionary) A dictionary of all vehicles in the company. Each item stores a Vehicle object where the key is the _vin of the vehicle and the value is the corresponding Vehicle object.

_customers: (type: list) A list of all customers in the company. Each element is a Customer object.

Methods

__init__(self, name): The constructor takes one parameter: name. The constructor initializes all its attributes. The _name attribute is assigned the given parameter: name, the _income attribute is set to 0.0, the

_vehicles attribute is initialized to an empty dictionary, and the _customers attribute is set to an empty list.

get_name(self): This method takes no parameters and returns the _name attribute of the company.

get_income(self): This method takes no parameters and returns the _income attribute of the company.

get_customers(self): This method takes no parameters and returns the _customers list.

get_vehicles(self): This method takes no parameters and returns the _vehicles dictionary.

set_name(self, name): This method takes a string representing a name as a parameter and sets the _name attribute to the given name parameter.

set_income(self, income): This method takes a float representing an income as a parameter and sets the _income attribute to the given income parameter.

set_customers(self, customers): This method takes a list of Customer objects as a parameter and sets the _customers attribute to the given list of customers.

set_vehicles(self, vehicles): This method takes a dictionary of Vehicle obejcts as a parameter and sets the _vehicles attribute to the given dictionary of vehicles.

add_to_income(self, value): This method takes a float representing a value as a parameter and adds it to the _income attribute.

add_vehicle(self, vehicle): This method takes a Vehicle object as a parameter and adds it to the _vehicles dictionary. When adding a Vehicle object, the key is the _vin attribute of the vehicle parameter and the value is the vehicle parameter.

add_customer(self, customer): This method takes a Customer object as a parameter and adds it to the _customers list.

This method returns a boolean value (True or False). The method checks if there is a Customer object in the _customers list whose _name attribute matches the given name of the given customer parameter. If a customer with a matching _name is not found, the method adds the customer parameter to the _customers list and returns True. If a customer with a matching _name is found, the method does not add the customer to the _customers list and returns False.

rent_vehicle(self, customer_name, vin, rental_duration): This method takes three parameters: customer_name, vin, and rental_duration, and returns a boolean value (True or False)

The customer_name is a string representing the name of a customer that must exist in the _customers list. The method checks if there is a Customer object in the _customers list whose _name attribute matches the given customer_name. If a customer with a matching _name is not found, the method returns False.

The vin parameter is a string representing the VIN of the vehicle to be rented. The method checks if there is a Vehicle object in the _vehicles dictionary whose _vin matches the given VIN, and that the vehicle is avaiable for rent. If the vehicle is not found or is not available, the method returns False.

The rental_duration parameter is an integer representing the number of days the vehicle will be rented for.

If the customer is found in the _customers list, the vehicle is found in the _vehicles dictionary, and the vehicle is available, the method performs the following three steps and then returns True.

Update the vehicle's _available attribute to False.

Calculates the revenue of the rental by multiplying the rental_duration parameter by the vehicle's _rental_rate attribute, and adds the revenue to the company's _income attribute.

Adds the vehicle to the customer's _rented_vehicles dictionary using the vehicle's _vin attribute as the key.

get_summary(self, file_name): This method takes a string representing a file name as an argument and returns nothing. It will create a new text file and write a summary about the company to this file whose name is the given parameter: file_name. The summary written in the text file is used to test the correctness of your solution. Therefore, the implementation of this method is provided for you in order to ensure that the output generated by the get_summary() method is standardized. Do not change the implementation of the get_summary() method which is given in the starter code. customers and vehicles are written in the file with the same order they were added to the company.

Usage Notes

Once a vehicle is rented, it is no longer available for rent until it is returned.

Vehicle class

The Vehicle class represents an individual vehicle. It encapsulates essential attributes such as the vehicle's model, rental rate, VIN (Vehicle Identification Number), and availability status. Additionally, it contains a class variable called _vin_set which collects the _vin attributes of all the Vehicle objects created so far to prevent the creation of more than one Vehicle object with the same VIN.

Attributes

_vin: (type: string) The Vehicle Identification Number of the vehicle. No two vehicles can have the same Vehicle Identification Number.

_vin_set: (type: set) A class variable of type set used to store all the _vin attributes of the previously created Vehicle objects.

_model: (type: string) The model of the vehicle.

_rental_rate: (type: float) The daily rental rate of the vehicle in CAD/day.

_available: (type: boolean) A boolean value indicating whether the vehicle is available for rent or not. Default value is True.

Methods

__init__(self, model, rental_rate, vin, available=True): The constructor takes four parameters: model, rental_rate, vin, and available. The constructor initializes the _model, _rental_rate, and _available attributes using the given parameters. The available parameter is assigned the value True by default in the parameters list. The constructor does not initialize the _vin attribute; instead, the constructor calls the _validate_vin() method and passes the given vin parameter to it. The _vin attribute is initialized by the _validate_vin() method after checking that the given vin is valid. If the given vin is found to be invalid, the _validate_vin() method raises a ValueError, and the constructor does not complete successfully, thus preventing the Vehicle object from being created.

_validate_vin(self, vin): This private method is invoked by the constructor to assess the format and uniqueness of the provided vin parameter. It takes a string representing a VIN of a vehicle as a parameter and has no return value. The method initializes the _vin attribute using the parameter vin and adds the parameter vin to the _vin_set set if the provided vin is valid; otherwise, it raises a ValueError and displays an error message (Refer to the Usage Notes section below for the specific conditions defining a valid VIN and the error messages to be dispalyed).

get_model(self): This method takes no parameters and returns the _model of the vehicle.

get_rental_rate(self): This method takes no parameters and returns the _rental_rate of the vehicle.

get_vin(self): This method takes no parameters and returns the _vin variable of the vehicle.

get_available(self): This method takes no parameters and returns the _available variable of the vehicle.

set_model(self, model): This method takes a string representing a model as a parameter and sets the _model attribute to the given model.

set_rental_rate(self, rental_rate): This method takes a float representing a rental rate as a parameter and sets the _rental_rate attribute to the given rental_rate.

set_available(self, available): This method takes a boolean representing an availability status as a parameter and sets the _available attribute to the given availability status.

Usage Notes

_vin_set is a class variable of type set and it is used to store all the _vin attributes of the previously created Vehicle objects. To ensure that no two vehicles can have the same VIN, when a new Vehicle object is being created, its constructor (__init__()) will not complete successfully if vin is not valid. The private method _validate_vin() will be called by __init__() to check if the provided VIN is valid. A VIN is valid if the following two conditions are True:

It is a string of length == 6 and contains only alphanumeric characters (e.g. 432hj4, 234222 are both valid). If this condition is False, the _validate_vin() raises a ValueError("Invalid VIN format. VIN must be a string with 6 characters that can be either digits or letters")

The provided VIN is not in the _vin_set set variable. If this condition is False, the method _validate_vin() raises a ValueError("VIN must be unique. Another vehicle with the same VIN already exists.")

If the previous two conditions are both False, a ValueError is raised and either of the two error messages is displayed.

Within a class, variables fall into two categories: class variables and instance variables. A class variable is shared among all instances of the class, whereas an instance variable is unique to each object. Class variables hold values that are common across all instances. All variables within the three classes are instance variables, except for _vin_set, which is a class variable in the Vehicle class. It serves to store all _vin attributes from created Vehicle instances, ensuring that no two Vehicle objects share the same _vin.

Customer class

The Customer class represents a customer of the car rental company.

Attributes

_name: (type: string) The name of the customer.

_phone_number: (type: string) The phone number of the customer. A string of length 10 that contains digits only.

_rented_vehicles: (type: dictionary) A dictionary that contains all the vehicles currently rented by the customer. Each item stores a Vehicle object where the key is the _vin attribute of the Vehicle, and the value is the Vehicle object.

Methods

__init__(self, name, phone_number): The constructor takes two parameters: _name and _phone_number. The constructor initializes the _name and _phone_number attributes. The _rented_vehicles attribute is initialized to an empty dictionary. You do not need to check the validity of the given _phone_number, assume it is valid.

get_name(self): This method takes no parameters and returns the _name attribute of the customer.

get_phone_number(self): This method takes no parameters and returns the _phone_number attribute of the customer.

get_rented_vehicles(self): This method takes no parameters and returns the _rented_vehicles dictionary.

set_name(self, name): This method takes a string representing a name as a parameter and sets the _name attribute to the given name.

set_phone_number(self, phone_number): This method takes a string representing a phone number as a parameter and sets the _phone_number attribute to the given phone_number parameter.

add_rented_vehicle(self, vehicle): This method takes a Vehicle object as a parameter and adds it to the _rented_vehicles dictionary. The key is the _vin attribute of the vehicle and the value is the vehicle.

return_rented_vehicle(self, vin): This method takes a string representing a VIN as a parameter and returns a boolean. The method searches for a Vehicle object in the _rented_vehicles dictionary whose _vin attribute matches the given vin. If the vehicle was found, the available variable of that vehicle is set to True before the vehicle is removed from the _rented_vehicles dictionary, then the method returns True. If no Vehicle object with a matching _vin exists in the _rented_vehicles dictionary, the method returns False.

Usage Notes

There is no method to rent a vehicle in the Customer class. A vehicle can be rented to a customer using the rent_vehicle() method of the Company class.

Start() Function

The start() function is the entry point for your program. It starts by creating a Company object with the name "Pythonic Car Rental Company" (Do not change the company name). It then displays a menu that offers the user several options to choose from and handles the user's inputs. The start() function takes no parameters and does not return anything. The function should be invoked once in the global scope of the file.

The function should display the following menu (in the same order):

1: Add a new vehicle.

2: Add a new customer.

3: Rent a vehicle.

4: Return a rented vehicle.

5: Print summary.

6: Exit.

The user can select one option at a time by typing the number of the option. The valid options are 1, 2, 3, 4, 5, and 6. If the user enters an invalid option, the following warning message is printed: "Invalid choice. Please enter a number between 1 and 6.", and the menu is displayed again.

1: Add a new vehicle

When the user selects option 1, the user is asked to enter the following information about the vehicle:

model: A string representing the model of the vehicle.

rental_rate: A float representing the daily rental rate of the vehicle.

vin: A string representing the VIN of the vehicle.

These three pieces of information are entered as strings at first, using the input() built-in function. The given rental_rate is then converted to a float.

When converting the user's input to the appropriate data type, you should use the appropriate built-in function (e.g. float(), int(), etc.). Make sure you handle any exceptions that may occur when converting the user's input to the appropriate data type.

If the conversion fails, the raised ValueError is handeled (using try/except) and the error message associated with the ValueError is displayed, then the main menu is displayed again. If the conversion succeeds, the start() function attempts to create a Vehicle object and passes the three pieces of information. Then, the created Vehicle object is added to the Company object using the add_vehicle() method. Finally, the message "Vehicle added successfully!" is printed, and the main menu is displayed again.

Remember that the _vin attribute of the Vehicle object must be unique and have the right format. If the vin variable provided by the user is not valid, the Vehicle object will not be created and will raise a ValueError. The raised error must be handeled (using try/except) and the associated error message is displayed. The main menu is then displayed again.

2: Add a new customer

When the user selects option 2, the user is asked to enter the following information about the customer:

name: A string representing the name of the customer.

phone_number: A string representing the phone number of the customer.

You do not need to check the validity of the provided phone_number or convert it to an integer. Check that the given phone_number is valid. A valid phone_number has a length of 10 and contains digits only. If the provided phone_number is invalid, the message "Invalid phone number. Phone number must be 10 digits." is displayed and the main menu is displayed.

After validating the phone_number, a Customer object is created using the two pieces of information and the add_customer() method of the Company object is called and the created Customer object as a parameter.

If add_customer() returns True, the message "Customer added successfully." is displayed to the user. Otherwise, the message "Customer already exists." is displayed.

3: Rent a vehicle

When the user selects option 3, the user is asked to enter the following information about the rental:

customer_name: A string representing the name of the customer.

vin: A string representing the VIN of the vehicle.

rental_duration: An int representing the number of days the vehicle will be rented for.

These three pieces of information are entered as strings at first, using the input() built-in function. The rental duration is converted to an int.

When converting the user's input to the appropriate data type, you should use the appropriate built-in function (e.g. float(), int(), etc.). Make sure you handle any exceptions that may occur when converting the user's input to the appropriate data type.

If the conversion fails, the raised ValueError is handeled (using try/except) and the error message associated with the ValueError is displayed, then the main menu is displayed again. If the conversion succeeds, the rent_vehicle() method of the Company object is called, and the given three pieces of information are passed to it as parameters.

If rent_vehicle() returns True, the message "Vehicle rented successfully." is displayed to the user. Otherwise, the message "Failed to rent the vehicle." is displayed.

4: Return a rented vehicle

When the user selects option 4, the user is asked to enter the following information about the return:

customer_name: A string representing the name of the customer who will return a vehicle that he rented before.

vin: A string representing the VIN of the vehicle.

The start() function will look for a customer in the company _customers list with a name that matches the given customer_name.

If a customer with a matching _name is not found, the message "Customer not found." is displayed and the main menu is displayed again. If the customer is found, the return_rented_vehicle() method of that customer is called, and the given VIN is passed as a parameter.

If return_rented_vehicle() returns True, the message "Vehicle returned successfully." is displayed to the user. Otherwise, the message "Failed to return the vehicle." is displayed.

5: Print summary

When the user selects option 5, the user is asked to enter the following information:

file_name: A string representing a name of a txt file that the summary is written to (e.g., summary.txt).

If the provided file_name does not end with ".txt", ".txt" is appended to file_name before it is passed as a parameter to get_summary(). For example, if file_name == "summary", it becomes "summary.txt"

The get_summary() method of the Company object is called, and the file_name is passed as a parameter.

If the provided file_name is for a file that already exists, it should be overwritten. Otherwise, a new file is created, and the summary is written to it.