source: tmcsimulator/trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java @ 197

Revision 197, 16.4 KB checked in by jdalbey, 9 years ago (diff)

Deleted ATMSBatchDriver from clients folder. This is now obsolete since it's been integrated as a CAD Server Manager.

Line 
1package tmcsim.cadsimulator.managers;
2
3import atmsdriver.model.Highways;
4import atmsdriver.model.LoopDetector;
5import atmsdriver.model.TrafficEvent;
6import java.awt.event.ActionEvent;
7import java.awt.event.ActionListener;
8import java.io.FileInputStream;
9import java.io.FileNotFoundException;
10import java.rmi.RemoteException;
11import java.text.ParseException;
12import java.text.SimpleDateFormat;
13import java.util.ArrayList;
14import java.util.Collections;
15import java.util.Date;
16import java.util.HashMap;
17import java.util.LinkedList;
18import java.util.List;
19import java.util.Map;
20import java.util.Properties;
21import java.util.Scanner;
22import java.util.concurrent.TimeUnit;
23import java.util.logging.Level;
24import java.util.logging.Logger;
25import javax.swing.JOptionPane;
26import javax.swing.JWindow;
27import javax.swing.Timer;
28import javax.swing.UIManager;
29import tmcsim.cadsimulator.Coordinator;
30import tmcsim.cadsimulator.viewer.model.CADSimulatorState;
31import tmcsim.common.SimulationException;
32
33/**
34 * Traffic Model Manager is a model and controller for the Traffic Model
35 * used in the simulation.  It represents all the highways and traffic
36 * events that occur.
37 * @author jdalbey
38 * @version 2.0
39 */
40public class TrafficModelManager
41{
42    private final static int ONE_SECOND = 1000;
43    private static final int FEPSIM_INTERVAL = 30000;
44    private final static SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
45
46    /**
47     * Error Logger.
48     */
49    private static Logger atmsLogger = Logger.getLogger("tmcsim.cadsimulator.managers");
50
51    /**
52     * Enumeration containing property names for Properties parsing.
53     *
54     * @author Matthew Cechini
55     */
56    private static enum PROPERTIES
57    {
58        /**
59         *
60         */
61        HIGHWAYS_MAP_FILE("Highways_Map_File"),
62        /**
63         *
64         */
65        FEPSIM_IP_ADDR("FEPSim_IP_addr"),
66        /**
67         *
68         */
69        EVENTS_FILE("Events_File"),
70        OUTPUT_DEST("Output_Destination");
71       
72        public String name;
73
74        private PROPERTIES(String n)
75        {
76            name = n;
77        }
78    };
79
80
81    /**
82     * Properties Object.
83     */
84    private Properties atmsProperties = null;
85    /**
86     * Highways in traffic network
87     */
88    final private Highways highways;
89
90    /**
91     * LinkedList of batch events
92     */
93    private LinkedList<TrafficEvent> eventQueue;
94    /**
95     * Map of incidents to events
96     */
97    private Map<String, List<TrafficEvent>> incidents;
98
99    /**
100     * GUI for this driver
101     */
102    private TrafficModelViewer theView;
103   
104    /**
105     * Constructor. Loads the Properties file and initializes the
106     * ATMSCommunicator with the parsed data.
107     *
108     * @param propertiesFile Target file path of properties file.
109     * @param theCoordinator Reference to the simulation Coordinator from whom we get simulation
110     * elapsed time.
111     */
112    public TrafficModelManager(String propertiesFile, final Coordinator theCoordinator) 
113            throws SimulationException
114    {
115        if (!loadProperties(propertiesFile))
116        {
117            System.exit(0);
118        }
119//        final Coordinator theCoordinator = theCoordinator;
120        // Initialize the highway model
121        incidents = new HashMap<String, List<TrafficEvent>>();
122        highways = new Highways(
123                atmsProperties.getProperty(PROPERTIES.HIGHWAYS_MAP_FILE.name),
124                //"config/vds_data/highways_fullmap.txt",
125                //        "192.168.251.46", 8080);  //IP address of FEP Sim Linux VM
126                atmsProperties.getProperty(PROPERTIES.FEPSIM_IP_ADDR.name),
127                8080); 
128
129        // READ THE BATCH FILE OF COMMANDS and put in a queue
130        eventQueue = readBatchFile();
131        // Launch the display
132        theView = new TrafficModelViewer(this, new ArrayList<String>(incidents.keySet()));
133        theView.setVisible(true);
134        theView.update("0:00", "1:11", eventQueue);
135
136        // Create a timer that fetches the simulation time every second.
137        Timer timer = new Timer(ONE_SECOND, new ActionListener()
138        {
139            // Every second, see if an event should be launched
140            public void actionPerformed(ActionEvent e)
141            {
142                String currentClock = "";
143                String currentATMStime = "";
144                Date simClock = new Date();
145                // Obtain the simulation time from the CAD server
146                try
147                {
148                    long simtime = theCoordinator.getCurrentSimulationTime();
149                    currentClock = formatInterval(simtime);
150                    // For Debugging, show the ATMS time
151//                    long ATMStime = theCoorInt.getATMStime();       
152//                    Date atmsdate = new Date(ATMStime);
153//                    currentATMStime = formatter.format(atmsdate);
154                    try
155                    {
156                        simClock = formatter.parse(currentClock);
157                    }
158                    catch (ParseException ex)
159                    {
160                        Logger.getLogger(TrafficModelManager.class.getName()).log(Level.SEVERE, null, ex);
161                        System.out.println("Invalid simulation clock time found in ATMSDriverClient");
162                        System.exit(-1);
163                    }
164                    //System.out.println("Current clock: " + currentClock);
165                }
166                catch (RemoteException ex)
167                {
168                    System.out.println("Remote Exception reading sim or ATMS clock time");
169                    Logger.getLogger(TrafficModelManager.class.getName()).log(Level.SEVERE, null, ex);
170                }
171                // If we have any events left to process
172                if (!eventQueue.isEmpty())
173                {
174                    // Get the time to launch the next event
175                    TrafficEvent nextEvent = eventQueue.peek();
176                    Date eventTime = nextEvent.eventDate;
177                    //System.out.println("Next event will be launched at: " + formatter.format(eventTime));
178                    // Check the queue of events to see if the first
179                    // item should be launched.  IF so,
180                    // issue that command and remove it from queue.
181                    if (eventTime.before(simClock) || eventTime.equals(simClock))
182                    {
183                        System.out.println("LAUNCHING EVENT: " + nextEvent.toString());
184                        // apply colorization to highways
185                        highways.applyColorToHighwayStretch(nextEvent.routeNumber, nextEvent.dir,
186                                nextEvent.postmile, nextEvent.range, nextEvent.color);
187                        // Remove this event from the queue, we're done with it.
188                        eventQueue.remove();
189                    }
190
191                    theView.update(currentClock, currentATMStime, eventQueue);
192                }
193            }
194        });
195        timer.start();
196
197        if (atmsProperties.getProperty(PROPERTIES.OUTPUT_DEST.name).equals("FEP"))
198        {
199            // Start the FEP thread (to update ATMS every 30 sec). (See class def below)
200            Thread wtfep = new WriteToFEPThread();
201            wtfep.start();
202        }
203        else
204        {
205            Thread wtConsole = new WriteToConsoleThread();
206            wtConsole.start();
207        }
208       
209    }
210
211    /**
212     * This method verifies that the CAD Simulator Host and Port values are not
213     * null. Also, if a CAD Position or User ID do not exist in the properties
214     * file, the user is prompted to enter values. These values are written to
215     * the properties file. If the user cancels the process of entering these
216     * values, the verification fails.
217     *
218     * @param propertiesFile File path (absolute or relative) to the properties
219     * file containing configuration data.
220     * @return True if the properties file is valid, false if not.
221     * @throws SimulationException if there is an exception in verifying the
222     * properties file, or if the user cancels input.
223     */
224    private boolean loadProperties(String propertiesFile)
225            throws SimulationException
226    {
227        // Load the properties file.
228        try
229        {
230            atmsProperties = new Properties();
231            atmsProperties.load(new FileInputStream(propertiesFile));
232
233        } catch (Exception e)
234        {
235            atmsLogger.logp(Level.SEVERE, "TrafficModelManager", "Constructor",
236                    "Exception in parsing properties file.", e);
237            throw new SimulationException(SimulationException.INITIALIZE_ERROR,
238                    e);           
239        }
240
241
242        // Ensure that the properties file does not have null values for the
243        // required information.
244        if (atmsProperties.getProperty(PROPERTIES.HIGHWAYS_MAP_FILE.name) == null
245                || atmsProperties.getProperty(PROPERTIES.FEPSIM_IP_ADDR.name) == null
246                || atmsProperties.getProperty(PROPERTIES.EVENTS_FILE.name) == null
247                || atmsProperties.getProperty(PROPERTIES.OUTPUT_DEST.name) == null)
248        {
249            atmsLogger.logp(Level.SEVERE, "TrafficModelManager",
250                    "Constructor", "Null value in properties file.");
251            throw new SimulationException(SimulationException.INITIALIZE_ERROR);
252        }
253
254        return true;
255    }
256    /**
257     * Read a file of traffic events. 
258     * @return the chronologically ordered list of events
259     */
260    // Method is package private to facilitate unit testing.
261    LinkedList<TrafficEvent> readBatchFile()
262    {
263        FileInputStream fis;
264        LinkedList<TrafficEvent> eventList = new LinkedList<TrafficEvent>();
265        try
266        {
267            fis = new FileInputStream(
268                    //"config/vds_data/atmsBatchEvents.txt");
269            atmsProperties.getProperty(PROPERTIES.EVENTS_FILE.name));
270            // Read all lines from the file of events
271            Scanner scan = new Scanner(fis);
272            while (scan.hasNext())
273            {
274                // Read a line and add it to the event queue
275                String line = scan.nextLine().trim();
276                if (line.charAt(0) != '#')
277                {
278                    TrafficEvent evt;
279                    try
280                    {
281                        evt = new TrafficEvent(line);
282                        eventList.add(evt);
283                        String incident = evt.incident;
284                        // Add the line to the list for the corresponding incident
285                        List evtList;
286                        if (incidents.containsKey(evt.incident))
287                        {
288                            evtList = incidents.get(evt.incident);
289                        }
290                        else
291                        {
292                            evtList = new ArrayList<String>();
293                        }
294                        evtList.add(evt);
295                        // and put it back in the map
296                        incidents.put(incident, evtList);
297                    }
298                    catch (ParseException ex)
299                    {
300                        Logger.getLogger(TrafficModelManager.class.getName()).log(Level.SEVERE, null, ex);
301                        System.out.println("Wrong format data in batch event file: " + line + " \nskipping.");
302                        System.out.println("Skipping badly formatted event.");
303                    }
304                }
305            }
306        }
307        catch (FileNotFoundException ex)
308        {
309            Logger.getLogger(TrafficModelManager.class.getName()).log(Level.SEVERE, null, ex);
310        }
311        System.out.println("Events file read, " + eventList.size() + " events queued.");
312        // Put the events in chronological order
313        Collections.sort(eventList);
314        return eventList;
315    }
316
317    /**
318     * Clear an incident. For each event associated with an incident, turn the
319     * dots in its range Green and remove it from the event queue.
320     *
321     * @param incidentNumber incident to be cleared.
322     */
323    public void clearIncident(String incidentNumber)
324    {
325        boolean ok = incidents.containsKey(incidentNumber);
326        if (!ok)
327        {
328            System.out.println("Sorry, that incident number isn't found.");
329            return;
330        }
331        System.out.println("Clearing incident " + incidentNumber);
332        List<TrafficEvent> events = incidents.get(incidentNumber);
333        // Process each event associated with this incident
334        for (TrafficEvent event : events)
335        {
336            System.out.println("Event: " + event + " cleared.");
337            eventQueue.remove(event);
338
339            // apply colorization to highways, forcing to green, indicating cleared
340            highways.applyColorToHighwayStretch(event.routeNumber, event.dir,
341                    event.postmile, event.range, LoopDetector.DOTCOLOR.GREEN);
342
343        }
344        // Now refresh the view with the updated queue of events
345        theView.update("0:00", "0:00", eventQueue);
346    }
347
348    /**
349     * Format a time in seconds as HH:MM:SS
350     *
351     * @param l
352     * @return
353     */
354    private String formatInterval(final long l)
355    {
356        final long hr = TimeUnit.SECONDS.toHours(l);
357        final long min = TimeUnit.SECONDS.toMinutes(l - TimeUnit.HOURS.toSeconds(hr));
358        final long sec = TimeUnit.SECONDS.toSeconds(l - TimeUnit.HOURS.toSeconds(hr) - TimeUnit.MINUTES.toSeconds(min));
359        return String.format("%02d:%02d:%02d", hr, min, sec);
360    }
361
362    /**
363     * Construct the CADClient with the properties file path, either from the
364     * command line arguments or default.
365     *
366     * @param args Command line arguments.
367     */
368    public static void main(String[] args) throws RemoteException
369    {
370        final String CONFIG_FILE_NAME = "traffic_model_config.properties";       
371        if (System.getProperty("CONFIG_DIR") == null)
372        {
373            System.setProperty("CONFIG_DIR", "config");
374        }
375        CADSimulatorState theModel = new CADSimulatorState();
376        Coordinator theCoordinator = new Coordinator(theModel);
377        try
378        {
379            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
380            new TrafficModelManager(System.getProperty("CONFIG_DIR") + System.getProperty("file.separator") + CONFIG_FILE_NAME,
381            theCoordinator);
382
383        }
384        catch (Exception e)
385        {
386            atmsLogger.logp(Level.SEVERE, "SimulationManager", "Main",
387                    "Error initializing application.");
388
389            JOptionPane.showMessageDialog(new JWindow(), e.getMessage(),
390                    "Error - Program Exiting", JOptionPane.ERROR_MESSAGE);
391
392            System.exit(-1);
393        }
394
395    }
396    class WriteToConsoleThread extends Thread
397    {
398
399        public void run()
400        {
401            System.out.println("WriteToConsole Thread starting.");
402            // Run indefinitely
403            while (true)
404            {
405                 // Write the highway network status to the FEP Simulator
406                 System.out.println(highways.toString());
407
408                // Wait for FEP Sim to process the data we just sent
409                try
410                {
411                    Thread.sleep(1000);
412                }
413                catch (InterruptedException ie)
414                {
415                    ie.printStackTrace();
416                }
417            }
418
419        }
420    }
421   
422    class WriteToFEPThread extends Thread
423    {
424
425        public void run()
426        {
427            System.out.println("WriteToFEP Thread starting.");
428            // Run indefinitely
429            while (true)
430            {
431                try
432                {
433                    // Write the highway network status to the FEP Simulator
434                    highways.writeToFEP();
435                }
436                catch (SimulationException ex)
437                {
438                    // Ask user if they want to proceed without FEP Sim connection
439                    int reply = JOptionPane.showConfirmDialog(null, "Failed to connect to FEP Sim, proceed anyway?", "Network Failure", JOptionPane.YES_NO_OPTION);
440                    if (reply == JOptionPane.NO_OPTION)
441                    {
442                        System.exit(0);
443                    }
444                    System.out.println("Skipping writeToFEP...");
445                }
446
447                // Wait for FEP Sim to process the data we just sent
448                try
449                {
450                    Thread.sleep(FEPSIM_INTERVAL);
451                }
452                catch (InterruptedException ie)
453                {
454                    ie.printStackTrace();
455                }
456            }
457
458        }
459    }
460}
Note: See TracBrowser for help on using the repository browser.