Index: /trunk/src/atmsdriver/GoogleMapAnimator.form
===================================================================
--- /trunk/src/atmsdriver/GoogleMapAnimator.form	(revision 245)
+++ /trunk/src/atmsdriver/GoogleMapAnimator.form	(revision 245)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.3" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+  <Properties>
+    <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
+      <Dimension value="[151, 92]"/>
+    </Property>
+  </Properties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <Component id="scrollBar" min="-2" pref="24" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+              <Component id="jScrollPane1" pref="421" max="32767" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Component id="scrollBar" alignment="0" max="32767" attributes="0"/>
+          <Component id="jScrollPane1" min="-2" max="-2" attributes="0"/>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Component class="javax.swing.JScrollBar" name="scrollBar">
+      <Events>
+        <EventHandler event="adjustmentValueChanged" listener="java.awt.event.AdjustmentListener" parameters="java.awt.event.AdjustmentEvent" handler="scrollbarValueChanged"/>
+      </Events>
+    </Component>
+    <Container class="javax.swing.JScrollPane" name="jScrollPane1">
+      <AuxValues>
+        <AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
+      </AuxValues>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
+      <SubComponents>
+        <Component class="javax.swing.JTextArea" name="txtDisplay">
+          <Properties>
+            <Property name="columns" type="int" value="20"/>
+            <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
+              <Font name="Courier New" size="15" style="0"/>
+            </Property>
+            <Property name="rows" type="int" value="5"/>
+          </Properties>
+        </Component>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
Index: /trunk/src/atmsdriver/GoogleMapAnimator.java
===================================================================
--- /trunk/src/atmsdriver/GoogleMapAnimator.java	(revision 245)
+++ /trunk/src/atmsdriver/GoogleMapAnimator.java	(revision 245)
@@ -0,0 +1,211 @@
+package atmsdriver;
+
+import atmsdriver.model.Highways;
+import atmsdriver.model.TrafficEvent;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Scanner;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.JFrame;
+import tmcsim.cadsimulator.managers.TrafficModelManager;
+import tmcsim.common.SimulationException;
+
+/**
+ * Read and process all Traffic Events in a file and output 
+ * a snapshot of the highway model after each event to a json file. 
+ * This file can be read by Google maps. 
+ * This application is used by Traffic Event authors to assist
+ * in verifying the correctness of their data file.
+ * @author jdalbey
+ */
+public class GoogleMapAnimator extends javax.swing.JPanel
+{
+    /**
+     * Error logger.
+     */
+    private final static Logger logger = Logger.getLogger("trafficmodeleventdriver");
+
+    /**
+     * Highways in traffic network
+     */
+    final private Highways highways;
+
+    /**
+     * LinkedList of batch events
+     */
+    private final LinkedList<TrafficEvent> eventQueue;
+    /**
+     * Map of incidents to events
+     */
+    private Map<String, List<TrafficEvent>> incidents;
+    /**
+     * Highway history
+     */
+    private List<String> history;
+    /**
+     * name of events file obtained from properties
+     */
+    private String events_file = ""; 
+    /**
+     * Creates the JPanel and builds the highways and events. 
+     */
+    public GoogleMapAnimator() throws RemoteException, SimulationException
+    {
+        initComponents();
+
+        // Initialize the highway model
+        incidents = new HashMap<String, List<TrafficEvent>>();
+        highways = new Highways(
+                "config/vds_data/highways_fullmap.txt",
+                // following aren't used by this application
+                "localhost", 8080);
+        final String CONFIG_FILE_NAME = "traffic_model_config.properties";
+        String propertiesFile = "config" + System.getProperty("file.separator") 
+                 + CONFIG_FILE_NAME;
+        Properties props = TrafficModelManager.loadProperties(propertiesFile);
+        events_file = props.getProperty("Events_File");
+        FileInputStream fis = null;
+        try
+        {
+            fis = new FileInputStream(events_file);
+        } catch (FileNotFoundException ex)
+        {
+            Logger.getLogger(TrafficModelManager.class.getName()).log(Level.SEVERE, null, 
+                    "Missing Traffic Events file " + events_file);
+            System.exit(-1);
+        }
+        Scanner fileScanner = new Scanner(fis);        
+        // Read all lines from the file of events and put in a queue
+        eventQueue = TrafficModelManager.readBatchFile(fileScanner);
+    }
+    /** Load the traffic events into a history buffer */
+    public void load()
+    {
+        txtDisplay.setText("Loading traffic events from: " + events_file);
+        history = new ArrayList<String>();
+        // If we have any events left to process
+        while (!eventQueue.isEmpty())
+        {
+            // Get next event
+            TrafficEvent nextEvent = eventQueue.peek();
+            System.out.println(nextEvent.eventTime);
+            // apply colorization to highways
+            highways.applyColorToHighwayStretch(nextEvent.routeNumber, nextEvent.dir,
+                    nextEvent.postmile, nextEvent.range, nextEvent.color);
+            //history.add(highways.toString()+"\n"+nextEvent.eventTime);
+            
+            // Output the highway model 
+            String geojson = highways.toJson();
+            //System.out.println(geojson); // diagnostic
+            PrintWriter out;
+            try
+            {
+                out = new PrintWriter("highways.json");
+                out.print(geojson);
+                out.close();
+            }
+            catch (FileNotFoundException ex)
+            {
+                Logger.getLogger(GoogleMapAnimator.class.getName()).log(Level.SEVERE, null, ex);
+            }
+            
+            // Sleep 10 sec for the javascript page to load the file
+            try
+            {
+                Thread.sleep(10000); // pause 10 seconds
+            }
+            catch (InterruptedException ex)
+            {
+                Logger.getLogger(GoogleMapAnimator.class.getName()).log(Level.SEVERE, null, ex);
+            }
+            // Remove this event from the queue, we're done with it.
+            eventQueue.remove();
+        }
+        scrollBar.setMaximum(history.size());
+        // display the first item from the history
+        txtDisplay.setText(history.get(0));
+    }
+    /**
+     * This method is called from within the constructor to initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is always
+     * regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents()
+    {
+
+        scrollBar = new javax.swing.JScrollBar();
+        jScrollPane1 = new javax.swing.JScrollPane();
+        txtDisplay = new javax.swing.JTextArea();
+
+        setPreferredSize(new java.awt.Dimension(151, 92));
+
+        scrollBar.addAdjustmentListener(new java.awt.event.AdjustmentListener()
+        {
+            public void adjustmentValueChanged(java.awt.event.AdjustmentEvent evt)
+            {
+                scrollbarValueChanged(evt);
+            }
+        });
+
+        txtDisplay.setColumns(20);
+        txtDisplay.setFont(new java.awt.Font("Courier New", 0, 15)); // NOI18N
+        txtDisplay.setRows(5);
+        jScrollPane1.setViewportView(txtDisplay);
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+        this.setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addComponent(scrollBar, javax.swing.GroupLayout.PREFERRED_SIZE, 24, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 421, Short.MAX_VALUE))
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addComponent(scrollBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+            .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+        );
+    }// </editor-fold>//GEN-END:initComponents
+
+    private void scrollbarValueChanged(java.awt.event.AdjustmentEvent evt)//GEN-FIRST:event_scrollbarValueChanged
+    {//GEN-HEADEREND:event_scrollbarValueChanged
+        // when the scroll bar is moved show the corresponding snapshot from history
+        txtDisplay.setText(history.get(evt.getValue()) );
+        repaint();
+    }//GEN-LAST:event_scrollbarValueChanged
+
+    /** Entry point for the application.  Builds a surrounding JFrame and 
+     * runs the application.
+     * @param args
+     * @throws RemoteException
+     * @throws SimulationException 
+     */
+    public static void main(String[] args) throws RemoteException, SimulationException
+    {
+        JFrame frame = new JFrame("Traffic Events Animator");
+        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+        frame.setSize(1050,450);
+        GoogleMapAnimator display = new GoogleMapAnimator();
+        frame.add(display);
+        frame.setVisible(true);
+        display.load();
+    }
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JScrollPane jScrollPane1;
+    private javax.swing.JScrollBar scrollBar;
+    private javax.swing.JTextArea txtDisplay;
+    // End of variables declaration//GEN-END:variables
+}
