Warning: Can't use blame annotator:
svn blame failed on trunk/src/atmsdriver/model/Station.java: ("Can't find a temporary directory: Internal error", 20014)

source: tmcsimulator/trunk/src/atmsdriver/model/Station.java @ 186

Revision 186, 10.3 KB checked in by jtorres, 9 years ago (diff)

Highways.java, FEPLine.java, LoopDetector?.java, Station.java: reconfigured the getHighwaysMeta() function to a toCondensedFormat(boolean MetaDataOnly?) method. By specifying MetaDataOnly? as true, you get the same output as the previous getHighwaysMeta() function. By specifying MetaDataOnly? as false, you get the new condensed format needed to send to the FEPSim over the socket. This allows us to use the same function to get a meta data dump, as well as get the highways data format needed for FEPSim socket. HighwaysParser?.cpp: removed the old tinyxml code, set up skeleton for new parser. NetworkReader?.h: deleted, and added HighwaysParser?.h. LoadSadDotsTest?.java and StationTest?.java: configured to use new toCondensedFormat method instead of getHighwaysMeta.

RevLine 
1package atmsdriver.model;
2
3import atmsdriver.model.LoopDetector.DOTCOLOR;
4import java.util.List;
5import org.w3c.dom.Document;
6import org.w3c.dom.Element;
7
8/**
9 * A Station (LDS or Loop Detector Station) represents a group of lane detectors
10 * across all lanes at a particular point on a highway.  A station is
11 * identified by its highway number and postmile.  A station has an associated
12 * direction used to establish which direction is Main and which is Opposite.
13 * The MLTotVol and OppTotVol for a station can be dynamically updated.
14 * A station has other attributes: lineNum, ldsID, drop, and location which are
15 * used by the FEP.  A station can be compared to other stations by its postmile.
16 *
17 * @author John A. Torres
18 * @version 9/10/2017
19 */
20public class Station implements Comparable
21{
22
23    /* Static Station meta data */
24    final public int lineNum;
25    final public int ldsID; // double check
26    final public int drop;
27    final public String location;
28    final public List<LoopDetector> loops;
29    final public int routeNumber;
30    final public double postmile;
31    final public DIRECTION direction;
32
33    /* Dynamic Station data */
34    private int MLTotVol;
35    private int OppTotVol;
36
37    /* Constructor */
38    public Station(int lineNum, int ldsID, int drop,
39            String location, List<LoopDetector> loops, int hwy,
40            DIRECTION direction, double postmile)
41    {
42        this.lineNum = lineNum;
43        this.ldsID = ldsID;
44        this.drop = drop;
45        this.loops = loops;
46        this.location = location;
47        this.postmile = postmile;
48        this.direction = direction;
49        this.routeNumber = hwy;
50
51        this.MLTotVol = getMLTotVol();
52        this.OppTotVol = getOPPTotVol();
53    }
54   
55    /**
56     * Calculates the total ML Volume.
57     *
58     * @return total ML volume.
59     */
60    private int getMLTotVol()
61    {
62        int mlTotVol = 0;
63        for(LoopDetector loop : loops)
64        {
65            if(loop.loopLocation.startsWith("ML"))
66            {
67                mlTotVol += loop.vol;
68            }
69        }
70        return mlTotVol;
71    }
72   
73    /**
74     * Calculates the total OPP Volume
75     *
76     * @return total OPP volume.
77     */
78    private int getOPPTotVol()
79    {
80        int oppTotVol = 0;
81        for(LoopDetector loop : loops)
82        {
83            if(loop.loopLocation.startsWith("OS"))
84            {
85                oppTotVol += loop.vol;
86            }
87        }
88        return oppTotVol;
89    }
90   
91    /** Returns a string of highways data. If MetaDataOnly is true, you get a full
92     *  dump of the highways meta data, which does not include dynamic loop values,
93     *  and does include the string location names. If MetaDataOnly is false,
94     *  dynamic loop values are included, and unnecessary information like string
95     *  location values are included.
96     *
97     *  The FEPSimulator takes in the toCondensedFormat() output, with a MetaDataOnly
98     *  value of false, over the socket.
99     *
100     *  The MetaDataOnly flag should be used to get a full dump of the highways
101     *  information. This was used to get the highways_fullmap.txt output.
102     *
103     * @param MetaDataOnly Whether you want meta data, or a full dump for FEPSim
104     * @return String, highways data in condensed format
105     */
106    public String toCondensedFormat(boolean MetaDataOnly)
107    {
108        StringBuilder build = new StringBuilder();
109        build.append(Integer.toString(this.ldsID));
110        build.append(" ");
111        build.append(Integer.toString(this.drop));
112        build.append(" ");
113        build.append(Integer.toString(this.routeNumber));
114        build.append(" ");
115        build.append(this.direction.getLetter());
116        build.append(" ");
117        build.append(Double.toString(this.postmile));
118        build.append(" ");
119        build.append(Integer.toString(loops.size()));
120        build.append(" ");
121        if(MetaDataOnly)
122        {
123            build.append(this.location);
124        }
125        build.append("\n");
126        for (LoopDetector loop : loops)
127        {
128            build.append(loop.toCondensedFormat(MetaDataOnly));
129        }
130        return build.toString();
131    }
132
133    /**
134     * Compare this Station to another by postmile. Note: This might be better
135     * as a Comparator since it checks only one field.
136     */
137    @Override
138    public int compareTo(Object otherStation)
139    {
140        // check for identity
141        if (this == otherStation)
142        {
143            return 0;
144        }
145        // check that Object is of type Station, if not throw exception
146        if (!(otherStation instanceof Station))
147        {
148            throw new ClassCastException("A Station object expected.");
149        }
150
151        // get difference of values
152        double otherStationPostmile = ((Station) otherStation).postmile;
153        double val = this.postmile - otherStationPostmile;
154
155        // set appropriate comparable return value
156        int retval = 0;
157        if (val > 0)
158        {
159            retval = 1;
160        }
161        else if (val < 0)
162        {
163            retval = -1;
164        }
165
166        return retval;
167    }
168
169    /** Determine which lane fields to update based on given direction
170     * and update all the loop detectors with the given color.
171     * @param direction desired highway direction
172     * @param dotColor desired dot color
173     */
174    public void updateByDirection(DIRECTION direction, DOTCOLOR dotColor) 
175    {
176        String laneDir = "OS";
177        if(direction.equals(this.direction))
178        {
179            laneDir = "ML";
180        }
181        outputUpdateMessage(dotColor, laneDir);
182       
183        for(LoopDetector loop : loops)
184        {
185            if(loop.loopLocation.startsWith(laneDir))
186            {
187                // UPDATE LOOP WITH VALUES
188                int speed = 0;
189                loop.updateLoop(dotColor.volume(), dotColor.occupancy(), speed);
190            }
191        }
192       
193        this.MLTotVol = getMLTotVol();
194        this.OppTotVol = getOPPTotVol();
195    }
196   
197    /**
198     * Output for updateByDirection. Logs the update to the console.
199     *
200     * @param dotcolor
201     * @param OPP_ML
202     */
203    private void outputUpdateMessage(DOTCOLOR dotcolor, String OPP_ML)
204    {
205        System.out.printf("Updating %-3.3s %-5.5s %-3.3s lanes\t %-12.12s "
206                + "at postmile %-6.6s to %-7.7s\n", 
207                Integer.toString(this.routeNumber), this.direction.name(), 
208                OPP_ML, this.location, Double.toString(this.postmile), 
209                dotcolor.name());
210    }
211   
212    /**
213     * XML tags used for toXML() method.
214     */
215    private static enum XML_TAGS
216    {
217
218        STATION("Station"),
219        LDS_ID("LDS_ID"),
220        LINE_NUM("Line_Num"),
221        DROP("Drop"),
222        LOOPS("Loops"),
223        LOCATION("Location"),
224        POST_MILE("Post_Mile"),
225        DIRECTION("Direction"),
226        FREEWAY("Freeway"),
227        ML_TOT_VOL("ML_Tot_Vol"),
228        OPP_TOT_VOL("Opp_Tot_Vol");
229
230        String tag;
231
232        private XML_TAGS(String n)
233        {
234            tag = n;
235        }
236    }
237   
238    /**
239     * Returns the Station data in XMLFormat.
240     *
241     * @param currElem The current XML <Station> element
242     */
243    public void toXML(Element currElem)
244    {
245        Document theDoc = currElem.getOwnerDocument();
246
247        Element stationElement = theDoc.createElement(XML_TAGS.STATION.tag);
248        currElem.appendChild(stationElement);
249
250        Element ldsIDElement = theDoc.createElement(XML_TAGS.LDS_ID.tag);
251        ldsIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.ldsID)));
252        stationElement.appendChild(ldsIDElement);
253
254        Element lineNumElement = theDoc.createElement(XML_TAGS.LINE_NUM.tag);
255        lineNumElement.appendChild(theDoc.createTextNode(String.valueOf(this.lineNum)));
256        stationElement.appendChild(lineNumElement);
257
258        Element dropElement = theDoc.createElement(XML_TAGS.DROP.tag);
259        dropElement.appendChild(theDoc.createTextNode(String.valueOf(this.drop)));
260        stationElement.appendChild(dropElement);
261
262        Element locationElement = theDoc.createElement(XML_TAGS.LOCATION.tag);
263        locationElement.appendChild(theDoc.createTextNode(this.location));
264        stationElement.appendChild(locationElement);
265
266        Element postMileElement = theDoc.createElement(XML_TAGS.POST_MILE.tag);
267        postMileElement.appendChild(theDoc.createTextNode(String.valueOf(this.postmile)));
268        stationElement.appendChild(postMileElement);
269
270        Element directionElement = theDoc.createElement(XML_TAGS.DIRECTION.tag);
271        directionElement.appendChild(theDoc.createTextNode("" + this.direction.getLetter()));
272        stationElement.appendChild(directionElement);
273
274        Element freewayElement = theDoc.createElement(XML_TAGS.FREEWAY.tag);
275        freewayElement.appendChild(theDoc.createTextNode(String.valueOf(this.routeNumber)));
276        stationElement.appendChild(freewayElement);
277
278        Element mlElement = theDoc.createElement(XML_TAGS.ML_TOT_VOL.tag);
279        mlElement.appendChild(theDoc.createTextNode(String.valueOf(this.MLTotVol)));
280        stationElement.appendChild(mlElement);
281
282        Element oppElement = theDoc.createElement(XML_TAGS.OPP_TOT_VOL.tag);
283        oppElement.appendChild(theDoc.createTextNode(String.valueOf(this.OppTotVol)));
284        stationElement.appendChild(oppElement);
285
286        Element loopsElement = theDoc.createElement(XML_TAGS.LOOPS.tag);
287        stationElement.appendChild(loopsElement);
288
289        for (LoopDetector loop : loops)
290        {
291            loop.toXML(loopsElement);
292        }
293    }
294
295    /**
296     * Enum for freeway direction.
297     *
298     * @author John A. Torres
299     * @version 9/10/2017
300     */
301    public static enum DIRECTION
302    {
303        NORTH,
304        SOUTH,
305        EAST,
306        WEST;
307
308        // All the first letters of the values, in order.
309        private static String allLetters = "NSEW";
310
311        /**
312         * Return the first letter of this enum.
313         *
314         * @return String first letter of this enum.
315         */
316        public String getLetter()
317        {
318            return this.toString().substring(0, 1);
319        }
320
321        /**
322         * Returns a direction given its first character.
323         *
324         * @param letter the first character of a direction
325         * @return direction corresponding to letter
326         * @pre letter must be one of allLetters
327         */
328        public static DIRECTION toDirection(String letter)
329        {
330            return values()[allLetters.indexOf(letter.charAt(0))];
331        }
332
333    }
334}
Note: See TracBrowser for help on using the repository browser.