package simulator; /* * IntervalRide.java * Created on Jan 9, 2005 * */ import java.util.ListIterator; /** * IntervalRide - This class implements interval rides. These rides are similar to * cycle rides except that it does not allow empty cars to be launched. An excample * would be a roller coaster ride. * @author Ping * */ public class IntervalRide extends Attraction { public static String ATTRACTION_TYPE = "Interval"; protected static final int NUM_OF_CARS_THRESHOLD = 1; protected static final int WAITING_THRESHOLD = 10; /** * @param attractionName * @param entrance * @param exit * @param initialNumOfCars * @param maxNumOfCarsPossible * @param carCapacity * @param rideTime * @param loadingTime */ public IntervalRide(String attractionName, Location entrance, Location exit, int initialNumOfCars, int maxNumOfCarsPossible, int carCapacity, int rideTime, int loadingTime) { super(attractionName, entrance, exit, initialNumOfCars, maxNumOfCarsPossible, carCapacity, rideTime, loadingTime); } /* * This function determines if we should add a car to the ride or not */ protected boolean shouldAddCar() { int numOfCars = cars.size(); int capacity = numOfCars * carCapacity; // we should add a car if our total capacity is less than the number of people waiting // and we haven't reached our full capacity in terms of number of cars return capacity < waitingLine.size() && numOfCars < maxNumOfCarsPossible; } /* * This function determines if we should remove a car from the attraction */ protected boolean shouldRemoveCar() { int numOfCarsWaiting = 0; boolean shouldRemove = false; for(Car c : cars) { // get the waiting time for each car if(c.isCarWaiting() && c.getMinutesSpent() > WAITING_THRESHOLD) { numOfCarsWaiting++; if(numOfCarsWaiting > NUM_OF_CARS_THRESHOLD) { shouldRemove = true; break; } } } return shouldRemove && cars.size() > 1; } /** * This function removes the first car that is waiting from the list */ protected void removeCar() { // find a car thats waiting so it can be removed // don't want to remove a car that is in the middle of the ride. ListIterator iterator = cars.listIterator(); while(iterator.hasNext()) { Car c = iterator.next(); if(c.isCarWaiting()) { iterator.remove(); break; } } } /** * Thhis function must remove customers from the waiting queue and put * them on rides (if there are space available) or remove customer from rides * (if they are done) during each clock tick. * */ public boolean onClockTick() { Car dispatchedCar = null; // since we can only launch 1 car at a time, we only load // one car at a time. Realistically, the rides probably only have // enough space to load 1 car at a time anyways. boolean hasLoadedCar = false; Customer[] riders; // we could use an iterator here, but we have more control if we do the // loop ourselves since we are adding/removing items from the list for(int i = 0; i < cars.size(); i++) { Car c = cars.get(i); if(c.isCarDone()) { // unload the car c.unloadCustomers(); } if(c.isCarWaiting() && !hasLoadedCar) { // During each clock tick, we are only loading 1 car riders = extractCustomers(); if(riders.length != 0) { // make sure we aren't loading an empty car c.loadCustomers(riders); hasLoadedCar = true; } } // we are only launching 1 car if(c.isCarReady() && dispatchedCar == null) { // this car is ready to be launched, so lets remove it and // put it in at the end. This might always be the first element c.dispatchCar(); // remove it so we can put it at the end dispatchedCar = cars.remove(i); // this is just to prevent the index from moving since the list // has just shrunk so all the elements got "pushed" forward i--; } c.onClockTick(); } if(dispatchedCar != null) { // add the dispatched car back to the end of the list // this is to model reality a little bit to make the conceptual // model a little easier. In reality when a car is dispatched it // really circles around to the back of all the other cars. cars.addLast(dispatchedCar); } updateNumOfCars(); // this will update the stats at the end. return super.onClockTick(); } /** * This function returns the estimated waiting time for this ride. * It does not have to be 100% accurate but should present a rough * estimate as to when someone will get on the ride (assuming he/she * enters the waiting line right now). * * @return int representing the expected number of minutes someone will wait */ public int getEstimatedWaitTime() { if(timeSinceEstimate >= TIME_UNTIL_NEW_ESTIMATES) { timeSinceEstimate = 0; estimatedWaitTime = 0; try { IntervalRide clone = (IntervalRide)this.clone(); clone.setSimulationMode(true); // the line not only needs to be empty, but there needs to be // a car available (if the car has just finished, u can // probably get on then) while(clone.getLineLength() > 0 || !clone.hasCarAvailable()) { clone.onClockTick(); estimatedWaitTime++; } } catch(CloneNotSupportedException e) { e.printStackTrace(); } } return estimatedWaitTime; } public Object clone() throws CloneNotSupportedException { return super.clone(); } }