package simulator; /* * AmusementPark.java * Created on Jan 6, 2005 * */ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * AmusementPark - This is the class from which the simulation * is started. Amusement park contains all the rides and customers * in the park and keeps track of the time. * * @author Ping * */ public class AmusementPark implements ClockedThing { /* * Note: In the future, we might want to split up the rides * into separate lists as well (from an efficiency prospective). */ // This stores all the rides in the park // Although we use a vector here, another possible implementation // might want to use Hashtable. However, we iterate through all // rides more often than we look up rides by name. protected ArrayList rides; // This list stores all the customers waiting to enter // the park protected MyPriorityQueue customersWaitingToEnter; // This stores all the customers that are in the park // but in transit between rides protected ArrayList customersInTransit; // This list stores all the customers that are done and // have left the park protected ArrayList customersDone; // These variables store all the necessary information about time protected Time openingTime; protected Time closingTime; protected Time currTime; // These two variables store the entrance and exit of the park protected Location entrance; protected Location exit; // This is just a flag to determine if the park is open or not protected boolean parkIsOpen; protected Logger logger; boolean simRanOnce = false; public AmusementPark(Collection rides, Location entrance, Location exit, Time openingTime, Time closingTime, Logger logger) { this.rides = new ArrayList(rides); customersInTransit = new ArrayList(); customersDone = new ArrayList(); this.entrance = entrance; this.exit = exit; this.openingTime = openingTime; this.closingTime = closingTime; this.logger = logger; currTime = null; parkIsOpen = false; } /** * This function officially opens the park. It opens all the * rides and takes the list of customers that will enter the park * throughout the day * * @param customers - All the customers that will be visiting the park * today. */ public void openPark(Collection customers) { for(Attraction a : rides) { // Open all the rides a.openRide(); } customersWaitingToEnter = new MyPriorityQueue(); // now go through all the customers for(Customer c : customers) { customersWaitingToEnter.enqueue(c, c.getTimeEntered()); } try { currTime = (Time)openingTime.clone(); } catch(CloneNotSupportedException e) { e.printStackTrace(); } logger.parkOpened(currTime); parkIsOpen = true; } /** * @return Returns the entrance of the park. */ public Location getEntrance() { return entrance; } /** * @return Returns the exit of the park. */ public Location getExit() { return exit; } /** * This function returns true if the park is open, false otherwise * @return Returns the parkIsOpen. */ public boolean isParkOpen() { return parkIsOpen; } /** * This function returns an instance of the current time. * Note it returns a reference, so any changes made by this class * will also affect the returned clock. * * @return Time - a reference to the current clock */ public Time getCurrTime() { return currTime; } /** * This function returns a reference to the opening time * * Note: Whatever changes made to the returned time instance will * also affect this park's closing time and vice versa. * @return */ public Time getOpeningTime() { return openingTime; } /** * This function returns a reference to the closing time * * Note: Whatever changes made to the returned time instance will * also affect this park's closing time and vice versa. * @return */ public Time getClosingTime() { return closingTime; } /** * This function returns an enumeration of all the customers who have * finished the simulation (they have exited the park). * * @return */ public Iterator getAllFinishedCustomers() { return customersDone.iterator(); } /** * This function gets a particular attraction based on that attraction's * name. * @param rideName - The name of the attraction * @return A reference to the attraction */ public Attraction getAttraction(String rideName) { for(Attraction a : rides) { if(a.getName().equalsIgnoreCase(rideName)) { return a; } } return null; } /** * This function removes the customer from the in-transit list * since the customer is no longer in transit. THe customer however * does not get put on another list that is managed by the park * (it should now be in one of the lists managed by the individual rides) * @param customer The customer to remove */ public void customerArrivedAtDestination(Customer customer) { customersInTransit.remove(customer); } /** * This function is to let the amusement park know that this customer * is now in transit and can move around the park (not in any rides). * * @param customer The customer that is now in transition */ public void customerInTransit(Customer customer) { customersInTransit.add(customer); } /** * This returns all the rides in the park. * @return */ public Iterator getAllRides() { return rides.iterator(); } /** * This is to signal one minute has passed in the simulation * During each minute, new customers may enter the park, customers * in transition can move 1 distance unit, and the ride also * process the waiting line as well as the cars on the ride. * * @return This function returns true if the simulation should keep running * false when all the customers have left the park and the park is closed */ public boolean onClockTick() { // Check to see if the park should still be open if(parkIsOpen && currTime.compareTo(closingTime) >= 0) { parkIsOpen = false; // tell each customer in transit that the park is closing for(Customer c : customersInTransit) { c.parkClosing(); } for(Attraction a : rides) { a.closeRide(); } } // now let people enter the park if its time if(parkIsOpen) { while(!customersWaitingToEnter.isEmpty()) { // Keep examining all the customers that can // enter Customer c = customersWaitingToEnter.peek(); if(c.getTimeEntered().compareTo(currTime) <= 0) { // remove the customer from the waiting to enter // list customersWaitingToEnter.dequeue(); // now put the customer in the transit queue // so he is "in the park" customersInTransit.add(c); c.enterPark(this, currTime, entrance, logger); } else { // since the list is a priority queue sorted // based on enter time, as soon as we // encounter someone that can't enter yet, // we are done. break; } } } for(int i = 0; i < customersInTransit.size(); i++) { Customer c = customersInTransit.get(i); boolean stillInPark = c.onClockTick(); if(!stillInPark) { // this customer is done and has left the park customersInTransit.remove(i); i--; customersDone.add(c); } } // this flag determines some rides still need processing // like if they still have people in line or on the ride boolean stillNeedToProcessRides = false; for(Attraction a : rides) { boolean rideNotDone = a.onClockTick(); if(rideNotDone) { stillNeedToProcessRides = true; } } currTime.onClockTick(); boolean isSimulationGoing = stillNeedToProcessRides || parkIsOpen || !customersInTransit.isEmpty(); if(!isSimulationGoing) { // everything is done, so lets close it all up logger.parkClosed(); } return isSimulationGoing; } }