In this project, you are required to implement a simulation of a transportation system. The main objective is to analyze the incoming requests provided as a list of input, and carrying out the necessary actions.
There are two types of passengers, discounted and standard, which are able to ride the bus or the train, or drive their own cars to travel. The passengers can refill their travel cards, purchase a car and refuel their cars. Each public transport vehicle has an operating range in the shape of a rectangle. While the bus fare is fixed, the trains charge per stop.
Please note that the program will not require a user interaction during the execution, it parses the input file composed of the sequential travelling operations.
Also, as a significant remark, the signature of the methods and the field names that you are going to implement should be identical with the ones that are specified in this document. If a specific method signature is not enforced by the project description document, you can feel free to implement in your own way (i.e. you can implement extra methods considering your own design choice). However, you should also consider the proper usage of access modifiers for preserving the desired visibility and accessibility throughout the project. In other words, you should not define everything as “public”, which results in a penalty if done so.
• Class Hierarchy and Implementation Details
You are already provided with the following interfaces:
Do not modify the code in these files! You are responsible for all the compilation errors originated from the changes made in any of these classes including the addition or removal of libraries.
In addition, you are given a part of the Main class. You are required to complete the Main class with the instructions given later in this document.
The other files are just empty. Using the fundamentals of the objectoriented programming methodology and the inheritance principles, you are expected to fill in these files in a suitable manner to complete the project. Do not forget that you are free to create new packages, classes or interfaces. However, the class names and properties that are given below should be exactly the same in your projects. Please note that, if you fail to follow this instruction, you do not get any points as your projects will be automatically graded.
Before CMPE 160, there was a single source file and all the functions were implemented in that file. However, in this project, there will be multiple classes that interact with each other during execution. Therefore, before starting the implementation, you are advised to allocate some time to understand the main logic behind the design and the relation among the code pieces.
Within the scope of this project, you are expected to implement these classes (which will be explained in detail in the rest of this document):
The class hierarchy that you must consider during the implementation is illustrated in the class diagram below:
The main method simply reads an input file that is composed of sequential commands related to the travel operations. You can use this class to test your code. Scanners for input and output files and the array lists defined below are given for you.
Main method creates 3 array lists called passengers, vehicles and locations. The first location is created in (0,0) coordinates and added to locations, where the passengers always start at.
You are required to read from an input file and print to an output file, names of which are passed to your program as arguments. Apart from unit tests to test your code and class structure, we will use Main class to test your code for various inputs and outputs.
In the first line, there is a number N, which represents the total number of events that occur during the simulation.
In the following N lines, the actions are specified in their customized format as described below. In other words, each distinct line represents an event with a specific action in the transportation system. Please note that the test cases will not cover any erroneous input file with regards to the format (i.e. passenger type will always be “D” or “S”).
The possible actions are encoded through separate numbers:
- – creating a passenger
- – creating a location
- – creating a public transport vehicle
- – passenger travels to a location
- – passenger purchases a car
- – passenger refuels their car
- – passenger refills their travel card
- When creating a passenger, four or five inputs are given depending on whether the passenger has a car or not. The type of the passenger is given as “D” or “S”, which stand for Discounted and Standard, respectively. Whether the passenger has a driver’s license is given as 0 or 1, 0 being false and 1 being true. Whether the passenger has a car is given as 0 and 1 like before. If the passenger has a car, one more input is given, which is a double type indicating the fuel consumption rate of the car. The ID of a passenger is determined by your simulation and should be unique to each passenger. In other words, no two passengers can have the same ID, even if one of them is a discounted one and the other a standard one. Successive numbers should be assigned as IDs according to the order of adding them to the simulation by starting indexing from 0, such that the first passenger must
have the ID 0 and the second 1 and so on. Example:
- D 1 0 means that you need to create a discounted
passenger who has a driver’s license but no car.
1 S 1 1 0.1 means that you need to create a standard passenger who has a driver’s license and a car that has a fuel consumption rate of 0.1.
- When creating a location, two double inputs are given, which are the x and y coordinates of the location. The IDs of the locations are also determined by your simulation like the
IDs of the passengers.
- 0 50.0 means that you need to create a location with the coordinates (40.0, 50.0).
- When creating a public transport vehicle five inputs are given. The first one is the type of the vehicle, as 1 or 2, where 1 being the bus and 2 being the train. After that, the range of the vehicle is given in 4 double values, in (x1, y1) and (x2, y2) format. The IDs of the vehicles are also determined by your simulation.
- When a passenger wants to travel, three inputs are given. The passenger ID, the location ID, the transportation type. If the type is 3, the passenger drives the personal car. If it is 1 or 2, one more input is given, which is the vehicle ID, and the passenger rides the bus or the train, respectively.
- When a passenger purchases a car, two inputs are given: the passenger ID and the fuel consumption rate of the car to be purchased. Also driver’s license status should be changed to true.
- When a passenger refuels the car, two inputs are given: the passenger ID and the fuel amount in double.
- When a passenger refills the travel card, two inputs are given: the passenger ID and the amount to be added to the travel card in double.
You must print the passengers in the locations list in the main class with their attributes. If a corresponding passenger has a car, you need to print the remaining fuel, otherwise print the remaining balance in the travel card. Please note that the double values should have 2 digits after the fraction point. The output format should be ordered in ascending order of the location IDs, while in each location, the passengers should be also ordered according to their IDs.
A location should be printed as “Location ID: (x, y)”, while a passenger should be printed out as “Passenger ID: <remaining fuel in the car> or <remaining balance of the travel card>” without any angle bracket.
Location 0: (100.00, 200.00)
Passenger 1: 500.00
Passenger 4: 600.00
Passenger 5: 4.19
Location 1: (200.00, 304.00)
Passenger 2: 400.00
Passenger 3: 26.5
Passenger 6: 14.00
Locations 2: (1.00, 1.00)
Passenger 0: 2.11
Location class should have the following variables, exactly named as below:
- int ID
- double locationX
- double locationY
- ArrayList<Passenger> history: keeps track of every passenger who has visited
- ArrayList<Passenger> current: keeps track of the passengers currently here
You must implement these methods, exactly as named below:
- A constructor with three parameters, ID, locationX and locationY.
- A method that calculates the distance between the object
i t s e l f a n d a n o t h e r L o c a t i o n , double
- void incomingPassenger(Passenger p) and void outgoingPassenger(Passenger p) for doing the necessary operations on the history and current lists.
Additionally, the choice of defining the variables as private, protected or public may require additional getter and setter methods.
Passenger should have the following variables, exactly as named below:
- int ID
- boolean hasDriversLicense
- double cardBalance: the passenger’s travel card balance
- Car car
- Location currentLocation
P a s s e n g e r s h o u l d i m p l e m e n t ownCar a n d usePublicTransport interfaces and implement the methods they require. The class should have the following methods, exactly as named below:
- A constructor with three parameters, ID, hasDriversLicense, Location l
- Another constructor for the passengers who have cars, with three parameters, ID, Location l, double fuelConsumption. Their driver’s license status should be initialized as true.
- ride(PublicTransport p, Location l) for the passengers to travel using public transport.
- drive(Location l) for the passengers to use their own cars.
- Methods for the passengers to refill their cards, purchase a car and refuel their cards.
- Note that the actions will not take place unless they meet the necessary conditions.
DiscountedPassenger.java and StandardPassenger.java
They should extend the Passenger class and each have a constructor with three parameters, ID, hasDriversLicense, Location l, and another constructor with three parameters, ID, Location l, double fuelConsumption.
Car should have the following fields:
- int ownerID
- double fuelAmount
- double fuelConsumption
It should have the following methods:
- A constructor with two parameters, ID, fuelConsumption
- void refuel(double amount)
PublicTransport is an abstract class and should have the following fields:
- int ID
- double x1, y1, x2, and y2 as the coordinates of the operation range.
It should have the following methods:
- A constructor with five parameters, ID, and the four coordinates
- canRide(Location departure, Location arrival) to determine if the vehicle is suitable for the journey.
Train.java and Bus.java
They should extend the PublicTransport class. They should have a constructor with five inputs like PublicTransport. Both of them should have a method called getPrice with properties below:
As mentioned before, while the bus fare is fixed at 2 liras regardless of the distance travelled, the trains charge per stop. There are 15 kilometers between every stop and traveling one stop costs 5 liras. You must round the distance down or up (choose which one’s closer to the destination) when calculating how many stops the passenger will travel.
For example, if a passenger will ride the train for a location 40 kms away, they will get off the train after 3 stops.
While the Standard Passengers pay the full price, Discounted Passengers get 50% discount on the bus and 20% discount on the train. You must do the necessary checks in these vehicle classes.