package System; import Agents.Agent; import Agents.Person; import Agents.TrafficLightHub; import Database.Sql; import Entity.CustomStyle; import Entity.Disaster; import Entity.Hospital; import Entity.TrafficLight; import GeographicInformation.BoundingBox; import GeographicInformation.Location; import GlobalData.CTANetwork; import GlobalData.Constants; import GlobalData.SharedData; import Messaging.Message; import Messaging.QueueParameters; import Utilities.KmlUtility; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; /** * The Care taker agent for all traffic lights. This CTA is responsible to generate * the individual traffic lights and changes the light based on the number of ticks. * The CTA also exchanges information with the Vehicle CTA. */ public class TrafficLightCTA extends CareTakerAgent { HashMap<String, CustomStyle> trafficLightStyles = new HashMap<String, CustomStyle>(); /** * Stop receiving messages when the flag is true. */ private boolean holdMessages = false; /** * The locations where the traffic lights will be drawn on the map. * The locations are constant for the traffic light and only the style * changes for every tick. */ private ArrayList<Location> agentLocations; /** * The style of the individual traffic lights change. */ private ArrayList<String> agentStyles; /** * The status of all the traffic lights to be broadcasted to all the VehicleCTA */ //private HashMap<Long, Integer> agentSignalStatus; private ArrayList<TrafficLight> agentSignalStatus; private boolean restoreState = false; /** * Constructor to create the TrafficLight CTA */ public TrafficLightCTA() { Utilities.Log.ConfigureLogger(); readConfigurations(); createObjects(); //CTAStatus = Collections.synchronizedMap(new HashMap<String, Integer>()); buildCTAStatus(); //agents = new ArrayList<Agent>(); //agentLocations = new ArrayList<Location>(); //agentStyles = new ArrayList<String>(); //agentSignalStatus = new HashMap<Long, Integer>(); //agentSignalStatus = new ArrayList<TrafficLight>(); addQueueListener(); Utilities.Log.logger.info("TrafficLightHub CTA Started"); Utilities.Log.logger.info("Number of CTAs : " + CTANetwork.hosts.size()); } private TrafficLightCTA(String filename) { Utilities.Log.ConfigureLogger(); createObjects(); restoreState(filename); addQueueListener(); restoreState = true; Utilities.Log.logger.info("Restored state after " + currentTickNumber + " tick"); sendRestoreState(); Utilities.Log.logger.info("Sent Restored State Message"); long timeBeforewaiting = System.currentTimeMillis(); while (!checkIfAllCTAsDoneWithRestoreState()) { try { long timeNow = System.currentTimeMillis(); if (timeNow - timeBeforewaiting >= CTANetwork.MAXIMUM_TIME_OUT_FOR_SAVING_STATE) { updateTimeOutList(); Utilities.Log.logger.info("Continuing with run after timeout for saving state"); break; } else { //wait until all CTAs are ready Thread.sleep(500); } } catch (InterruptedException ex) { Logger.getLogger(PeopleCTA.class.getName()).log(Level.SEVERE, null, ex); } } buildCTAStatus(); Utilities.Log.logger.info("Number of CTAs : " + CTANetwork.hosts.size()); } /** * Creates all the objects necessary for the CTA operation. * @see EmergencyServiceCTA * @see CareTakerAgent */ private void createObjects() { CTAStatus = Collections.synchronizedMap(new HashMap<String, Integer>()); agents = new ArrayList<Agent>(); agentStyles = new ArrayList<String>(); agentSignalStatus = new ArrayList<TrafficLight>(); agentLocations = new ArrayList<Location>(); } /** * Create the traffic light Hub agents that are responsible for changing the * status of the traffic lights they control for their respective locations. */ private void createTrafficLightHubs() { //Read the database for a list of hubs and create the agents. ArrayList<Integer> hubIds = Sql.getTrafficHubs(); Utilities.Log.logger.info("TrafficLightHubCTA:: Number of Hubs:" + hubIds.size()); for (int i = 0; i < hubIds.size(); i++) { int hubId = hubIds.get(i); TrafficLightHub trafficLightHub = new TrafficLightHub(hubId); agents.add(trafficLightHub); } /* For each hub add the locations of the TrafficLights to the agentlocations to place the placemarks in the KML*/ for (Agent t : agents) { ArrayList<TrafficLight> agentLights = ((TrafficLightHub) t).getAttributes().trafficLights; for (TrafficLight l : agentLights) { agentLocations.add(l.getLocation()); agentStyles.add("" + l.getLight()); } } Utilities.Log.logger.info("Finished Creating TrafficHubs. Added " + agents.size() + " agents with" + agentLocations.size() + "traffic lights."); } /** * Check if all the agents are ready for next tick. * @return true if all agents are ready. */ @Override public boolean checkIfAllAgentsReadyForNextTick() { int count = 0; for (Agent p : agents) { if (p.statusFlag) { count++; } } if ((count == agents.size()) && (count > 0)) { return true; } else { return false; } } /** * Activate the agents, by calling their action methods */ @Override public void activateAgentBehaviour() { Collections.shuffle(agents); for (Agent p : agents) { p.run(); } } /** * Cleanup operations performed by the care taker after each run of all agents. * The cleanup operation adds the placemarks to the kml files and writes out * the output. In addition it changes the status of the CTA to ready for next * tick. */ private void cleanUp() { sendReadyForTick(); kmlUtility.addPlacemarks(agentLocations, agents, "traffic", agentStyles,this.getCurrentTickNumber()); //kmlUtility.addPlacemarks(agentLocations, agentStyles, currentTickNumber); if (currentTickNumber % 50 == 0) { writeKMLFile("trafffic"); kmlUtility = new KmlUtility(trafficLightStyles); } for (String host : CTAStatus.keySet()) { Utilities.Log.logger.info(host + " : " + CTAStatus.get(host)); } if ((currentTickNumber % SharedData.saveStateAtTick == 0 && SharedData.isStateSaveEnabled) || initiateStateSave) { initiateStateSave = false; Utilities.Log.logger.info("Sending message for CTAs to save their respective states at tick: " + currentTickNumber); sendSavingState(currentTickNumber); beginStateSave(); holdMessages = true; changeSavedCTAsToReady(); holdMessages = false; } } /** * This begins the process of saving states, for the CTA. * After sending a message to other CTAs saying it is saving its state, it waits until every CTA is also doing the same. * It then writes the state as binary data into a file, and sends a message saying it has completed saving state. * It waits until all CTAs have completed saving their respective states before exiting the funtion. */ private void beginStateSave() { // Check if all CTAs are saving state long timeBeforewaiting = System.currentTimeMillis(); while (!checkIfAllCTAsReadyForStateSave()) { try { long timeNow = System.currentTimeMillis(); if (timeNow - timeBeforewaiting >= CTANetwork.MAXIMUM_TIME_OUT_FOR_SAVING_STATE) { updateTimeOutList(); Utilities.Log.logger.info("Continuing with run after timeout for saving state"); break; } else { //wait until all CTAs are ready Thread.sleep(500); } } catch (InterruptedException ex) { Logger.getLogger(PeopleCTA.class.getName()).log(Level.SEVERE, null, ex); } } saveCTAState(); initiateStateSave = false; sendSavedState(); // Check if all CTAs have finished saving state timeBeforewaiting = System.currentTimeMillis(); while (!checkIfAllCTAsDoneWithStateSave()) { Utilities.Log.logger.info("Waiting for CTA to finish saving state"); try { long timeNow = System.currentTimeMillis(); if (timeNow - timeBeforewaiting >= CTANetwork.MAXIMUM_TIME_OUT_FOR_SAVING_STATE) { updateTimeOutList(); Utilities.Log.logger.info("Continuing with run after timeout for saved state"); break; } else { //wait until all CTAs are ready Thread.sleep(500); } } catch (InterruptedException ex) { Logger.getLogger(PeopleCTA.class.getName()).log(Level.SEVERE, null, ex); } } } /** * Create the all the style objects that will be used by the any of the * traffic lights. The style color will depend on the state of the * traffic light and will change for every tick. */ private void createStyles() { CustomStyle red = new CustomStyle(); red.color = Constants.SIGNAL_COLOR_RED; red.scale = Constants.SIGNAL_SCALE; red.url = Constants.SIGNAL_IMAGE; CustomStyle green = new CustomStyle(); green.color = Constants.SIGNAL_COLOR_GREEN; green.scale = Constants.SIGNAL_SCALE; green.url = Constants.SIGNAL_IMAGE; trafficLightStyles.put("" + Constants.SIGNAL_RED, red); trafficLightStyles.put("" + Constants.SIGNAL_GREEN, green); kmlUtility = new KmlUtility(trafficLightStyles); } /** * This method is called to set up the CTA for operation */ private void setUp() { // Boot functions if (Utilities.AIDGenerator.initializeAIDGen()) { createStyles(); } else { Utilities.Log.logger.info("AIDs cannot be generated"); //System.exit(0); exitSystem(); } // Generate Agents if (!restoreState) { createTrafficLightHubs(); } Utilities.Log.logger.info("Finished TrafficLight SetUp"); sendReadyForTick(); } /** * this method is called by the CTA when it needs to terminate. */ private void exitSystem() { sendDoneWithWork(); String stamp = new SimpleDateFormat("hh-mm-ss-aaa_dd-MMMMM-yyyy").format(new Date()).toString(); kmlUtility.writeFile("kml/" + stamp + ".kml"); System.exit(0); } /** * The run agents calls the individual agents run methods and advances the * agent by one tick. The CTA does not move forward untill all agents have * completed their run behaviour once within a given timeout. * The EmergencyService run agent calls the run method of the agents but does not * check if the agents are home as these agents are active for the entire simulation, * similar to a real emergency services. * @see CareTakerAgent */ private void runAgents() { activateAgentBehaviour(); while (checkIfAllAgentsReadyForNextTick()) { //Change the styles for signal placemarks to indicate a signal change. /* For every trafficLight in handeled by trafficLightHub add a new style and record its status. */ for (int i = agents.size() - 1; i > -1; i--) { agents.get(i).statusFlag = false; } //String stamp = new SimpleDateFormat("hh-mm-ss-aaa_dd-MMMMM-yyyy").format(new Date()).toString(); //kmlUtility.writeFile("kml/" + stamp + ".kml"); //Purge the previous values agentStyles = new ArrayList<String>(); //agentSignalStatus = new HashMap<Long, Integer>(); agentSignalStatus = new ArrayList<TrafficLight>(); for (int i = agents.size() - 1; i > -1; i--) { ArrayList<TrafficLight> agentLights = ((TrafficLightHub) agents.get(i)).getAttributes().trafficLights; for (TrafficLight l : agentLights) { agentStyles.add("" + l.getLight()); //agentSignalStatus.put(l.getRoadid(), l.getColor()); //agentSignalStatus.put(l.getCellid(), l.getColor()); agentSignalStatus.add(l); //Serilize object and broadcast it to all VehicleCTAs } } } Utilities.Log.logger.info("TrafficLightCTA::Completed runAgents"); } /** * This method serilizes the state of all the traffic lights (not hubs) and * sends it to the vehicle cta. * @return true if the message is sent successfully */ private boolean sendTrafficlightStatus() { Message statusUpdate = new Message(); statusUpdate.type = CTANetwork.RMQ_TYPE_AGENT_DATA; statusUpdate.messageObject = agentSignalStatus; ArrayList<String> broadCastList = CTANetwork.hostTypeMap.get(Constants.CTA_TYPE_VEHICLE); /*Chcek if there is a VehicleCTA at all? * If there are no vehicle CTA it means there are no vehicles. Hence the TrafficLightCTA can exit */ if (broadCastList == null || broadCastList.size() == 0) { Utilities.Log.logger.info("TrafficLightCTA::There are no vehicle CTAs to send the message to."); //return; Utilities.Log.logger.info("Exiting TrafficLightCTA"); //exitSystem(); return false; } else { ArrayList<String> activeHosts = new ArrayList<String>(); for (String host : broadCastList) { //Check the status of the VehicleCTAs //Utilities.Log.logger.info("Current host status: " + host + ":" + CTAStatus.get(host)); if (CTAStatus.get(host) != CTANetwork.CTA_DONE_WITH_WORK) { activeHosts.add(host); } else { Utilities.Log.logger.info("TrafficLightCTA:: " + host + "Host has Done with its work."); } Utilities.Log.logger.info("TrafficLightCTA:: ActiveHost Size: " + activeHosts.size()); } Utilities.Log.logger.info("TrafficLightCTA:: " + activeHosts.size() + " VehicleCTAs are currently active."); if (activeHosts.size() == 0) { Utilities.Log.logger.info("There are no vehicle CTAs to send the message to."); Utilities.Log.logger.info("Exiting TrafficLightCTA"); //exitSystem(); return false; } else { for (String host : activeHosts) { //queueManager.send(host, outputBuffer.toByteArray()); queueManager.send(host, statusUpdate); } return true; } } } /** * Any specific CTA initilizations are done here. */ private void initialize() { } /** * This function checks if all the agents on this CTA have satisfied their * objective, in which case the CTA has completed its task. * @return true if all agents in the CTA have completed their objectives */ private boolean objectiveSatisfiedForAllAgents() { int count = 0; for (Agent p : agents) { if (p.objectiveFlag) { count++; } } if (count == agents.size()) { return true; } else { return false; } } /** * This method complets one iteration of the CTA's operation. The method * terminates when all the agents in the CTA have completed their tasks. */ private void runCTA() { try { setUp(); //Runs until objectives for all agents is fulfilled while (!objectiveSatisfiedForAllAgents()) { initialize(); //Time out for waiting for other agents long timeBeforewaiting = System.currentTimeMillis(); //now check if all agents are ready while (!checkIfAllCTAsReadyForNextTick(holdMessages)) { try { long timeNow = System.currentTimeMillis(); if (timeNow - timeBeforewaiting >= CTANetwork.MAXIMUM_TIME_OUT_FOR_CTA) { updateTimeOutList(); Utilities.Log.logger.info("Continuing with run after timeout"); break; } else { //wait until all CTAs are ready Thread.sleep(500); } } catch (InterruptedException ex) { Logger.getLogger(TrafficLightCTA.class.getName()).log(Level.SEVERE, null, ex); } } if (initiateStateSave && currentTickNumber >= tickNumberForStateSave) { } else { holdMessages = true; changeReadyCTAsToComputing(); //If sening the traffic light status fails then stop the CTA if (sendTrafficlightStatus() == false) { break; } Utilities.Log.logger.info("TrafficLightCTA: Size of the signalStatus:" + agentSignalStatus.size()); holdMessages = false; runAgents(); Utilities.Log.logger.info("Current Tick Number: " + currentTickNumber); currentTickNumber++; } cleanUp(); } exitSystem(); } catch (Exception e) { Utilities.Log.logger.info("Unable to complete work due to exection. Terminating" + e.getMessage()); e.printStackTrace(); sendDoneWithWork(); exitSystem(); } } /** * */ @Override protected void saveCTAState() { FileOutputStream fos = null; ObjectOutputStream out = null; DataOutputStream dos = null; String stamp = new SimpleDateFormat("hh-mm-ss-aaa_dd-MMMMM-yyyy").format(new Date()).toString(); String fileName = "savedstates/" + stamp + "_" + currentTickNumber + "_peopleCTA.data"; try { fos = new FileOutputStream(fileName); out = new ObjectOutputStream(fos); dos = new DataOutputStream(fos); // Objects of PeopleCTA //out.writeObject(kmlUtility); //out.writeObject(queueManager); out.writeObject(CTAStatus); out.writeObject(agents); out.writeObject(agentLocations); out.writeObject(agentStyles); // Objects of CTANetwork out.writeObject(CTANetwork.hostQueueMap); out.writeObject(CTANetwork.hostTypeMap); out.writeObject(CTANetwork.hosts); // Objects of SharedData out.writeObject(SharedData.boundingBox); out.writeObject(SharedData.ambulancePerHospital); out.writeObject(SharedData.deadPeopleAgents); out.writeObject(SharedData.disasters); out.writeObject(SharedData.hospitals); out.writeObject(SharedData.trafficLights); out.writeObject(SharedData.injuredPeopleBeingServed); out.writeObject(SharedData.injuredPeopleRescued); out.writeObject(SharedData.newInjuredPeople); out.writeObject(SharedData.pickedUpinjuredPeople); dos.writeInt(SharedData.numberOfAgents); dos.writeInt(SharedData.numberOfAmbulances); dos.writeInt(SharedData.numberOfCivilVehicles); dos.writeInt(SharedData.numberOfFireVehicles); dos.writeInt(SharedData.numberOfPeopleCTA); dos.writeInt(SharedData.numberOfPoliceVehicles); dos.writeBoolean(SharedData.isDisasterTriggered); dos.writeInt(currentTickNumber); dos.writeBoolean(holdMessages); dos.close(); fos.close(); out.close(); Utilities.Log.logger.info("Saved State"); } catch (IOException ex) { ex.printStackTrace(); } } /** * Restores the state of this CTA from a file. Thsi will restore all objects of the CTA saved previously. * The CTA will continue running from the point where state was restored, at the point in the file where it was previously saved * @param filename */ @Override protected void restoreState(String filename) { FileInputStream fis = null; ObjectInputStream in = null; DataInputStream din = null; try { fis = new FileInputStream(filename); in = new ObjectInputStream(fis); din = new DataInputStream(fis); //queueManager = (QueueManager) in.readObject(); CTAStatus = (Map<String, Integer>) in.readObject(); agents = (ArrayList<Agent>) in.readObject(); agentLocations = (ArrayList<Location>) in.readObject(); agentStyles = (ArrayList<String>) in.readObject(); CTANetwork.hostQueueMap = (HashMap<String, QueueParameters>) in.readObject(); CTANetwork.hostTypeMap = (HashMap<Integer, ArrayList<String>>) in.readObject(); CTANetwork.hosts = (ArrayList<String>) in.readObject(); SharedData.boundingBox = (BoundingBox) in.readObject(); SharedData.ambulancePerHospital = (List<Integer>) in.readObject(); SharedData.deadPeopleAgents = (List<Person>) in.readObject(); SharedData.disasters = (List<Disaster>) in.readObject(); SharedData.hospitals = (List<Hospital>) in.readObject(); SharedData.trafficLights = (List<TrafficLight>) in.readObject(); SharedData.injuredPeopleBeingServed = (List<Person>) in.readObject(); SharedData.injuredPeopleRescued = (List<Person>) in.readObject(); SharedData.newInjuredPeople = (List<Person>) in.readObject(); SharedData.pickedUpinjuredPeople = (List<Person>) in.readObject(); SharedData.numberOfAgents = (int) din.readInt(); SharedData.numberOfAmbulances = (int) din.readInt(); SharedData.numberOfCivilVehicles = (int) din.readInt(); SharedData.numberOfFireVehicles = (int) din.readInt(); SharedData.numberOfPeopleCTA = (int) din.readInt(); SharedData.numberOfPoliceVehicles = (int) din.readInt(); SharedData.isDisasterTriggered = (boolean) din.readBoolean(); currentTickNumber = (int) din.readInt(); holdMessages = (boolean) din.readBoolean(); din.close(); in.close(); fis.close(); } catch (IOException ex) { ex.printStackTrace(); } catch (ClassNotFoundException ex) { ex.printStackTrace(); // } } } /** * CTA Main function * @param args */ public static void main(String args[]) { if (args.length == 0) { TrafficLightCTA obj = new TrafficLightCTA(); obj.runCTA(); } else { TrafficLightCTA obj = new TrafficLightCTA(args[0]); obj.restoreState = true; obj.runCTA(); } } /** * This is the method called to handle any message received by this CTA * @param message the message object form any other CTA * @see CTANetwork * @see Messaging.QueueParameters * @see Messaging.QueueManager */ public void receivedMessage(Message message) { //update status of the host from which message was received while (holdMessages) { } switch (message.type) { case CTANetwork.RMQ_TYPE_STATUS_UPDATE: //Find out what type of status update it is Message statusType = (Message) message.messageObject; switch (statusType.type) { case CTANetwork.CTA_READY_FOR_NEXT_TICK: changeCTAStatus(statusType.hostName, statusType.type); break; case CTANetwork.CTA_DONE_WITH_WORK: changeCTAStatus(statusType.hostName, statusType.type); break; case CTANetwork.CTA_SAVING_STATE: Utilities.Log.logger.info("Received state save message from " + statusType.hostName + "at tick: " + currentTickNumber); tickNumberForStateSave = (Integer) statusType.messageObject; initiateStateSave = true; changeCTAStatus(statusType.hostName, statusType.type); break; case CTANetwork.CTA_SAVED_STATE: Utilities.Log.logger.info("Received state saved message from " + statusType.hostName + "at tick: " + currentTickNumber); changeCTAStatus(statusType.hostName, statusType.type); break; case CTANetwork.CTA_RESTORED_STATE: Utilities.Log.logger.info("Received restored state message from " + statusType.hostName + "at tick: " + currentTickNumber); changeCTAStatus(statusType.hostName, statusType.type); break; // case CTANetwork.CTA_COMPLETE_EXIT: // Utilities.Log.logger.info("VehicleCTA: Done with work and Exitting....."); // changeCTAStatus(statusType.hostName, statusType.type); // break; } break; } Utilities.Log.logger.info("TrafficCTA: ReceivedMessage of type: " + message.type); } }