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 @ 278

Revision 278, 12.5 KB checked in by jdalbey, 7 years ago (diff)

Station.java CHANGED HIGHWAY MODEL to be consistent with JD's new BuildHighwayFile? pgm that creates a highway map based on VDS instead of Controller (LDS). (The code I removed is just commented out for now).

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