Index: trunk/src/tmcsim/highwaymodel/StationComparator.java
===================================================================
--- trunk/src/tmcsim/highwaymodel/StationComparator.java	(revision 422)
+++ trunk/src/tmcsim/highwaymodel/StationComparator.java	(revision 422)
@@ -0,0 +1,53 @@
+package tmcsim.highwaymodel;
+
+import java.util.Comparator;
+
+/**
+ * Compare two stations by route and postmile. 
+ * Used by Highways.toJson() so json is listed by route then postmile
+ * @author jdalbey
+ * @version 4/2/2019
+ */
+public final class StationComparator implements Comparator
+{
+
+    /**
+     * Compare two stations by route and postmile. 
+     */
+    @Override
+    public int compare(Object a, Object b)
+    {
+        // check for identity
+        if (a == b)
+        {
+            return 0;
+        }
+        // check that Object is of type Station, if not throw exception
+        if (!(a instanceof Station && b instanceof Station))
+        {
+            throw new ClassCastException("A Station object expected.");
+        }
+        Station statA = (Station) a;
+        Station statB = (Station) b;
+        // compare by direction field first
+        int i = statA.direction.compareTo(statB.direction);
+        if (i != 0) return i;
+        
+        // get difference of postmile values
+        double val = statA.postmile - statB.postmile;
+        
+        // set appropriate comparable return value
+        int retval = 0;
+        if (val > 0)
+        {
+            retval = 1;
+        }
+        else if (val < 0)
+        {
+            retval = -1;
+        }
+
+        return retval;
+    }
+
+}
Index: trunk/src/tmcsim/highwaymodel/Highway.java
===================================================================
--- trunk/src/tmcsim/highwaymodel/Highway.java	(revision 422)
+++ trunk/src/tmcsim/highwaymodel/Highway.java	(revision 422)
@@ -0,0 +1,59 @@
+package tmcsim.highwaymodel;
+
+import tmcsim.highwaymodel.Station.DIRECTION;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * Highway represents a freeway that has two directions of traffic. A highway is
+ * identified by its highway number.  A highway contains lane detector stations,
+ * called Stations, along its length.
+ *
+ * @author jdalbey
+ */
+final public class Highway implements Comparable<Highway>
+{
+    /** The identifying number for this highway, e.g., 101 */
+    public final Integer routeNumber;
+    /** The ordered list of stations (lane detector stations) on this highway */
+    public final List<Station> stations;
+    /** The directions for this highway, either N/S or E/W */
+    public final Set<DIRECTION> availDirs = new TreeSet<DIRECTION>();
+    
+    /** Construct a highway 
+     * 
+     * @param highwayNum integer identifier for this highway
+     * @param stations ordered list of stations on this highway
+     */
+    public Highway(Integer routeNumber, ArrayList<Station> stations)
+    {
+        this.routeNumber = routeNumber;
+        this.stations = stations;
+        // Get available directions for route
+        if (stations != null)
+        {
+            for(Station stn : stations)
+            {
+                availDirs.add(stn.direction);
+            }
+        }
+    }
+    
+    @Override
+    public String toString()
+    {
+        return Integer.toString(this.routeNumber);
+    }
+
+    @Override
+    public int compareTo(Highway other)
+    {
+        int otherRoute = ((Highway) other).routeNumber; 
+        //ascending order
+        return this.routeNumber - otherRoute;        
+    }
+}
Index: trunk/src/tmcsim/highwaymodel/TrafficEvent.java
===================================================================
--- trunk/src/tmcsim/highwaymodel/TrafficEvent.java	(revision 422)
+++ trunk/src/tmcsim/highwaymodel/TrafficEvent.java	(revision 422)
@@ -0,0 +1,81 @@
+
+package tmcsim.highwaymodel;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Scanner;
+
+
+/**
+ * Traffic Event represents some occurrence in the traffic on 
+ * a highway network.  A traffic event occurs at a particular time
+ * and belongs to a unique simulation incident.  The event occurs on 
+ * a specified section of a given highway route.  Each event specifies
+ * the level of traffic congestion by a color.  Events are comparable
+ * by the time of their occurrence.
+ * @author jdalbey
+ */
+public final class TrafficEvent implements Comparable<TrafficEvent>
+{
+    public final String incident;
+    public final String eventTime;
+    public final Date eventDate;  // for convenience
+    public final int routeNumber;
+    public final LoopDetector.DOTCOLOR color;
+    public final Station.DIRECTION dir;
+    public final double postmile;
+    public final double range;
+    public final String rawString;
+    
+    private final static SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
+
+    /** Create an event from a string as in this example:
+     * 181 00:12:30 405 S 0.6 11.0 G
+     * @param eventString
+     * @return traffic event
+     * @throws Scanner exception if string improperly formatted
+     */
+    public TrafficEvent(String eventString) throws ParseException
+    {
+        this.rawString = eventString;
+        Scanner lineScan = new Scanner(eventString);
+        this.incident = lineScan.next();
+        this.eventTime = lineScan.next(); // time field
+        // may throw parseexception
+        this.eventDate = formatter.parse(eventTime);
+        this.routeNumber = lineScan.nextInt();
+        this.dir = Station.DIRECTION.toDirection(lineScan.next());
+        this.postmile = lineScan.nextDouble();
+        this.range = lineScan.nextDouble();
+        this.color = LoopDetector.DOTCOLOR.toDotColor(lineScan.next());    
+    }
+
+    @Override
+    public int compareTo(TrafficEvent o)
+    {
+        return eventDate.compareTo(o.eventDate);
+    }
+    
+    @Override
+    public String toString()
+    {
+        return rawString;
+    }
+    @Override 
+    public boolean equals(Object other)
+    {
+        Boolean result = false;
+        if (other == null) return false;
+        if ( other instanceof TrafficEvent  )
+        {
+          TrafficEvent that = (TrafficEvent) other;
+          result = that.incident.equals(this.incident)
+                  && that.eventTime.equals(this.eventTime)
+                  && ((int) that.postmile) == ((int) this.postmile)
+                  && that.dir == this.dir
+                  && that.color == this.color;
+        }
+        return result;    
+    }            
+}
Index: trunk/src/tmcsim/highwaymodel/Station.java
===================================================================
--- trunk/src/tmcsim/highwaymodel/Station.java	(revision 422)
+++ trunk/src/tmcsim/highwaymodel/Station.java	(revision 422)
@@ -0,0 +1,403 @@
+package tmcsim.highwaymodel;
+
+import tmcsim.highwaymodel.LoopDetector.DOTCOLOR;
+import java.util.ArrayList;
+import java.util.List;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A Station (VDS or Vehicle Detector Station) represents a group of lane detectors
+ * across all lanes in ONE direction at a particular point on a highway. A station is identified
+ * by its highway number and postmile. A station has an associated direction
+ * used to establish which direction is Main and which is Opposite. The MLTotVol
+ * and OppTotVol for a station can be dynamically updated. A station has other
+ * attributes: lineNum, vdsID, drop, and location which are used by the FEP. A
+ * station can be compared to other stations by its postmile.
+ *
+ * @author John A. Torres, jdalbey
+ * @version 9/10/2017, 3/22/2019
+ */
+public final class Station implements Comparable
+{
+
+    /* Static Station meta data */
+    final public int lineID;
+    final public int vdsID; // double check
+    final public int drop;
+    final public String location;
+    final public List<LoopDetector> loops;
+    final public int routeNumber;
+    final public double postmile;
+    final public DIRECTION direction;
+
+    /* Dynamic Station data */
+    private int MLTotVol;
+    private int OppTotVol;
+
+    /* Constructor */
+    public Station(int lineID, int vdsID, int drop,
+            String location, List<LoopDetector> loops, int hwy,
+            DIRECTION direction, double postmile)
+    {
+        this.lineID = lineID;
+        this.vdsID = vdsID;
+        this.drop = drop;
+        this.loops = loops;
+        this.location = location;
+        this.postmile = postmile;
+        this.direction = direction;
+        this.routeNumber = hwy;
+
+        this.MLTotVol = getMLTotVol();
+        this.OppTotVol = getOPPTotVol();
+    }
+
+    /**
+     * Calculates the total ML Volume.
+     *
+     * @return total ML volume.
+     */
+    private int getMLTotVol()
+    {
+        int mlTotVol = 0;
+        for (LoopDetector loop : loops)
+        {
+            if (loop.loopLocation.startsWith("ML"))
+            {
+                mlTotVol += loop.vol;
+            }
+        }
+        return mlTotVol;
+    }
+
+    /**
+     * Calculates the total OPP Volume
+     *
+     * @return total OPP volume.
+     */
+    private int getOPPTotVol()
+    {
+        int oppTotVol = 0;
+        for (LoopDetector loop : loops)
+        {
+            if (loop.loopLocation.startsWith("OS"))
+            {
+                oppTotVol += loop.vol;
+            }
+        }
+        return oppTotVol;
+    }
+
+    /**
+     * Returns a string of highways data. If MetaDataOnly is true, you get a
+     * full dump of the highways meta data, which does not include dynamic loop
+     * values, and does include the string location names. If MetaDataOnly is
+     * false, dynamic loop values are included, and unnecessary information like
+     * string location values are included.
+     *
+     * The FEPSimulator takes in the toCondensedFormat() output, with a
+     * MetaDataOnly value of false, over the socket.
+     *
+     * The MetaDataOnly flag should be used to get a full dump of the highways
+     * information. This was used to get the highways_fullmap.txt output.
+     *
+     * @param MetaDataOnly Whether you want meta data, or a full dump for FEPSim
+     * @return String, highways data in condensed format
+     */
+    public String toCondensedFormat(boolean MetaDataOnly)
+    {
+        StringBuilder build = new StringBuilder();
+        build.append(Integer.toString(this.vdsID));
+        build.append(" ");
+        build.append(Integer.toString(this.drop));
+        build.append(" ");
+        build.append(Integer.toString(this.routeNumber));
+        build.append(" ");
+        build.append(this.direction.getLetter());
+        build.append(" ");
+        build.append(Double.toString(this.postmile));
+        build.append(" ");
+        build.append(Integer.toString(loops.size()));
+        build.append(" ");
+        if (MetaDataOnly)
+        {
+            build.append(this.location);
+        }
+        build.append("\n");
+        for (LoopDetector loop : loops)
+        {
+            build.append(loop.toCondensedFormat(MetaDataOnly));
+        }
+        return build.toString();
+    }
+
+    /**
+     * Compare this Station to another by postmile. Note: This might be better
+     * as a Comparator since it checks only one field.
+     */
+    @Override
+    public int compareTo(Object otherStation)
+    {
+        // check for identity
+        if (this == otherStation)
+        {
+            return 0;
+        }
+        // check that Object is of type Station, if not throw exception
+        if (!(otherStation instanceof Station))
+        {
+            throw new ClassCastException("A Station object expected.");
+        }
+
+        // get difference of values
+        double otherStationPostmile = ((Station) otherStation).postmile;
+        double val = this.postmile - otherStationPostmile;
+
+        // set appropriate comparable return value
+        int retval = 0;
+        if (val > 0)
+        {
+            retval = 1;
+        }
+        else if (val < 0)
+        {
+            retval = -1;
+        }
+
+        return retval;
+    }
+
+    /**
+     * See if this station matches the specified attributes.
+     * @param dir
+     * @param postmile
+     * @return true if this station's attributes match the given ones.
+     */
+    public boolean matches(DIRECTION dir, double postmile)
+    {
+        double val = this.postmile - postmile;
+        return (Math.abs(val) < 0.01) && this.direction.equals(dir);
+    }
+    /**
+     * Determine which lane fields to update based on given direction and update
+     * all the loop detectors with the given color.
+     *
+     * @param direction desired highway direction
+     * @param dotColor desired dot color
+     */
+    public void updateByDirection(DIRECTION direction, DOTCOLOR dotColor)
+    {
+        // Is this station going in the desired direction?
+        if (direction.equals(this.direction))
+        {
+            outputUpdateMessage(dotColor, direction.toString());
+
+            // Set the values for all lanes at this station
+            for (LoopDetector loop : loops)
+            {
+                // Set loop detector attributes given the desired color
+                loop.setAttributes(dotColor);
+            }
+
+            this.MLTotVol = getMLTotVol();
+            this.OppTotVol = getOPPTotVol();
+        }
+    }
+    /**
+     * Compute the color for the lanes in a given direction.
+     * @return DOTCOLOR of this station's traffic flow
+     */
+    public DOTCOLOR getColor()
+    {
+        /* For now just use the color of the first lane. 
+         * TODO: Average the color in ALL the lanes  */
+
+        String laneDir = "";
+        
+        // FOR FUTURE USE we will need to examine all detectors for this station
+        // and perform an average
+        // for (LoopDetector loop : loops)
+        {
+            // for now, Return color according to loop volume of first lane
+            if (loops.get(0).vol == 1)
+            {
+                return DOTCOLOR.RED;
+            }
+            if (loops.get(0).vol == 3)
+            {
+                return DOTCOLOR.YELLOW;
+            }
+            if (loops.get(0).vol == 0)
+            {
+                return DOTCOLOR.GREEN;
+            }
+        }
+        
+        // Default case for invalid data
+        return DOTCOLOR.GREEN;
+    }
+
+    /**
+     * Output for updateByDirection. Logs the update to the console.
+     *
+     * @param dotcolor
+     * @param OPP_ML
+     */
+    private void outputUpdateMessage(DOTCOLOR dotcolor, String OPP_ML)
+    {
+        System.out.printf("Updating %-3.3s %-5.5s %-3.3s lanes\t %-12.12s "
+                + "at postmile %-6.6s to %-7.7s\n",
+                Integer.toString(this.routeNumber), this.direction.name(),
+                OPP_ML, this.location, Double.toString(this.postmile),
+                dotcolor.name());
+    }
+
+    /**
+     * XML tags used for toXML() method.
+     */
+    private static enum XML_TAGS
+    {
+
+        STATION("Station"),
+        LDS_ID("LDS_ID"),
+        LINE_NUM("Line_Num"),
+        DROP("Drop"),
+        LOOPS("Loops"),
+        LOCATION("Location"),
+        POST_MILE("Post_Mile"),
+        DIRECTION("Direction"),
+        FREEWAY("Freeway"),
+        ML_TOT_VOL("ML_Tot_Vol"),
+        OPP_TOT_VOL("Opp_Tot_Vol");
+
+        String tag;
+
+        private XML_TAGS(String n)
+        {
+            tag = n;
+        }
+    }
+
+    /**
+     * Returns the Station data in XMLFormat.
+     *
+     * @param currElem The current XML <Station> element
+     */
+    public void toXML(Element currElem)
+    {
+        Document theDoc = currElem.getOwnerDocument();
+
+        Element stationElement = theDoc.createElement(XML_TAGS.STATION.tag);
+        currElem.appendChild(stationElement);
+
+        Element ldsIDElement = theDoc.createElement(XML_TAGS.LDS_ID.tag);
+        ldsIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.vdsID)));
+        stationElement.appendChild(ldsIDElement);
+
+        Element lineNumElement = theDoc.createElement(XML_TAGS.LINE_NUM.tag);
+        lineNumElement.appendChild(theDoc.createTextNode(String.valueOf(this.lineID)));
+        stationElement.appendChild(lineNumElement);
+
+        Element dropElement = theDoc.createElement(XML_TAGS.DROP.tag);
+        dropElement.appendChild(theDoc.createTextNode(String.valueOf(this.drop)));
+        stationElement.appendChild(dropElement);
+
+        Element locationElement = theDoc.createElement(XML_TAGS.LOCATION.tag);
+        locationElement.appendChild(theDoc.createTextNode(this.location));
+        stationElement.appendChild(locationElement);
+
+        Element postMileElement = theDoc.createElement(XML_TAGS.POST_MILE.tag);
+        postMileElement.appendChild(theDoc.createTextNode(String.valueOf(this.postmile)));
+        stationElement.appendChild(postMileElement);
+
+        Element directionElement = theDoc.createElement(XML_TAGS.DIRECTION.tag);
+        directionElement.appendChild(theDoc.createTextNode("" + this.direction.getLetter()));
+        stationElement.appendChild(directionElement);
+
+        Element freewayElement = theDoc.createElement(XML_TAGS.FREEWAY.tag);
+        freewayElement.appendChild(theDoc.createTextNode(String.valueOf(this.routeNumber)));
+        stationElement.appendChild(freewayElement);
+
+        Element mlElement = theDoc.createElement(XML_TAGS.ML_TOT_VOL.tag);
+        mlElement.appendChild(theDoc.createTextNode(String.valueOf(this.MLTotVol)));
+        stationElement.appendChild(mlElement);
+
+        Element oppElement = theDoc.createElement(XML_TAGS.OPP_TOT_VOL.tag);
+        oppElement.appendChild(theDoc.createTextNode(String.valueOf(this.OppTotVol)));
+        stationElement.appendChild(oppElement);
+
+        Element loopsElement = theDoc.createElement(XML_TAGS.LOOPS.tag);
+        stationElement.appendChild(loopsElement);
+
+        for (LoopDetector loop : loops)
+        {
+            loop.toXML(loopsElement);
+        }
+    }
+
+    /**
+     * Enum for freeway direction.
+     *
+     * @author John A. Torres
+     * @version 9/10/2017
+     */
+    public static enum DIRECTION
+    {
+        NORTH,
+        SOUTH,
+        EAST,
+        WEST;
+
+        // All the first letters of the values, in order.
+        private static String allLetters = "NSEW";
+
+        /**
+         * Return the first letter of this enum.
+         *
+         * @return String first letter of this enum.
+         */
+        public String getLetter()
+        {
+            return this.toString().substring(0, 1);
+        }
+        
+        public DIRECTION getOpposite()
+        {
+            switch (this)
+            {
+                case NORTH:
+                    return SOUTH;
+                case SOUTH:
+                    return NORTH;
+                case EAST:
+                    return WEST;
+                case WEST:
+                    return EAST;
+            }
+            return null;
+        }
+
+        /**
+         * Returns a direction given its first character.
+         *
+         * @param letter the first character of a direction
+         * @return direction corresponding to letter
+         * @pre letter must be one of allLetters
+         */
+        public static DIRECTION toDirection(String letter)
+        {
+            if(letter.indexOf(letter.charAt(0)) == -1)
+            {
+                return null;
+            }
+            return values()[allLetters.indexOf(letter.charAt(0))];
+        }
+    }
+    
+    @Override
+    public String toString()
+    {
+        return Integer.toString(this.vdsID)+this.getColor();
+    }
+}
Index: trunk/src/tmcsim/highwaymodel/Highways.java
===================================================================
--- trunk/src/tmcsim/highwaymodel/Highways.java	(revision 422)
+++ trunk/src/tmcsim/highwaymodel/Highways.java	(revision 422)
@@ -0,0 +1,426 @@
+package tmcsim.highwaymodel;
+
+import atmsdriver.trafficeventseditor.TrafficLaneEvent;
+import tmcsim.highwaymodel.Station.DIRECTION;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * Highways represents California state highways supervised by CalTrans. 
+ * The highways have sensors to detect traffic flow.  In the simulation
+ * the traffic flow is artificially created and Highways maintains the
+ * current levels of traffic flow throughout the network.
+ *
+ * Highways builds an internal representation of the highway network
+ * from VDS data (obtained from PeMS) The current state of the network
+ * is output to a json file for use by CPTMS. 
+ *
+ * @author John A. Torres, jdalbey
+ */
+final public class Highways
+{
+    final public List<Highway> highways;
+
+    public Highways(String highwaysMapFileName)
+    {
+       // build highways data structure
+        this.highways = buildHighwayNetwork(highwaysMapFileName);
+    }
+    
+    private ArrayList<Highway> buildHighwayNetwork(String highwaysMapFileName)
+    {
+        // NOTE: Could this method be streamlined? Is it necessary to have the
+        // second data structure?
+        System.out.println("Building highways...");
+        // The list of highways to return
+        ArrayList<Highway> highways = new ArrayList<Highway>();
+        
+        // map of hwy number to its list of stations
+        Map<Integer, ArrayList<Station>> highwayMap = new HashMap<>();
+        
+        // Open the postmile file and scan each line
+        File file = new File(highwaysMapFileName);
+        try 
+        {
+            Scanner scanner = new Scanner(file);
+            while (scanner.hasNext())
+            {
+                Station station = loadStation(scanner); 
+                Integer hwyNum = station.routeNumber;
+                // if the map does not contain an entry for the highway, create
+                // a new entry (key/value pair) for the highway and instantiate
+                // the empty list of stations
+                if (!highwayMap.containsKey(hwyNum))
+                {
+                    ArrayList<Station> stnList = new ArrayList<>();
+                    stnList.add(station);
+                    highwayMap.put(hwyNum, stnList);
+                } 
+                // if the map does have an entry for the highway, add the current
+                // station to its list of stations
+                else
+                {
+                    highwayMap.get(hwyNum).add(station);
+                }
+            }
+        }catch (FileNotFoundException e) {
+            e.printStackTrace();
+        }
+        // get the set of highway numbers
+        Set<Integer> hwyKeys = highwayMap.keySet();
+        // get the highway number and associated stations and create a new hwy
+        // and add the hwy to this.highways
+        for (Integer hwyKey : hwyKeys)
+        {
+            ArrayList<Station> hwyStations = highwayMap.get(hwyKey);
+            Collections.sort(hwyStations);
+            System.out.println("Loaded highway " + hwyKey + " with " +
+                    hwyStations.size() + " stations.");
+            highways.add(new Highway(hwyKey,
+                    hwyStations));
+        }
+        System.out.println("");
+        return highways;
+    }
+
+    /** Search for a station with the given attributes 
+     * 
+     * @param routeNumber
+     * @param direction
+     * @param postmile
+     * @return the desired station, or null if not found.
+     */
+    public Station findStation(Integer routeNumber, Station.DIRECTION direction,
+            Double postmile)
+    {
+        // Get the highway by route number
+        Highway highway = getHighwayByRouteNumber(routeNumber);
+        if (highway == null)
+        {
+            Logger.getLogger(Highways.class.getName()).log(Level.SEVERE,  
+                    "Highway "+routeNumber+" not found in findStation()", "");
+            return null;
+        }
+        //Search the stations on this highway for a match
+        for (Station station : highway.stations)
+        {
+            if (station.matches(direction, postmile))
+            {
+                return station;
+            }
+        }
+        return null;
+    }
+    /**
+     * Applies specified color to the specified highway stretch. Route number
+     * and direction specify the highway. Postmile and range specify the stretch
+     * of specified highway. 
+     * The purpose of this method is to modify the highway state to represent 
+     * traffic conditions created by the Traffic Manager.  These conditions 
+     * originate in the traffic events file which specifies traffic congestion arising
+     * during the simulation.  NOTE: Since these events describe congestion,
+     * the direction that the color should be applied is the REVERSE of the
+     * regular flow of traffic.  
+     * So a request to apply red to 55 S from 8.5 for 2 miles means 
+     * the stretch 8.5 -> 10.5 because sobo traffic normally flows toward
+     * decreasing postmiles and we want to do the reverse.
+     * @param routeNumber highway route number
+     * @param direction highway direction (for normal traffic flow)
+     * @param postmile origin postmile value
+     * @param range range from origin postmile
+     * @param dotColor the color to be applied to specified highway stretch
+     */
+    public void applyColorToHighwayStretch(Integer routeNumber, Station.DIRECTION direction,
+            Double postmile, Double range, LoopDetector.DOTCOLOR dotColor)
+    {
+        System.out.println("Applying " + dotColor.name() + " dots to highway "
+                + routeNumber + " " + direction.name() + " at postmile "
+                + postmile + " with a range of " + range + " miles...");
+
+        // Get the highway by route number
+        Highway highway = getHighwayByRouteNumber(routeNumber);
+        // This check added to fix defect #118. Handles situation when the 
+        // events file specifies a highway that doesn't exist in the network.
+        if (highway == null)
+        {
+            Logger.getLogger(Highways.class.getName()).log(Level.SEVERE,  
+                    "Highway "+routeNumber+" not found trying to applyColor", "");
+            return;
+        }
+        // start value for highway section, and end value for highway section
+        // by postmile
+        Double startPost;
+        Double endPost;
+        double epsilon = 0.001;
+
+        // postmiles increase from s to n and w to e
+        // S or W directions backup in a positive postmile direction
+        if (direction.equals(Station.DIRECTION.SOUTH) || direction.equals(Station.DIRECTION.WEST))
+        {
+            // add range value to startPost to get
+            // the end postmile value of the highway section
+            startPost = postmile;
+            endPost = postmile + range;
+            // iterate through the stations, if within the specified highway
+            // stretch, update the station by direction and apply dot color
+            for (Station station : highway.stations)
+            {
+                if (station.postmile >= startPost && station.postmile <= endPost)
+                {
+                    station.updateByDirection(direction, dotColor);
+                }
+            }
+        } 
+        // N or E directions backup in a negative postmile direction
+        else
+        {
+            // subtract range value from startPost
+            // to get the end postmile value of the highway section
+            startPost = postmile;
+            endPost = postmile - range;
+
+            // iterate through the stations, if within the specified highway
+            // section, update the station by direction and apply dot color
+            for (Station station : highway.stations)
+            {
+                if (station.postmile <= startPost && station.postmile >= endPost)
+                {
+                    station.updateByDirection(direction, dotColor);
+                }
+            }
+        }
+        System.out.println("");
+    }
+    
+    
+    /**
+     * Loads a single Station from the postmile coordinates file
+     * @param sc scanner at the current station line
+     * @return Station
+     */
+    private Station loadStation(Scanner sc)
+    {
+        String line = sc.nextLine();
+        Scanner scline = new Scanner(line);
+        scline.useDelimiter(",");
+        
+        String route  = scline.next(); // FWY DIR POSTMILE
+        scline.next();  // skip lat
+        scline.next();  // skip long
+        String description = scline.next(); // the description of the location
+
+        Scanner rteScan = new Scanner(route);
+        int fwy = rteScan.nextInt();
+        DIRECTION dir = DIRECTION.toDirection(rteScan.next());
+        double postmile = rteScan.nextDouble();
+
+        ArrayList<LoopDetector> loops = new ArrayList<>();
+        // For now we'll use just a dummy loop detector
+        LoopDetector detector = new LoopDetector(1,"ML","ML_1");
+        loops.add(detector);
+
+        return new Station(11, 123, 99, description, loops, fwy, dir, postmile);
+    }
+     
+    /**
+     * Returns a highway by given highway number.
+     * 
+     * @param routeNum
+     * @return Highway with specified route number, or null if no highway with
+     *          the specified route num
+     */
+    public Highway getHighwayByRouteNumber(Integer routeNum)
+    {
+        Highway returnHwy = null;
+        // search through highways and check routeNums
+        for (Highway hwy : highways)
+        {
+            if (hwy.routeNumber.equals(routeNum))
+            {
+                returnHwy = hwy;
+                break;
+            }
+        }
+        return returnHwy;
+    }
+
+    /** Return a string representation of the Highways - for debugging */
+    public String toString()
+    {
+        StringBuilder result = new StringBuilder();
+        for (Highway hwy: highways)
+        {
+            // Consider each route direction
+            for (DIRECTION dir: hwy.availDirs)
+            {
+                String rowLabel = ""+String.format("%3s ",hwy.routeNumber)+dir.getLetter()+' ';
+                StringBuilder lineout = new StringBuilder();
+                // Examine every station on this highway and direction
+                for (Station station: hwy.stations)
+                {
+                    if (station.direction.equals(dir))
+                    {
+                    //lineout.append("" + dir.getLetter() + stat.postmile);
+                    lineout.append(station.getColor().symbol());
+                    //lineout.append("  ");
+                    }
+                    else 
+                    {
+                        lineout.append(".");
+                    }
+                }
+                // See if there were stations for this direction
+                String checkMe = lineout.toString().trim();
+                // if any stations were colored, output the line
+                if (checkMe.length() > 1)
+                {
+                    result.append(rowLabel);
+                    result.append(lineout + "\n");
+                }
+            }
+        }
+        result.append("\n");
+        return result.toString();
+    }
+    /** Return a json representation of the Highways, readable by Google Maps */
+    public String toJson()
+    {
+        // TODO: move loading this file to init method so it doesn't get 
+        // called every time.
+        PostmileCoords pmList = new PostmileCoords();
+        FileInputStream fis = null;
+        try
+        {
+            fis = new FileInputStream("config/vds_data/postmile_coordinates.txt");
+        }
+        catch (FileNotFoundException ex)
+        {
+            Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex);
+        }
+        Scanner s = new Scanner(fis).useDelimiter("\\A");
+        pmList.load(s);
+        
+        Collections.sort(highways);  // Sort the highways for easier inspection
+        String header = "{\n" +
+        "  \"type\": \"FeatureCollection\",\n" +
+        "  \"features\": [";
+        StringBuilder result = new StringBuilder();
+        result.append(header);
+        for (Highway hwy: highways)
+        {
+            // Examine every station on this highway
+            StringBuilder lineout = new StringBuilder();
+            Collections.sort(hwy.stations, new StationComparator());
+            for (Station stat: hwy.stations)
+            {
+                String pmID = "" + hwy.routeNumber + " " 
+                        + stat.direction.getLetter() + " " 
+                        + stat.postmile;
+                PostmileCoords.Postmile currentPM = pmList.find(pmID);
+                if (currentPM == null)
+                { 
+                Logger.getLogger(Highways.class.getName()).log(Level.INFO, 
+                        "Postmile Coords lookup couldn't find Station: "+pmID,
+                        " ");
+                }
+                if (currentPM != null)
+                {    
+                    //lineout.append("" + dir.getLetter() + stat.postmile);
+                    //lineout.append(stat.getColorByDirection(dir));
+                    String outString = currentPM.toJson();
+                    // replace the color code with the color name
+                    String colorName=stat.getColor().htmlColor();
+                    outString = outString.replace("desiredcolor",colorName);
+                    lineout.append(outString);
+                    lineout.append("  ");
+                }
+            }
+            //result.append(rowLabel);
+            result.append(lineout + "\n");
+
+        }
+        // remove last trailing comma
+        result.replace(result.lastIndexOf(","), result.lastIndexOf(",") + 1, " "  );
+
+        result.append("  ]\n" +  "}");
+        return result.toString();
+    }
+    
+    /**
+     * Generates the route number list, used for user input validation.
+     * @return list of route numbers.
+     */
+    public List<Integer> getAllRouteNums()
+    {
+        ArrayList<Integer> routeNums = new ArrayList<>();
+        // add the route number for each highway to the list
+        for(Highway hwy : highways)
+        {
+            routeNums.add(hwy.routeNumber);
+        }
+        return routeNums;
+    }
+    
+    /**
+     * XML tags used in writeToXML()
+     */
+    private static enum XML_TAGS
+    {
+
+        NETWORK("Network");
+
+        String tag;
+
+        private XML_TAGS(String n)
+        {
+            tag = n;
+        }
+    }
+    
+    /** Reset all the traffic levels to free flowing (green) */
+    public void reset()            
+    {
+        for(Highway hwy: highways)
+        {
+            for(Station stn : hwy.stations)
+            {
+                for(LoopDetector ld : stn.loops)
+                {
+                    ld.setAttributes(LoopDetector.DOTCOLOR.GREEN);
+                }
+            }
+        }
+    }
+    
+    public void applyTrafficLaneEvent(TrafficLaneEvent event)
+    {
+        Integer routeNum = event.routeNum;
+        Highway hwy = getHighwayByRouteNumber(routeNum);
+        for(Station stn: hwy.stations)
+        {
+            if(stn.equals(event.station))
+            {
+                for(LoopDetector ld : stn.loops)
+                {
+                    if(ld.equals(event.loopDetector))
+                    {
+                        ld.occ = event.color.occupancy();
+                        ld.vol = event.color.volume();
+                        break;
+                    }
+                }
+                break;
+            }
+        }
+    }
+}
Index: trunk/src/tmcsim/highwaymodel/LoopDetector.java
===================================================================
--- trunk/src/tmcsim/highwaymodel/LoopDetector.java	(revision 422)
+++ trunk/src/tmcsim/highwaymodel/LoopDetector.java	(revision 422)
@@ -0,0 +1,228 @@
+package tmcsim.highwaymodel;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/** 
+ *  A LoopDetector represents a single detector for a single lane in a network.
+ * 
+ *  A LoopDetector contains static meta data, and three dynamic attributes: vol,
+ *  occ, and spd.
+ *
+ * Lane Type 	A string indicating the type of lane. Possible values (and their meaning) are:
+ *
+ *    CD (Coll/Dist)
+ *    CH (Conventional Highway)
+ *    FF (Fwy-Fwy connector)
+ *    FR (Off Ramp)
+ *    HV (HOV)
+ *    ML (Mainline)
+ *    OR (On Ramp)
+ * @author John A. Torres
+ * @version 09/10/2017
+ */
+public class LoopDetector 
+{
+    /* static data */
+    final public int loopID;
+    final public String loopLocation;
+    final public String loopLocationID;
+    
+    /* dynamic data */
+    public int vol;
+    public float occ;
+    
+    /**
+     * Constructs a LoopDetector from loopID, loopLocation, and laneNum
+     * with initially free flowing traffic.
+     * 
+     * @param loopID
+     * @param loopLocation
+     * @param laneNum 
+     */
+    public LoopDetector(int loopID, String loopLocationID, String loopLocation)
+    {
+        /* Set static data */
+        this.loopID = loopID;
+        this.loopLocation = loopLocation;
+        this.loopLocationID = loopLocationID;
+        /* Init dynamic data */
+        this.vol = 0;
+        this.occ = 0;
+    }
+    
+    /** 
+     * Setter for loop detector dynamic attributes.  Reserved for future use
+     * with "live" highway data.
+     * @param vol volume
+     * @param occ occupancy
+     * @param spd speed not used
+     */
+    public void setAttributes(int vol, float occ)
+    {
+        this.vol = vol;
+        this.occ = occ;
+    }
+    /** Set the attributes of this detector given a color.
+     * @param DOTCOLOR of the attributes to assign. 
+     */
+    public void setAttributes(DOTCOLOR color)
+    {
+        this.vol = color.volume();
+        this.occ = color.occupancy();
+    }
+    /**
+     * XML tags used for toXML() method.
+     */
+    private static enum XML_TAGS
+    {
+        LOOP_ID("Loop_ID"),
+        LOOP_LOCATION("Loop_Location"),
+        VOL("Vol"),
+        OCC("Occ"),
+        LOOP("Loop");
+        
+        String tag;
+        
+        private XML_TAGS(String n)
+        {
+            tag = n;
+        }
+    }
+    
+    /** Returns a string of highways data. If MetaDataOnly is true, you get a full
+     *  dump of the highways meta data, which does not include dynamic loop values,
+     *  and does include the string location names. If MetaDataOnly is false,
+     *  dynamic loop values are included, and unnecessary information like string
+     *  location values are included.
+     * 
+     *  The FEPSimulator takes in the toCondensedFormat() output, with a MetaDataOnly
+     *  value of false, over the socket.
+     * 
+     *  The MetaDataOnly flag should be used to get a full dump of the highways
+     *  information. This was used to get the highways_fullmap.txt output.
+     * 
+     * @param MetaDataOnly Whether you want meta data, or a full dump for FEPSim
+     * @return String, highways data in condensed format
+     */
+    public String toCondensedFormat(boolean MetaDataOnly)
+    {
+        StringBuilder build = new StringBuilder();
+        build.append(Integer.toString(this.loopID));
+        build.append(" ");
+        if(!MetaDataOnly)
+        {
+            build.append(" ");
+            build.append(this.occ);
+            build.append(" ");
+            build.append(this.vol);
+            build.append(" ");
+        }
+        else
+        {
+            build.append(this.loopLocationID);
+            build.append(" ");
+        }
+        build.append(this.loopLocation);
+        build.append("\n");
+        return build.toString();
+    }
+
+    /**
+     * Returns the LoopDetector data in XMLFormat
+     * 
+     * @param currElem The current XML <LoopDetector> element
+     */
+    public void toXML(Element currElem)
+    {
+        Document theDoc = currElem.getOwnerDocument();
+        
+        Element loopElement = theDoc.createElement(XML_TAGS.LOOP.tag);
+        currElem.appendChild(loopElement);
+        
+        Element loopIDElement = theDoc.createElement(XML_TAGS.LOOP_ID.tag);
+        loopIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.loopID)));
+        loopElement.appendChild(loopIDElement);
+        
+        Element loopLocElement = theDoc.createElement(XML_TAGS.LOOP_LOCATION.tag);
+        loopLocElement.appendChild(theDoc.createTextNode(this.loopLocation));
+        loopElement.appendChild(loopLocElement);
+        
+        Element volElement = theDoc.createElement(XML_TAGS.VOL.tag);
+        volElement.appendChild(theDoc.createTextNode(String.valueOf(this.vol)));
+        loopElement.appendChild(volElement);
+        
+        Element occElement = theDoc.createElement(XML_TAGS.OCC.tag);
+        occElement.appendChild(theDoc.createTextNode(String.valueOf(this.occ)));
+        loopElement.appendChild(occElement);
+    }
+    
+    /**
+     * Enum for highway status dot colors. Each color has associated volume
+     * and occupancy constants, single character symbol, and hml color name.
+     *
+     * @author John A. Torres, jdalbey
+     * @version 10/11/2017
+     */
+    public static enum DOTCOLOR {
+
+        RED(1, 0.06f,'@',"red"),    // "Stopped" is less than 25mph
+        YELLOW(3,0.059f,'+',"yellow"), // speed = 26
+        GREEN(0,0,'-',"lime");       // freeflowing
+        
+        // All the first letters of the values, in order.
+        public static String allLetters = "RYG";
+        
+        private int vol;  /* volume */
+        private float occ;  /* occupancy */      
+        private char symbol; /* symbolic representation of this color */
+        private String htmlColor; /* html color name */
+        
+        
+        private DOTCOLOR(int v, float o, char symbol, String htmlColor)
+        {
+            vol = v;
+            occ = o;
+            this.symbol = symbol;
+            this.htmlColor = htmlColor;
+        }
+        /**
+         * Return the first letter of this enum.
+         *
+         * @return String first letter of this enum.
+         */
+        public String getLetter() {
+            return this.toString().substring(0, 1);
+        }
+
+        public int volume()
+        {
+            return vol;
+        }
+        public float occupancy()
+        {
+            return occ;
+        }
+        public char symbol()
+        {
+            return symbol;
+        }
+        public String htmlColor()
+        {
+            return htmlColor;
+        }
+        /**
+         * Returns a DOTCOLOR given its first character.
+         *
+         * @param letter the first character of a DOTCOLOR
+         * @return DOTCOLOR corresponding to letter
+         * @pre letter must be one of allLetters
+         */
+        public static DOTCOLOR toDotColor(String letter) {
+            return values()[allLetters.indexOf(letter.charAt(0))];
+        }
+    }  
+    
+}
Index: trunk/src/tmcsim/highwaymodel/PostmileCoords.java
===================================================================
--- trunk/src/tmcsim/highwaymodel/PostmileCoords.java	(revision 422)
+++ trunk/src/tmcsim/highwaymodel/PostmileCoords.java	(revision 422)
@@ -0,0 +1,161 @@
+
+package tmcsim.highwaymodel;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * PostmileCoords is a collection of Postmiles (id and LatLong Coordinates).
+ * @author jdalbey
+ */
+public class PostmileCoords implements Iterable
+{
+    private List<Postmile> postmileList;
+    public PostmileCoords()
+    {
+        postmileList = new ArrayList<Postmile>();
+    }
+    /** Accessor to value at given index */
+    public Postmile get(int idx)
+    {
+        return postmileList.get(idx);
+    }
+    /** Return the size */
+    public int size()
+    {
+        return postmileList.size();
+    }
+    /** Find the postmile with the given name */
+    public Postmile find(String target)
+    {
+        int idx = 0;
+        while (idx < postmileList.size() && !postmileList.get(idx).nameEquals(target))
+        {
+            idx++;
+        }
+        if (idx < postmileList.size())
+        {
+            return postmileList.get(idx);
+        }
+        else
+        {
+            return null;
+        }
+    }
+    /** Load the postmile list from external file */
+    public void load(Scanner scan)
+    {
+        try
+        {
+        String out = scan.next();
+        //  split into an array 
+        String[] results = out.split("\\n");
+        for (String item : results)
+        {
+            String[] fields = item.split(",");
+            String[] nameparts = fields[0].split(" ");
+            String statepm = nameparts[2];
+            // some postmiles come with a prefix, which we ignore
+            if (Character.isLetter(statepm.charAt(0)))
+            {
+                statepm = statepm.substring(1);
+            }  
+            String revisedpm = nameparts[0] + " " + nameparts[1] + " " + statepm;
+            Postmile pm;
+            // If the file has 6 fields per line, include the perpx,y values
+            if (fields.length == 6)
+            {
+                pm = new Postmile(revisedpm,fields[1],fields[2],fields[3],fields[4],fields[5]);
+            }
+            else // otherwise assume the file has just 4 fields
+            {
+                pm = new Postmile(revisedpm,fields[1],fields[2],fields[3]);
+            }
+            postmileList.add(pm);
+        }
+        }
+        catch (Exception ex)  // probably badly formatted file
+        {
+            ex.printStackTrace();
+        }
+    }
+
+    @Override
+    public Iterator iterator()
+    {
+        return postmileList.iterator();
+    }
+    /**
+     *  Postmile is a postmile id and its LatLong Coordinates.
+     */
+    final static class Postmile  
+    {
+        String name;  // the postmile name (Route,Direction,State postmile, e.g., 5 N 6.2)
+        String latitude; // the latitude coordinate for this postmile
+        String longitude; // the longitude coordinate for this postmile
+        String street; // cross street name
+        /* These fields are used by the map to adjust position of dot when zoomed */
+        String perpx="0";  // perpendicular vector, x-component (default value)
+        String perpy="0";  // perpendicular vector, y-component (default value)
+        public Postmile(String name, String lat, String longitude, String street)
+        {
+            this.name = name.trim();
+            this.latitude = lat.trim();
+            this.longitude = longitude.trim();
+            this.street = street.trim();
+        }
+        // This constructor is used if the file contains data for perpendicular vectors
+        public Postmile(String name, String lat, String longitude, String street, String perpx, String perpy)
+        {
+            this.name = name.trim();
+            this.latitude = lat.trim();
+            this.longitude = longitude.trim();
+            this.street = street.trim();
+            this.perpx = perpx.trim();
+            this.perpy = perpy.trim();
+        }
+        public boolean nameEquals(String target)
+        {
+            // remove .0 for comparing strings
+            if (target.endsWith(".0"))
+            {
+                String truncTarget = target.substring(0,target.length()-2);
+                return this.name.equals(truncTarget);
+            }
+            return this.name.equals(target);
+        }
+        @Override public boolean equals(Object aThat) 
+        {
+            if (this == aThat) return true;
+            if (!(aThat instanceof Postmile)) return false;
+            Postmile that = (Postmile) aThat;
+            boolean r1 = this.name.equals(that.name);
+            boolean r2 = this.latitude.equals(that.latitude);
+            boolean r3 = this.longitude.equals(that.longitude);
+            boolean r4 = this.street.equals(that.street);
+            return r1 && r2 && r3 && r4;
+        }
+        @Override public String toString()
+        {
+            return name + ": " + latitude +","+ longitude +","+ street+","+ perpx +","+ perpy;
+        }
+        public String toJson()
+        {
+            String pattern =  "\n{\n   \"type\": \"Feature\",\n" +
+                    "   \"id\": \"%s\",\n" +
+                    "   \"geometry\":\n       {\n        \"type\": \"Point\",\n" +
+                    "        \"coordinates\": [%s,%s]\n" +
+                    "       },\n" +
+                    "   \"properties\": \n" +         
+                    "       {\"street\": \"%s\", " +
+                    "\"color\": \"desiredcolor\", " +
+                    "\"perpx\": \"%s\", " +
+                    "\"perpy\": \"%s\"" +
+                    "}\n},";
+
+            return String.format(pattern, name, longitude, latitude, street, perpx, perpy);
+        }
+    }
+}
Index: trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java
===================================================================
--- trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java	(revision 407)
+++ trunk/src/tmcsim/cadsimulator/managers/TrafficModelManager.java	(revision 422)
@@ -2,7 +2,7 @@
 
 import atmsdriver.GoogleMapAnimator;
-import atmsdriver.model.Highways;
-import atmsdriver.model.LoopDetector;
-import atmsdriver.model.TrafficEvent;
+import tmcsim.highwaymodel.Highways;
+import tmcsim.highwaymodel.LoopDetector;
+import tmcsim.highwaymodel.TrafficEvent;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
@@ -129,7 +129,5 @@
             incidents = new HashMap<String, List<TrafficEvent>>();
             highways = new Highways(
-                    props.getProperty(PROPERTIES.HIGHWAYS_MAP_FILE.name),
-                    props.getProperty(PROPERTIES.FEPSIM_IP_ADDR.name),
-                    8080); 
+                    props.getProperty(PROPERTIES.HIGHWAYS_MAP_FILE.name)); 
             this.theCoordinator = theCoordinator;
         }
@@ -211,15 +209,4 @@
         timer.start();
 
-        if (props.getProperty(PROPERTIES.OUTPUT_DEST.name).equals("FEP"))
-        {
-            // Start the FEP thread (to update ATMS every 30 sec). (See class def below)
-            Thread wtfep = new WriteToFEPThread();
-            wtfep.start();
-        }
-        else
-        {
-            Thread wtConsole = new WriteToConsoleThread();
-            wtConsole.start();
-        }
         // Always write to json for google map display
         Thread wtJson = new WriteToJsonThread();
@@ -411,28 +398,4 @@
     }
 
-    class WriteToConsoleThread extends Thread
-    {
-
-        public void run()
-        {
-            System.out.println("WriteToConsole Thread starting.");
-            // Run indefinitely
-            while (true)
-            {
-                 // Write the highway network status to the Console
-                 System.out.println(highways.toString());
-                // Pause the thread
-                try
-                {
-                    Thread.sleep(10000);
-                }
-                catch (InterruptedException ie)
-                {
-                    ie.printStackTrace();
-                }
-            }
-
-        }
-    }
     /** Writes the highway model to a GeoJson file for reading
      *  by Google Maps.
@@ -475,43 +438,4 @@
     }
     
-    class WriteToFEPThread extends Thread
-    {
-
-        public void run()
-        {
-            System.out.println("WriteToFEP Thread starting.");
-            // Run indefinitely
-            boolean running = true;
-            while (running)
-            {
-                try
-                {
-                    // Write the highway network status to the FEP Simulator
-                    highways.writeToFEP();
-                }
-                catch (SimulationException ex)
-                {
-                    // Ask user if they want to proceed without FEP Sim connection
-//                    int reply = JOptionPane.showConfirmDialog(null, "Failed to connect to FEP Sim, proceed anyway?", "Network Failure", JOptionPane.YES_NO_OPTION);
-//                    if (reply == JOptionPane.NO_OPTION)
-//                    {
-//                        System.exit(0);
-//                    }
-                    System.out.println("Skipping writeToFEP...");
-                    running = false;
-                }
-
-                // Wait for FEP Sim to process the data we just sent
-                try
-                {
-                    Thread.sleep(FEPSIM_INTERVAL);
-                }
-                catch (InterruptedException ie)
-                {
-                    ie.printStackTrace();
-                }
-            }
-
-        }
-    }
+    
 }
Index: trunk/src/tmcsim/cadsimulator/viewer/TrafficModelViewPanel.java
===================================================================
--- trunk/src/tmcsim/cadsimulator/viewer/TrafficModelViewPanel.java	(revision 277)
+++ trunk/src/tmcsim/cadsimulator/viewer/TrafficModelViewPanel.java	(revision 422)
@@ -1,5 +1,5 @@
 package tmcsim.cadsimulator.viewer;
 
-import atmsdriver.model.TrafficEvent;
+import tmcsim.highwaymodel.TrafficEvent;
 import java.util.LinkedList;
 import java.util.List;
Index: trunk/src/tmcsim/utilities/BuildHighwayFile.java
===================================================================
--- trunk/src/tmcsim/utilities/BuildHighwayFile.java	(revision 345)
+++ trunk/src/tmcsim/utilities/BuildHighwayFile.java	(revision 422)
@@ -15,4 +15,5 @@
 
 /**
+ * OBSOLETE since deprecating ATMS functionality. No longer used.
  * This utility program is used to create the highway map file used as part
  * of the configuration files needed by the simulator.
Index: trunk/src/tmcsim/application.properties
===================================================================
--- trunk/src/tmcsim/application.properties	(revision 419)
+++ trunk/src/tmcsim/application.properties	(revision 422)
@@ -1,5 +1,5 @@
-#Thu, 20 Jun 2019 14:43:41 -0700
+#Sun, 23 Jun 2019 11:49:46 -0700
 
-Application.revision=417
+Application.revision=419
 
 Application.buildnumber=140
