Warning: Can't use blame annotator:
svn blame failed on trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java: ("Can't find a temporary directory: Internal error", 20014)

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

Revision 193, 16.6 KB checked in by jdalbey, 9 years ago (diff)

TrafficModelManager?: Added extra config property to allow for specifying output destination (console or FEP).

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