-
-
Save Eldres/478eea2f76d49d8d8fb0 to your computer and use it in GitHub Desktop.
Write a program to simulate the behavior of a self-serve gas station. The goal of this simulation is to collect statistical information of the gas station’s cars and gas pumps. A gas station consists of several pumps and a car waiting line (i.e. a car queue). In each time unit, at most one new car arrives at the gas station. If the car waiting l…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// DO NOT ADD NEW METHODS OR DATA FIELDS! | |
package PJ3; | |
class Car { | |
private int carId; | |
private int serviceDuration; | |
private int arrivalTime; | |
Car() { | |
} | |
Car(int CID, int serviceTime, int arriveTime) { | |
// add statements | |
this.carId = CID; | |
this.serviceDuration = serviceTime; | |
this.arrivalTime = arriveTime; | |
} | |
int getServiceDuration() { | |
// add statements | |
return serviceDuration; | |
} | |
int getArrivalTime() { | |
// add statements | |
return arrivalTime; | |
} | |
int getCarId() { | |
return carId; | |
} | |
public String toString() { | |
return "" + carId + ":" + serviceDuration + ":" + arrivalTime; | |
} | |
public static void main(String[] args) { | |
// quick check! | |
Car mycar = new Car(20, 30, 40); | |
System.out.println("Car Info:" + mycar); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// DO NOT ADD NEW METHODS OR DATA FIELDS! | |
package PJ3; | |
class GasPump { | |
// start time and end time of current interval | |
private int startIntervalTime; | |
private int endIntervalTime; | |
// pump id and current car which is served by this gas pump | |
private int pumpId; | |
private Car currentCar; | |
// for keeping statistical data | |
private int totalFreeTime; | |
private int totalBusyTime; | |
private int totalCars; | |
// Constructor | |
GasPump() { | |
// add statements | |
this.startIntervalTime = 0; | |
this.endIntervalTime = 0; | |
this.pumpId = 0; | |
this.currentCar = null; | |
this.totalFreeTime = 0; | |
this.totalBusyTime = 0; | |
this.totalCars = 0; | |
} | |
// Constructor with gas pump id | |
GasPump(int gasPumpId) { | |
// add statements | |
this.pumpId = gasPumpId; | |
this.startIntervalTime = 0; | |
this.endIntervalTime = 0; | |
this.currentCar = null; | |
this.totalFreeTime = 0; | |
this.totalBusyTime = 0; | |
this.totalCars = 0; | |
} | |
// accessor methods | |
int getPumpId() { | |
return pumpId; | |
} | |
Car getCurrentCar() { | |
// add statements | |
return currentCar; | |
} | |
// need this to setup priority queue for Busy pumps | |
int getEndIntervalTime() { | |
// return end time of busy interval | |
// add statements | |
return endIntervalTime; | |
} | |
// State transition : FREE interval -> BUSY interval: | |
void switchFreeToBusy(Car currentCar, int currentTime) { | |
// Main goal : switch from free interval to busy interval | |
// | |
// end free interval, start busy interval | |
// steps : update totalFreeTime | |
// set Busy interval - startIntervalTime , endIntervalTime, currentCar, | |
// update totalCars | |
// add statements | |
totalFreeTime += currentTime - startIntervalTime; | |
this.currentCar = currentCar; | |
startIntervalTime = currentTime; | |
endIntervalTime = startIntervalTime + currentCar.getArrivalTime(); | |
totalCars++; | |
} | |
// State transition : BUSY interval -> FREE interval: | |
Car switchBusyToFree() { | |
// Main goal : switch from busy interval to free interval | |
// | |
// end busy interval, start free interval | |
// steps : update totalBusyTime | |
// set Free interval - startIntervalTime | |
// return currentCar | |
// add statements | |
totalBusyTime += endIntervalTime - startIntervalTime; | |
startIntervalTime = endIntervalTime; | |
Car tempCar = currentCar; | |
this.currentCar = null; | |
return tempCar; | |
} | |
// use this method at the end of simulation to update gas pump data in free | |
// and busy queues | |
void setEndSimulationTime(int endsimulationtime, int intervalType) | |
{ | |
// for end of simulation | |
// set endIntervalTime to endsimulationtime, | |
// for FREE interval, update totalFreeTime | |
// for BUSY interval, update totalBusyTime | |
// add statements | |
endIntervalTime = endsimulationtime; | |
if (intervalType == 1) { | |
totalFreeTime += endIntervalTime - startIntervalTime; | |
} else { | |
totalBusyTime += endIntervalTime - startIntervalTime; | |
} | |
} | |
// functions for printing statistics : | |
void printStatistics() { | |
// print gasPump statistics, see project statement | |
System.out.println("\tGasPump ID : " + pumpId); | |
System.out.println("\tTotal free time : " + totalFreeTime); | |
System.out.println("\tTotal service time : " + totalBusyTime); | |
System.out.println("\tTotal # of cars : " + totalCars); | |
if (totalCars > 0) | |
System.out.format("\tAverage service time : %.2f%n\n", | |
(totalBusyTime * 1.0) / totalCars); | |
} | |
public String toString() { | |
return "GasPump:" + pumpId + ":" + startIntervalTime + "-" | |
+ endIntervalTime + ":Car:" + currentCar; | |
} | |
public static void main(String[] args) { | |
Car mycar = new Car(15, 30, 40); | |
GasPump mypump = new GasPump(5); | |
mypump.switchFreeToBusy(mycar, 45); | |
System.out.println(mypump); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package PJ3; | |
import java.util.*; | |
//-------------------------------------------------------------------------- | |
// | |
// Define simulation queues in a gas station. Queues hold references to Car & | |
// GasPump objects | |
// | |
// Car (FIFO) queue is used to hold waiting cars. If the queue is too long | |
// (i.e. > carQSizeLimit), car goes away without entering car queue | |
// | |
// There are several gas pumps in a gas station. Use PriorityQueue to | |
// hold BUSY gas pumps and FIFO queue to hold FREE gas pumps, | |
// i.e. a pump that is FREE for the longest time should start be used first. | |
// | |
// To handle gasPump in PriorityQueue, we need to define comparator | |
// for comparing 2 gasPump objects. Here is a constructor from Java API: | |
// | |
// PriorityQueue(int initialCapacity, Comparator<? super E> comparator) | |
// | |
// For priority queue, the default compare function is "natural ordering" | |
// i.e. for numbers, minimum value is returned first | |
// | |
// User can define own comparator class for PriorityQueue. | |
// For GasPump objects, we like to have smallest end busy interval time first. | |
// | |
// The following class define compare() for two busy gas pumps : | |
class BusyGasPumpComparator implements Comparator<GasPump> { | |
// override compare() method | |
public int compare(GasPump o1, GasPump o2) { | |
return o1.getEndIntervalTime() - o2.getEndIntervalTime(); | |
} | |
} | |
// DO NOT ADD NEW METHODS OR DATA FIELDS | |
class GasStation { | |
// Private data fields: | |
// define one priority queue | |
private PriorityQueue<GasPump> busyGasPumpQ; | |
// define two FIFO queues | |
private Queue<Car> carQ; | |
private Queue<GasPump> freeGasPumpQ; | |
// define car queue size limit | |
private int carQSizeLimit; | |
// Constructor | |
public GasStation() { | |
// add statements | |
} | |
// Constructor | |
public GasStation(int numGasPumps, int carQlimit, int startGasPumpID) { | |
// use ArrayDeque to construct FIFO queue objects | |
carQ = new ArrayDeque<Car>(); | |
freeGasPumpQ = new ArrayDeque<GasPump>(); | |
// construct PriorityQueue object | |
// override compare() in Comparator to compare busy GasPump objects | |
busyGasPumpQ = new PriorityQueue<GasPump>(numGasPumps, | |
new BusyGasPumpComparator()); | |
// initialize carQlimit | |
// Construct GasPump objects and insert into FreeGasPumpQ | |
// add statements | |
this.carQSizeLimit = carQlimit; | |
for (int i = startGasPumpID; i < startGasPumpID+numGasPumps; i++) { | |
freeGasPumpQ.add(new GasPump(i)); | |
} | |
} | |
public GasPump removeFreeGasPumpQ() { | |
// remove and return a free gasPump | |
// Add statements | |
return freeGasPumpQ.poll(); | |
} | |
public GasPump removeBusyGasPumpQ() { | |
// remove and return a busy gasPump | |
// Add statements | |
return busyGasPumpQ.poll(); | |
} | |
public Car removeCarQ() { | |
// remove and return a car | |
// Add statements | |
return carQ.remove(); | |
} | |
public void insertFreeGasPumpQ(GasPump gasPump) { | |
// insert a free gasPump | |
// Add statements | |
freeGasPumpQ.add(gasPump); | |
} | |
public void insertBusyGasPumpQ(GasPump gasPump) { | |
// insert a busy gasPump | |
// Add statements | |
busyGasPumpQ.add(gasPump); | |
} | |
public void insertCarQ(Car car) { | |
// insert a car | |
// Add statements | |
carQ.add(car); | |
} | |
public boolean emptyFreeGasPumpQ() { | |
// is freeGasPumpQ empty? | |
// Add statements | |
return freeGasPumpQ.isEmpty(); | |
} | |
public boolean emptyBusyGasPumpQ() { | |
// is busyGasPumpQ empty? | |
// Add statements | |
return busyGasPumpQ.isEmpty(); | |
} | |
public boolean emptyCarQ() { | |
// is carQ empty? | |
// Add statements | |
return carQ.isEmpty(); | |
} | |
public int numFreeGasPumps() { | |
// get number of free gasPumps | |
// Add statements | |
if (freeGasPumpQ.isEmpty()) { | |
return 0; | |
} else { | |
return freeGasPumpQ.size(); | |
} | |
} | |
public int numBusyGasPumps() { | |
// get number of busy gasPumps | |
// Add statements | |
if (busyGasPumpQ.isEmpty()) { | |
return 0; | |
} else { | |
return busyGasPumpQ.size(); | |
} | |
} | |
public int numWaitingCars() { | |
// get number of cars | |
// Add statements | |
if (carQ.isEmpty()) { | |
return 0; | |
} else { | |
return carQ.size(); | |
} | |
} | |
public GasPump getFrontBusyGasPumpQ() { | |
// get front of busy gasPumps | |
// "retrieve" but not "remove" | |
// Add statements | |
return busyGasPumpQ.peek(); | |
} | |
public boolean isCarQTooLong() { | |
// is carQ too long? | |
// Add statements | |
if ((!carQ.isEmpty() == false) && (carQ.size() >= carQSizeLimit)) { | |
return true; | |
}else{ | |
return false; | |
} | |
} | |
public void printStatistics() { | |
System.out.println("\t# waiting cars : " + numWaitingCars()); | |
System.out.println("\t# busy gas pumps : " + numBusyGasPumps()); | |
System.out.println("\t# free gas pumps : " + numFreeGasPumps()); | |
} | |
public static void main(String[] args) { | |
GasStation sc = new GasStation(4, 5, 1001); | |
Car c1 = new Car(1, 18, 10); | |
Car c2 = new Car(2, 33, 10); | |
Car c3 = new Car(3, 21, 10); | |
Car c4 = new Car(3, 37, 10); | |
sc.insertCarQ(c1); | |
sc.insertCarQ(c2); | |
sc.insertCarQ(c3); | |
System.out.println("" + sc.carQ); | |
System.out.println("Remove car:" + sc.removeCarQ()); | |
System.out.println("Remove car:" + sc.removeCarQ()); | |
System.out.println("Remove car:" + sc.removeCarQ()); | |
System.out.println("" + sc.freeGasPumpQ); | |
GasPump p1 = sc.removeFreeGasPumpQ(); | |
GasPump p2 = sc.removeFreeGasPumpQ(); | |
GasPump p3 = sc.removeFreeGasPumpQ(); | |
GasPump p4 = sc.removeFreeGasPumpQ(); | |
System.out.println("Remove free gas pump:" + p1); | |
System.out.println("Remove free gas pump:" + p2); | |
System.out.println("Remove free gas pump:" + p3); | |
System.out.println("Remove free gas pump:" + p4); | |
p1.switchFreeToBusy(c1, 13); | |
p2.switchFreeToBusy(c2, 13); | |
p3.switchFreeToBusy(c3, 13); | |
p4.switchFreeToBusy(c4, 13); | |
sc.insertBusyGasPumpQ(p1); | |
sc.insertBusyGasPumpQ(p2); | |
sc.insertBusyGasPumpQ(p3); | |
sc.insertBusyGasPumpQ(p4); | |
System.out.println("" + sc.busyGasPumpQ); | |
p1 = sc.removeBusyGasPumpQ(); | |
p2 = sc.removeBusyGasPumpQ(); | |
p3 = sc.removeBusyGasPumpQ(); | |
p4 = sc.removeBusyGasPumpQ(); | |
System.out.println("Remove busy gas pump:" + p1); | |
System.out.println("Remove busy gas pump:" + p2); | |
System.out.println("Remove busy gas pump:" + p3); | |
System.out.println("Remove busy gas pump:" + p4); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package PJ3; | |
import java.util.*; | |
import java.io.*; | |
// You may add new functions or data in this class | |
// You may modify any functions or data members here | |
// You must use Car, GasPump and GasStation | |
// to implement your simulator | |
class GasStationSimulation { | |
// input parameters | |
private int numGasPumps, carQSizeLimit; | |
private int simulationTime, dataSource; | |
private int chancesOfArrival, maxDuration; | |
// statistical data | |
private int numGoAway, numServed, totalWaitingTime; | |
// internal data | |
private int carIdCounter; | |
private GasStation gasStationObj; // Gas station object | |
private Scanner dataFile; // get car data from file | |
// private Random dataRandom; // get car data using random function | |
// most recent car arrival info, see getCarData() | |
private boolean anyNewArrival; | |
private int serviceDuration; | |
Random rand = new Random(); // get car data using random function | |
// initialize data fields | |
private GasStationSimulation() { | |
numGasPumps = 0; | |
carQSizeLimit = 0; | |
simulationTime = 0; | |
dataSource = 0; | |
chancesOfArrival = 0; | |
maxDuration = 0; | |
numGoAway = 0; | |
numServed = 0; | |
totalWaitingTime = 0; | |
carIdCounter = 0; | |
gasStationObj = null; | |
dataFile = null; | |
anyNewArrival = false; | |
serviceDuration = 0; | |
} | |
private void getUserParameters() { | |
// read input parameters from user | |
// setup dataFile or dataRandom | |
Scanner input = new Scanner(System.in); | |
System.out.println("Enter simulation time: "); | |
do { | |
simulationTime = input.nextInt(); | |
} while (simulationTime < 1 || simulationTime > 10000); | |
System.out.println("Enter maximum service time of cars: "); | |
do { | |
maxDuration = input.nextInt(); | |
} while (maxDuration < 1 || maxDuration > 5000); | |
System.out.println("Enter chances (0% < & <= 100%) of new car: "); | |
do { | |
chancesOfArrival = input.nextInt(); | |
} while (chancesOfArrival < 1 || chancesOfArrival > 100); | |
System.out.println("Enter the number of gas pumps: "); | |
do { | |
numGasPumps = input.nextInt(); | |
} while (numGasPumps < 1 || numGasPumps > 10); | |
System.out.println("Enter car queue size limit: "); | |
do { | |
carQSizeLimit = input.nextInt(); | |
} while (carQSizeLimit < 1 || carQSizeLimit > 50); | |
System.out.println("Enter 1/0 to get data from file/rand(): "); | |
do { | |
dataSource = input.nextInt(); | |
} while (dataSource < 0 || dataSource > 1); | |
/* | |
* this will ask the user to enter the filename, then checks if the | |
* filename chosen by the user exists | |
*/ | |
if (dataSource == 1) { | |
System.out.println("Enter filename: "); | |
String file; | |
Scanner keyboard = new Scanner(System.in); | |
file = keyboard.nextLine(); | |
try { | |
dataFile = new Scanner(new File(file)); | |
} catch (FileNotFoundException e) { | |
System.out.println("Error opening file: " + file); | |
} | |
keyboard.close(); | |
} | |
input.close(); | |
} | |
// this method is called for each unit simulation time | |
private void getCarData() { | |
// get next car data : from file or random number generator | |
// set anyNewArrival and serviceDuration | |
if (dataSource == 1) { | |
int data1 = dataFile.nextInt(); | |
int data2 = dataFile.nextInt(); | |
anyNewArrival = (((data1 % 100) + 1) <= chancesOfArrival); | |
serviceDuration = (data2 % maxDuration) + 1; | |
} else { | |
anyNewArrival = ((rand.nextInt(100) + 1) <= chancesOfArrival); | |
serviceDuration = rand.nextInt(maxDuration) + 1; | |
} | |
} | |
private void doSimulation() { | |
// Initialize GasStation | |
gasStationObj = new GasStation(numGasPumps, carQSizeLimit, 1); | |
// Time driver simulation loop | |
for (int currentTime = 0; currentTime < simulationTime; currentTime++) { | |
System.out.println("Time " + currentTime); | |
// Step 1: any new car enters the gas station? | |
getCarData(); | |
if (anyNewArrival) { | |
// Step 1.1: setup car data | |
// Step 1.2: check car waiting queue too long? | |
carIdCounter++; | |
Car newCar = new Car(carIdCounter, serviceDuration, currentTime); | |
System.out.println("\tCar #" + carIdCounter | |
+ " arrives with duration " | |
+ newCar.getServiceDuration() + " units."); | |
if (gasStationObj.isCarQTooLong()) { | |
System.out.println("\tCar Queue is too long: Car #" | |
+ carIdCounter + " leaves the queue."); | |
numGoAway++; | |
} else { | |
gasStationObj.insertCarQ(newCar); | |
System.out.println("\tCar # " + carIdCounter | |
+ " waits in the car queue."); | |
} | |
} else { | |
System.out.println("\tNo new car!"); | |
} | |
// Step 2: free busy pumps, add to free pumpQ | |
for (int i = 0; i < gasStationObj.numBusyGasPumps(); i++) { | |
GasPump newGasPump = gasStationObj.getFrontBusyGasPumpQ(); | |
if (newGasPump.getEndIntervalTime() <= currentTime) { | |
Car newCar; | |
newGasPump = gasStationObj.removeBusyGasPumpQ(); | |
newCar = newGasPump.switchBusyToFree(); | |
System.out.println("\tCar # " + newCar.getCarId() | |
+ " is done."); | |
gasStationObj.insertFreeGasPumpQ(newGasPump); | |
System.out.println("\tPump #" + newGasPump.getPumpId() | |
+ " is free."); | |
} | |
} | |
// Step 3: get free pumps to serve waiting cars | |
for (int i = 0; i < gasStationObj.numFreeGasPumps(); i++) { | |
if (gasStationObj.numWaitingCars() != 0) { | |
Car newCar = gasStationObj.removeCarQ(); | |
GasPump newGasPump = gasStationObj.removeFreeGasPumpQ(); | |
newGasPump.switchFreeToBusy(newCar, currentTime); | |
gasStationObj.insertBusyGasPumpQ(newGasPump); | |
System.out.println("\tCar # " + newCar.getCarId() | |
+ " gets a pump."); | |
System.out | |
.println("\tPump # " + newGasPump.getPumpId() | |
+ " starts serving car # " | |
+ newCar.getCarId() + " for " | |
+ newCar.getServiceDuration() + " units."); | |
System.out.println("\tCar # " | |
+ newGasPump.getCurrentCar().getCarId() | |
+ ", currently served, is set to now busy pump # " | |
+ newGasPump.getPumpId()); | |
numServed++; | |
totalWaitingTime = totalWaitingTime | |
+ (currentTime - newCar.getArrivalTime()); | |
} | |
} // end simulation loop | |
} | |
// clean-up | |
} | |
private void printStatistics() { | |
// print out simulation results | |
// you need to display all free and busy tellers | |
System.out.println("End of simulation report."); | |
System.out.println("# total arrival cars: " + carIdCounter); | |
System.out.println("# cars gone away: " + numGoAway); | |
System.out.println("# cars served: " + numServed); | |
System.out.println("*** Current Pump Info. ***"); | |
System.out.println("# waiting cars: " + gasStationObj.numWaitingCars()); | |
System.out.println("# busy pumps: " + gasStationObj.numBusyGasPumps()); | |
System.out.println("# free pumps: " + gasStationObj.numFreeGasPumps()); | |
System.out.println("Total waiting line: " + totalWaitingTime); | |
System.out.println("*** Busy Pump info ***"); | |
while (gasStationObj.numBusyGasPumps() > 0) { | |
GasPump gasPump = gasStationObj.removeBusyGasPumpQ(); | |
gasPump.setEndSimulationTime(simulationTime, 0); | |
gasPump.printStatistics(); | |
} | |
System.out.println("*** Free Pump info ***"); | |
//System.out.println(gasStationObj.numFreeGasPumps()); | |
while (gasStationObj.numFreeGasPumps() > 0) { | |
GasPump gasPump = gasStationObj.removeFreeGasPumpQ(); | |
gasPump.setEndSimulationTime(simulationTime, 1); | |
gasPump.printStatistics(); | |
} | |
} | |
// *** main method to run simulation **** | |
public static void main(String[] args) { | |
GasStationSimulation gas_station_simulation = new GasStationSimulation(); | |
gas_station_simulation.getUserParameters(); | |
gas_station_simulation.doSimulation(); | |
gas_station_simulation.printStatistics(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment