Project 3
Objective : Build an object-oriented library which can be used to track automobile maintenance. There can be different car types such as petrol, diesel, gas, electric etc., This library should be able to support at least three of the car types.
Maintenance tasks include activities like oil change or replace oil filter, replace air filter, replace fuel filter, tire rotations, infotainment system debug, replace spark plugs, replace the cabin or a/c filter, check the level and refill clutch fluid or brake fluid, examine belts, wipers, hoses, check the tire conditions, check the charging systems and battery.
Solution: To meet the objective of building an object-oriented library for tracking automobile maintenance, we will implement the following classes and functionalities:
1. Vehicle Class:
- This class serves as a representation of a vehicle and stores information about the make, model, year, and mileage.
- For gaining access to and changing these attributes, it offers getter and setter functions.
- The class also has methods for obtaining vehicle information and checking tire rotation.
2. GasCar, DieselCar, ElectricCar Classes:
- These classes, which represent particular car types based on fuel type (gas, diesel, or electric), inherit from the Vehicle class.
- To retrieve the vehicle type and fuel type, respectively, they implement the virtual functions getType() and getFuelType().
- Additional functions for examining tire rotation and charger power are also included in the ElectricCar class.
3. FuelVehicle Abstract Class:
- This abstract class represents a vehicle with a particular fuel type and derives from the Vehicle class.
- It contains the getFuelType() pure virtual function as well as the checkOil() function.
4. MaintenanceTracker Class:
- The functions to add, update, list, and remove vehicle entries are provided by this class, which also manages the inventory of vehicles.
- It has a vector where pointers to Vehicle objects can be stored.
- The destructor makes sure that memory is allocated properly.
5. Helper Functions:
- getNewMake() handles input validation while obtaining the make of a new vehicle from the user.
- getNewModel() handles input validation while retrieving the model of a new vehicle from the user.
- getNewYear() handles input validation while retrieving the year of a new vehicle from the user.
- getNewOdometer() handles input validation while retrieving the odometer reading of a new vehicle from the user.
- getNewType() handles input validation while obtaining the fuel type for a new vehicle from the user.
- selectCar() handles input validation while letting the user choose a car from the inventory.
- getNewOdometerReading() handles input validation while retrieving the most recent odometer reading for a vehicle from the user.
In the main function (driver code), the MaintenanceTracker object named "tracker" is created to track and manage the vehicles. A menu is displayed to the user, providing options to list inventory, add a vehicle, update a vehicle, remove a vehicle, perform tire rotation, oil change, or recharge.
Code used for the given project 'Car Maintainence Library' -
/*
* Project_03.cpp
*
* Created on: 11-Jul-2023
* Author: sagar
*/
#include <iostream> #include <vector> #include <limits>
// Enum to represent different types of vehicles enum Type { GAS, DIESEL, ELECTRIC };
// Base class for vehicles class Vehicle { protected: std::string make; // Make of the vehicle std::string model; // Model of the vehicle int year; // Year of manufacture int odometer; // Odometer reading in kilometers
public: Vehicle(const std::string& make, const std::string& model, int year, int odometer) : make(make), model(model), year(year), odometer(odometer) {}
std::string getMake() const { return make; } // Get the make of the vehicle
std::string getModel() const { return model; } // Get the model of the vehicle
int getYear() const { return year; } // Get the year of manufacture
int getOdometer() const { return odometer; } // Get the odometer reading
void setOdometer(int newOdometer) { odometer = newOdometer; } // Set the odometer reading
virtual Type getType() const = 0; // Get the type of the vehicle (gas, diesel, electric)
virtual void performMaintenanceTasks() const = 0; // Perform maintenance tasks specific to each vehicle type
};
// GasCar class derived from vehicle class GasCar : public Vehicle { public: GasCar(const std::string& make, const std::string& model, int year, int odometer) : Vehicle(make, model, year, odometer) {}
Type getType() const override { return Type::GAS; } // Get the type of the vehicle (gas)
void performMaintenanceTasks() const override {
checkTireRotation();
// Add gas car-specific maintenance tasks here
}
private: void checkTireRotation() const { // Check if tire rotation is needed based on odometer reading int tireCycle = 50000; // Tire rotation cycle in kilometers int distance = getOdometer() % tireCycle; // Remaining distance for tire rotation int remainder = tireCycle - distance; // Remaining distance until tire rotation is due if (remainder >= 0) std::cout << "Tire rotation is advised.\n"; else std::cout << "Tires are good to go.\n"; } };
// DieselCar class derived from vehicle class DieselCar : public Vehicle { public: DieselCar(const std::string& make, const std::string& model, int year, int odometer) : Vehicle(make, model, year, odometer) {}
Type getType() const override { return Type::DIESEL; } // Get the type of the vehicle (diesel)
void performMaintenanceTasks() const override {
checkTireRotation();
// Add diesel car-specific maintenance tasks here
}
private: void checkTireRotation() const { // Check if tire rotation is needed based on odometer reading int tireCycle = 50000; // Tire rotation cycle in kilometers int distance = getOdometer() % tireCycle; // Remaining distance for tire rotation int remainder = tireCycle - distance; // Remaining distance until tire rotation is due if (remainder >= 0) std::cout << "Tire rotation is advised.\n"; else std::cout << "Tires are good to go.\n"; } };
// ElectricCar class derived from vehicle class ElectricCar : public Vehicle { public: ElectricCar(const std::string& make, const std::string& model, int year, int odometer) : Vehicle(make, model, year, odometer) {}
Type getType() const override { return Type::ELECTRIC; } // Get the type of the vehicle (electric)
void performMaintenanceTasks() const override {
checkTireRotation();
checkPower();
// Add electric car-specific maintenance tasks here
}
private: void checkTireRotation() const { // Check if tire rotation is needed based on odometer reading int tireCycle = 50000; // Tire rotation cycle in kilometers int distance = getOdometer() % tireCycle; // Remaining distance for tire rotation int remainder = tireCycle - distance; // Remaining distance until tire rotation is due if (remainder >= 0) std::cout << "Tire rotation is advised.\n"; else std::cout << "Tires are good to go.\n"; }
void checkPower() const {
// Check if battery recharge is needed based on odometer reading
int powerCycle = 400; // Battery recharge cycle in kilometers
int distance = getOdometer() % powerCycle; // Remaining distance for battery recharge
if (distance == 0)
std::cout << "Battery recharge is advised.\n";
else
std::cout << "Your vehicle is good to go.\n";
}
};
// Class to track and manage vehicles class MaintenanceTracker { public: std::vector<Vehicle*> inventory; // List of vehicles in the inventory
~MaintenanceTracker() {
for (auto& vehicle : inventory)
delete vehicle; // Delete the dynamically allocated vehicles
}
void addVehicle(Vehicle* vehicle) {
inventory.push_back(vehicle); // Add a vehicle to the inventory
}
void listVehicles() const {
for (const auto& vehicle : inventory) {
vehicle->performMaintenanceTasks(); // Perform maintenance tasks for the vehicle
std::cout << "Make: " << vehicle->getMake() << "\n";
std::cout << "Model: " << vehicle->getModel() << "\n";
std::cout << "Year: " << vehicle->getYear() << "\n";
std::cout << "Odometer: " << vehicle->getOdometer() << " km\n";
std::cout << "Fuel Type: " << vehicle->getType() << "\n";
std::cout << "---------------\n";
}
}
void updateVehicle(int index, int newOdometer) {
if (index >= 0 && index < inventory.size()) {
Vehicle* vehicle = inventory[index];
vehicle->performMaintenanceTasks(); // Perform maintenance tasks for the vehicle
vehicle->setOdometer(newOdometer); // Update the odometer reading
std::cout << "Vehicle updated successfully.\n";
} else {
std::cout << "Invalid vehicle index.\n";
}
}
void removeVehicle(int index) {
if (index >= 0 && index < inventory.size()) {
delete inventory[index]; // Delete the dynamically allocated vehicle
inventory.erase(inventory.begin() + index); // Remove the vehicle from the inventory
std::cout << "Vehicle removed successfully.\n";
} else {
std::cout << "Invalid vehicle index.\n";
}
}
};
// Helper functions to get user input std::string getNewMake() { std::string make; std::cout << "Enter vehicle make: "; std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); std::getline(std::cin, make); while (make.empty()) { std::cout << "Make cannot be blank. Enter vehicle make: "; std::getline(std::cin, make); } return make; }
std::string getNewModel() { std::string model; std::cout << "Enter vehicle model: "; std::getline(std::cin, model); while (model.empty()) { std::cout << "Model cannot be blank. Enter vehicle model: "; std::getline(std::cin, model); } return model; }
int getNewYear() { int year; std::cout << "Enter vehicle year: "; std::cin >> year; while (std::cin.fail() || year < 1900 || year > 2100) { std::cout << "Invalid year. Enter vehicle year: "; std::cin.clear(); std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); std::cin >> year; } return year; }
int getNewOdometer() { int odometer; std::cout << "Enter vehicle odometer reading: "; std::cin >> odometer; while (std::cin.fail() || odometer < 0) { std::cout << "Invalid odometer reading. Enter vehicle odometer reading: "; std::cin.clear(); std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); std::cin >> odometer; } return odometer; }
Type getNewType() { int type; std::cout << "Select fuel type:\n"; std::cout << " 0. Gas\n"; std::cout << " 1. Diesel\n"; std::cout << " 2. Electric\n"; std::cout << "Enter fuel type: "; std::cin >> type; while (std::cin.fail() || type < 0 || type > 2) { std::cout << "Invalid fuel type. Enter fuel type: "; std::cin.clear(); std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); std::cin >> type; } return static_cast<Type>(type); }
int selectCar(const MaintenanceTracker& tracker) { int index; std::cout << "Enter vehicle index: "; std::cin >> index; while (std::cin.fail() || index < 0 || index >= tracker.inventory.size()) { std::cout << "Invalid vehicle index. Enter vehicle index: "; std::cin.clear(); std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); std::cin >> index; } return index; }
int getNewOdometerReading() { int newOdometer; std::cout << "Enter new odometer reading: "; std::cin >> newOdometer; while (std::cin.fail() || newOdometer < 0) { std::cout << "Invalid odometer reading. Enter new odometer reading: "; std::cin.clear(); std::cin.ignore(std::numeric_limitsstd::streamsize::max(), '\n'); std::cin >> newOdometer; } return newOdometer; }
int main() { MaintenanceTracker tracker; // Create an instance of MaintenanceTracker to track and manage vehicles
while (true) {
std::cout << "Menu:\n";
std::cout << " 0. Quit.\n";
std::cout << " 1. List inventory.\n";
std::cout << " 2. Add vehicle.\n";
std::cout << " 3. Update vehicle.\n";
std::cout << " 4. Remove vehicle.\n";
int choice;
std::cin >> choice;
if (choice == 0)
break;
switch (choice) {
case 1: {
tracker.listVehicles(); // List all the vehicles in the inventory
break;
}
case 2: {
std::string make = getNewMake(); // Get the make of the new vehicle from the user
std::string model = getNewModel(); // Get the model of the new vehicle from the user
int year = getNewYear(); // Get the year of manufacture of the new vehicle from the user
int odometer = getNewOdometer(); // Get the odometer reading of the new vehicle from the user
Type fuelType = getNewType(); // Get the fuel type of the new vehicle from the user
Vehicle* vehicle = nullptr;
switch (fuelType) {
case Type::GAS:
vehicle = new GasCar(make, model, year, odometer); // Create a gas car object
break;
case Type::DIESEL:
vehicle = new DieselCar(make, model, year, odometer); // Create a diesel car object
break;
case Type::ELECTRIC:
vehicle = new ElectricCar(make, model, year, odometer); // Create an electric car object
break;
}
if (vehicle) {
tracker.addVehicle(vehicle); // Add the new vehicle to the inventory
std::cout << "Vehicle added successfully.\n";
} else {
std::cout << "Invalid fuel type.\n";
}
break;
}
case 3: {
int index = selectCar(tracker); // Get the index of the vehicle to update from the user
int newOdometer = getNewOdometerReading(); // Get the new odometer reading from the user
tracker.updateVehicle(index, newOdometer); // Update the vehicle's odometer reading
break;
}
case 4: {
int index = selectCar(tracker); // Get the index of the vehicle to remove from the user
tracker.removeVehicle(index); // Remove the vehicle from the inventory
break;
}
default:
std::cout << "Invalid choice. Please try again.\n";
}
}
return 0;
}









Logical Explaination:
-
The code starts by incorporating the required libraries and creating an enum named Type to represent the various kinds of vehicles, including GAS, DIESEL, and ELECTRIC.
-
The Vehicle base class is defined next. It includes typical details for cars like the make, model, year, and odometer. These attributes are initialized in the constructor, and the class also declares two pure virtual functions: performMaintenanceTasks() and getType(). These functions are intended to be overridden by derived classes because they are pure virtual.
-
There are three derived classes (GasCar, DieselCar, and ElectricCar) that each represent a different kind of vehicle. These classes offer their own implementations of the virtual functions and derive from the Vehicle base class. Additionally, they have private member functions that perform maintenance checks particular to the respective vehicle types, like checkTireRotation() and checkPower().
-
To track and manage vehicles, a class called MaintenanceTracker is defined. Its inventory, which houses the vehicles added to it, is a vector of pointers to Vehicle objects. To avoid memory leaks, this class' destructor is in charge of erasing dynamically allocated vehicles.
-
The MaintenanceTracker class provides several member functions:
addVehicle(): Adds a vehicle to the inventory vector.
listVehicles(): Lists all vehicles in the inventory vector, performing maintenance tasks and displaying their attributes.
updateVehicle(): Updates the odometer reading of a specific vehicle in the inventory vector.
removeVehicle(): Removes a specific vehicle from the inventory vector. -
To retrieve user input for vehicle attributes like make, model, year, odometer reading, and fuel type, helper functions are defined. These functions take care of input verification and make sure that the values entered are within the desired bounds.
-
The program's entry point is the main() function. To track and control vehicles, it creates a tracker instance of the MaintenanceTracker class.
-
Inside the main loop, the user is presented with a menu of options:
Listing the inventory
Adding a new vehicle
Updating an existing vehicle's odometer reading
Removing a vehicle from the inventory - The MaintenanceTracker class's member functions and the user-input helper functions are used to execute the appropriate action based on the user's selection. For instance, when adding a vehicle, the program asks for details about the vehicle, then, based on the chosen fuel type, creates the appropriate derived class object and adds it to the inventory vector.
-
The program continues to loop until the user selects the option to quit.
-
Once the main loop exits, the program ends.
- Overall, the code uses inheritance, polymorphism, and dynamic memory allocation in an object-oriented manner to model various vehicle types, carry out maintenance tasks particular to each type, and provide a user-friendly interface to manage the vehicles through the MaintenanceTracker class.
Program Output:
Based on the given project, we'll assume a sample interaction with the program.
Enter your choice: 2 (Means User selects option 2 to add a vehicle)

Here, supose user enters the details for a Diesel vehicle: Honda City, 2022, with an odometer reading of 41,000 km.

Now, supose user selects option 2 again to add another vehicle.

Here, supose user enters the details for a Electric vehicle: Tata Nexon, 2019, with an odometer reading of 32,500 km.

Now User selects option 1 to list the inventory

The program displays the inventory with the maintenance recommendations for each vehicle. The Diesel vehicle (Honda City) is advised for tire rotation, and the Electric vehicle (Tata Nexon) is also advised for tire rotation, and this vary with the inputs.

now user selected option 3 to update a vehicle.

User selects the Desiel vehicle (index 1) and provides a new odometer reading of 20,000 km.

Now User selects option 1 to list the inventory after the update.

The updated inventory is displayed. The Electric vehicle (Tata Nexon) now has the new odometer reading, and the maintenance recommendations are shown again as advised for both tire rotation and battery recharge.

User selects option 4 to remove a vehicle.

User selects option 1 to list the inventory after the removal

The inventory now only contains the Electric vehicle (Tata Nexon) since the Diesel vehicle (Honda City) was removed.

User selects option 0 to quit the program.
Explanation:
- The program enables menu interaction and a variety of actions on the inventory.
- Vehicle information, including make, model, year, odometer reading, and fuel type, can be added by the user.
- The software shows the inventory, which includes a list of the vehicles and maintenance advice based on their fuel type and odometer reading.
- The odometer reading of a vehicle can be changed by the user, which starts maintenance checks and updates the inventory.
- By choosing the appropriate index, vehicles can be taken out of the inventory.
- The program updates the inventory or displays the appropriate success/failure messages after each action.
- Until the user chooses the option to exit, the program loops continuously.
Conclusion:
By offering an object-oriented solution for managing and tracking automobile maintenance, the automobile maintenance tracking library project successfully accomplishes its goal. The project includes a central component for managing the vehicle inventory as well as classes for various vehicle types and the maintenance tasks associated with them. The implementation handles user input validation and has a user-friendly interface. The project provides a strong foundation for managing and tracking automobile maintenance, and there is room for future extensions and improvements. Overall, it offers a useful tool for streamlining the processes involved in vehicle maintenance.