Index: /trunk/src/tmcsim/utilities/BuildHighwayFile.java
===================================================================
--- /trunk/src/tmcsim/utilities/BuildHighwayFile.java	(revision 272)
+++ /trunk/src/tmcsim/utilities/BuildHighwayFile.java	(revision 272)
@@ -0,0 +1,319 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package tmcsim.utilities;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+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;
+
+/**
+ * This utility program is used to create the highway map file used as part
+ * of the configuration files needed by the simulator.
+ * It merges info from three input files to create highway map file.
+ * Input: 1. VDS file is the district VDS metadata file downloaded from the PeMS
+ *      Data Clearinghouse.  It gives identifying info about each VDS.
+ *      2. Loop detector (lane) file that we found on the ATMS server.
+ *      It lists all the lanes associated with each VDS.       
+ *      3. LDS file that has the fep line number for each LDS.
+ * Output: 1. The highway map file that lists VDS info and the lanes it governs.
+ *      2. A slightly reformatted loop file.
+ * @author jdalbey, jtorres
+ */
+public class BuildHighwayFile
+{
+    final public static String filepath = "config/vds_data/old_vds_data/";
+    final public static String vdsFileName = "d12_vds_meta.txt";
+    final public static String loopFileName = "cleaned_chu_atms_loop_data.txt";
+    final public static String ldsFileName = "cleaned_chu_atms_lds_data.txt";
+    final public static String reformattedLoopFile = "loop.txt";
+    final public static String highwayFile = "highway_stations.txt";
+    /** A dictionary of ldsIDs to VDSids */
+    Map<String,StationAddr> ldsDict;
+    /** A dictionary of FEP line numbers to a list of VDSids */
+    Map<String,List<String>> feplines;
+    /** A dictionary to lookup VDS data given vdsID */
+    Map<String,VehicleDetectionStation> vdsDict;
+    /** A list of ignored VDS id's - FOR DEBUGGING*/
+    List<String> ignored = new ArrayList<String>();
+    /** Reported missing */
+    Set<String> missingVDS = new HashSet<String>();
+    Set<String> missingLDS = new HashSet<String>();
+    
+    public void createHighwayFile()
+    {
+        try
+        {
+            PrintWriter hwyWriter = new PrintWriter(new File(filepath+highwayFile));
+            hwyWriter.print(feplines.size()+"\n");
+            for (String fep_line: feplines.keySet()) // for each fep line
+            {
+                hwyWriter.print(fep_line+" 0 ");
+                List<String> vdsList = feplines.get(fep_line);
+                hwyWriter.print(vdsList.size()+"\n");
+                //    output the vds info
+                for (String vds: vdsList)
+                {
+                    VehicleDetectionStation vdsItem = vdsDict.get(vds);
+                    if (vdsItem == null)
+                    {
+                        System.out.println(vds + " not found in vdsDict");
+                    }
+                    else
+                    {
+                        // Output the VDS identifying info
+                        hwyWriter.print(vdsItem.id + " ");
+                        hwyWriter.print(vdsItem.toString() + " ");
+                        hwyWriter.print(vdsItem.getLaneList().size() + " ");
+                        hwyWriter.print(vdsItem.street+"\n");
+                        List<String> laneList = vdsItem.getLaneList();
+                        //    output all the lanes
+                        for (String lane: laneList)
+                        {
+                            hwyWriter.print(lane);
+                            hwyWriter.print("\n");
+                        }
+                    }
+                }
+            }
+            hwyWriter.close();
+        }catch (FileNotFoundException ex)
+        {
+            Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex);
+        } catch (Exception ex)
+        {
+            ex.printStackTrace();
+            Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex);
+        }
+
+    }
+    
+    /** Read the loop file to create a dictionary to lookup all the lanes
+     * for a given VDS.  As a byproduct we will write the reformatted Loop file.
+     * (Not sure if this is needed. Ask jtorres.)
+     */
+    public void createLanelookup()
+    {   
+        feplines = new HashMap<String,List<String>> ();
+            
+        try
+        {
+            Scanner loopScanner = new Scanner(new File(filepath+loopFileName));
+            PrintWriter loopWriter = new PrintWriter(new File(filepath+reformattedLoopFile));
+            
+            loopScanner.nextLine();  // Skip the column headers
+
+            // Read all the lines in the loop file
+            while(loopScanner.hasNextLine())
+            {
+                String line = loopScanner.nextLine();
+                Scanner lineScanner = new Scanner(line);
+                
+                Integer fwy = lineScanner.nextInt();
+                String dir = lineScanner.next();
+                String postmile = lineScanner.next();
+                String ldsID = lineScanner.next();
+                String vdsID = lineScanner.next();
+                String loopID = lineScanner.next();
+                String shortLoc = lineScanner.next();
+                Integer laneNum = lineScanner.nextInt();
+                String loop_name = line.substring(73).trim(); // grab rest of line
+                loop_name = loop_name.replace(" ", "_");
+                
+                loopWriter.print(fwy + "\t");
+                loopWriter.print(dir+ "\t");
+                loopWriter.print(postmile + "\t");
+                loopWriter.print(ldsID + "\t");
+                loopWriter.print(vdsID + "\t");
+                loopWriter.print(loopID + "\t");
+                loopWriter.print(shortLoc + "\t");
+                loopWriter.print(laneNum + "\t");
+                loopWriter.print(loop_name + "\t");
+                loopWriter.print("?" + "\t");
+                loopWriter.print("0" + "\t");
+                loopWriter.print('\n');
+                
+                lineScanner.close();
+                
+                // Combine fields for one lane description
+                String laneDesc = loopID + " " + shortLoc + " " + loop_name;
+                // Add the lane to the lookup table
+                if (vdsDict.containsKey(vdsID))
+                {
+                    vdsDict.get(vdsID).addLane(laneDesc);
+                }
+                else
+                {
+                    if (shortLoc.equals("ML") && !missingVDS.contains(vdsID))
+                    {
+                        System.out.println("createLaneLookup(): vdsID: "+vdsID+
+                                " of type ML not found. "+ String.format("%3s %s %5s",fwy,dir,postmile));
+                        missingVDS.add(vdsID);
+                    }
+                }
+
+                // Also Add this vdsID to the list associated with a fepline
+                // lookup which fepline to use for this VDS (using ldsid as 
+                //  intermediate key.
+                StationAddr sa = ldsDict.get(ldsID);
+                if (sa == null)
+                {
+                    if (!missingLDS.contains(ldsID))
+                    {
+                        System.out.println("missing ldsID in Station Addr lookup: "+ldsID);
+                        missingLDS.add(ldsID);
+                    }
+                }
+                else
+                {
+                    String fep_line = sa.line_num;
+                    // Fetch the info about this VDS
+                    VehicleDetectionStation curr = vdsDict.get(vdsID);
+                    // Some VDS were ignored because they weren't Mainline
+                    if (curr != null)
+                    {
+                        // Assign the station address for this VDS
+                        curr.setStaAddr(ldsDict.get(ldsID).station_address);
+
+                        if (fep_line == null)
+                        {
+                            System.out.println("No fepline for ldsID "+ldsID+ " :vdsid "
+                                    +vdsID+"  "+fwy+dir+postmile);
+                        }
+                        else
+                        {
+                            // Add vdsID to list of feplines
+                            if (feplines.containsKey(fep_line))
+                            {
+                                List<String> vdsList = feplines.get(fep_line);
+                                // only add it if it isn't already there
+                                if (!vdsList.contains(vdsID))
+                                {
+                                    feplines.get(fep_line).add(vdsID);
+                                }
+                            }
+                            else // Create a new one
+                            {
+                                List<String> arraylist1 = new ArrayList<String>();
+                                arraylist1.add(vdsID);
+                                feplines.put(fep_line, arraylist1);
+                            }
+                        }
+                    }
+                }
+            }
+            
+            loopScanner.close();
+            loopWriter.close();
+            
+        } catch (FileNotFoundException ex)
+        {
+            Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex);
+        } 
+    }
+    /** Create a dictionary of VehicleDetectionStations */
+    public void createVDSdict()
+    {   
+        vdsDict = new HashMap<String,VehicleDetectionStation>(); 
+        try
+        {
+            Scanner vdsScanner = new Scanner(new File(filepath+vdsFileName));
+            
+            System.out.println(vdsScanner.nextLine()); // echo col headers
+
+            // Read the tab-delimited vds file
+            while(vdsScanner.hasNextLine())
+            {
+                String line = vdsScanner.nextLine();
+                Scanner lineScanner = new Scanner(line).useDelimiter("\t");
+                VehicleDetectionStation vds = new VehicleDetectionStation(lineScanner);
+                // We only want stations that are mainline
+                if (vds.type.equals("ML"))
+                {
+                    vdsDict.put(vds.id, vds);
+                }
+                else
+                {
+                    ignored.add(vds.id);
+                }
+                lineScanner.close();
+            }
+            vdsScanner.close();
+            System.out.println("Ignored "+ignored.size() + " non-Mainline VDS's");
+            
+        } catch (FileNotFoundException ex)
+        {
+            Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex);
+        } 
+    }
+    /** Read the lds file to create a dictionary to lookup the FEP line number.
+     */
+    public void createLDSdict()
+    {   
+        ldsDict = new HashMap<String,StationAddr> ();
+            
+        try
+        {
+            Scanner ldsScanner = new Scanner(new File(filepath+ldsFileName));
+            
+            ldsScanner.nextLine();  // Skip the column headers
+
+            // Read all the lines in the loop file
+            while(ldsScanner.hasNextLine())
+            {
+                String line = ldsScanner.nextLine();
+                Scanner lineScanner = new Scanner(line);
+                
+                String ldsID = lineScanner.next();
+                String line_num = lineScanner.next();
+                String stn_address = lineScanner.next();
+                // Save the fep linenum and station address for this LDS
+                StationAddr sa = new StationAddr(line_num,stn_address);
+                lineScanner.close();
+                // Add the ldsID to the dict
+                ldsDict.put(ldsID, sa);
+            }
+            ldsScanner.close();
+        } catch (FileNotFoundException ex)
+        {
+            Logger.getLogger(BuildHighwayFile.class.getName()).log(Level.SEVERE, null, ex);
+        } 
+    }
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args)
+    {
+        BuildHighwayFile app = new BuildHighwayFile();
+        app.createLDSdict();
+        app.createVDSdict();
+        app.createLanelookup();
+        app.createHighwayFile();
+    }
+
+    /** A record for a fep line_num  and Station Address pair */
+    final class StationAddr
+    {
+        public final String line_num;
+        public final String station_address;
+        public StationAddr(String line, String addr)
+        {
+            this.line_num = line;
+            this.station_address = addr;
+        }
+    }
+}
+
Index: /trunk/src/tmcsim/utilities/VehicleDetectionStation.java
===================================================================
--- /trunk/src/tmcsim/utilities/VehicleDetectionStation.java	(revision 272)
+++ /trunk/src/tmcsim/utilities/VehicleDetectionStation.java	(revision 272)
@@ -0,0 +1,71 @@
+
+package tmcsim.utilities;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.Scanner;
+
+/**
+ * Represent a single VDS.
+ * @author jdalbey
+ */
+public final class VehicleDetectionStation
+{
+    public final String id;
+    public final String fwy;
+    public final String dir;
+    public final String postmile;
+    public final String latitude;
+    public final String longitude;
+    public final String type;   // type of lanes being monitored
+    public final String street;
+    private String station_address; 
+    private List<String> laneList;
+    
+    public VehicleDetectionStation(Scanner lineScanner)
+    {
+        id = lineScanner.next();
+        fwy = lineScanner.next();
+        dir = lineScanner.next();
+        lineScanner.next(); // skip District
+        lineScanner.next(); // skip Country
+        lineScanner.next(); // skip City
+        String raw_pm = lineScanner.next().trim();
+        if (raw_pm.startsWith("R"))
+        {
+            raw_pm = raw_pm.substring(1);
+        }
+        postmile = raw_pm;
+        lineScanner.next(); // skip Abs_PM
+        latitude = lineScanner.next(); 
+        longitude = lineScanner.next(); 
+        lineScanner.next();   // skip length
+        type = lineScanner.next();   // skip type
+        lineScanner.next(); // skip lanes
+        street = lineScanner.next();  // TODO read street name correctly
+        laneList = new ArrayList<String>(); // list of lane descriptors    
+    }   
+    public void setStaAddr(String address)
+    {
+        this.station_address = address;
+    }
+    public String getStaAddr()
+    {
+        return this.station_address;
+    }
+    public void addLane(String laneDescription)
+    {
+        this.laneList.add(laneDescription);
+    }
+    public List getLaneList()
+    {
+        return laneList;
+    }
+    
+    @Override
+    public String toString()
+    {
+        return station_address + " " + fwy + " " + dir + " " + postmile;
+    }
+}
