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

Revision 285, 13.0 KB checked in by jdalbey, 7 years ago (diff)

Station.java: Add getColorName method, comment out dead code.

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     * @return character representing color of this station's traffic flow
205     * '@' = red, '+' = yellow, '-' = green
206     */
207    public char getColor()
208    {
209        /* For now just use the color of the first lane.
210         * TODO: Average the color in ALL the lanes for the given direction */
211
212        String laneDir = "";
213       
214            // THIS DECISION ISN'T NEEDED after JD's BuildHighwayFile pgm
215            // creates a highway map based on VDS instead of Controller (LDS).
216//        if (direction.equals(this.direction))
217//        {
218//            laneDir = "ML";
219//        }
220//        else if (direction.equals(this.direction.getOpposite()))
221//        {
222//            laneDir = "OS";
223//        }
224        // Search lanes to find specified direction
225        for (LoopDetector loop : loops)
226        {
227            // THIS DECISION ISN'T NEEDED after JD's BuildHighwayFile pgm
228            // creates a highway map based on VDS instead of Controller (LDS).
229//            if (loop.loopLocation.substring(0,2).equals(laneDir))
230//            {
231                // Return color according to loop volume of first matching lane
232                if (loop.vol == 1)
233                {
234                    return '@';
235                }
236                if (loop.vol == 3)
237                {
238                    return '+';
239                }
240                if (loop.vol == 0)
241                {
242                    return '-';
243                }
244//            }
245        }
246        // Default case for when the route is not on this direction
247        return ' ';
248    }
249    /**
250     * Return the color name for the traffic volume of this station.
251     */
252    public String getColorName()
253    {
254        String colorName = "";
255        switch (this.getColor())
256        {
257            case '@': colorName = "red";break;
258            case '+': colorName = "yellow"; break;
259            case '-': colorName = "lime";break;
260            case ' ': colorName = "lime";break;
261        }
262        return colorName;
263    }
264    /**
265     * Output for updateByDirection. Logs the update to the console.
266     *
267     * @param dotcolor
268     * @param OPP_ML
269     */
270    private void outputUpdateMessage(DOTCOLOR dotcolor, String OPP_ML)
271    {
272        System.out.printf("Updating %-3.3s %-5.5s %-3.3s lanes\t %-12.12s "
273                + "at postmile %-6.6s to %-7.7s\n",
274                Integer.toString(this.routeNumber), this.direction.name(),
275                OPP_ML, this.location, Double.toString(this.postmile),
276                dotcolor.name());
277    }
278
279    /**
280     * XML tags used for toXML() method.
281     */
282    private static enum XML_TAGS
283    {
284
285        STATION("Station"),
286        LDS_ID("LDS_ID"),
287        LINE_NUM("Line_Num"),
288        DROP("Drop"),
289        LOOPS("Loops"),
290        LOCATION("Location"),
291        POST_MILE("Post_Mile"),
292        DIRECTION("Direction"),
293        FREEWAY("Freeway"),
294        ML_TOT_VOL("ML_Tot_Vol"),
295        OPP_TOT_VOL("Opp_Tot_Vol");
296
297        String tag;
298
299        private XML_TAGS(String n)
300        {
301            tag = n;
302        }
303    }
304
305    /**
306     * Returns the Station data in XMLFormat.
307     *
308     * @param currElem The current XML <Station> element
309     */
310    public void toXML(Element currElem)
311    {
312        Document theDoc = currElem.getOwnerDocument();
313
314        Element stationElement = theDoc.createElement(XML_TAGS.STATION.tag);
315        currElem.appendChild(stationElement);
316
317        Element ldsIDElement = theDoc.createElement(XML_TAGS.LDS_ID.tag);
318        ldsIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.ldsID)));
319        stationElement.appendChild(ldsIDElement);
320
321        Element lineNumElement = theDoc.createElement(XML_TAGS.LINE_NUM.tag);
322        lineNumElement.appendChild(theDoc.createTextNode(String.valueOf(this.lineID)));
323        stationElement.appendChild(lineNumElement);
324
325        Element dropElement = theDoc.createElement(XML_TAGS.DROP.tag);
326        dropElement.appendChild(theDoc.createTextNode(String.valueOf(this.drop)));
327        stationElement.appendChild(dropElement);
328
329        Element locationElement = theDoc.createElement(XML_TAGS.LOCATION.tag);
330        locationElement.appendChild(theDoc.createTextNode(this.location));
331        stationElement.appendChild(locationElement);
332
333        Element postMileElement = theDoc.createElement(XML_TAGS.POST_MILE.tag);
334        postMileElement.appendChild(theDoc.createTextNode(String.valueOf(this.postmile)));
335        stationElement.appendChild(postMileElement);
336
337        Element directionElement = theDoc.createElement(XML_TAGS.DIRECTION.tag);
338        directionElement.appendChild(theDoc.createTextNode("" + this.direction.getLetter()));
339        stationElement.appendChild(directionElement);
340
341        Element freewayElement = theDoc.createElement(XML_TAGS.FREEWAY.tag);
342        freewayElement.appendChild(theDoc.createTextNode(String.valueOf(this.routeNumber)));
343        stationElement.appendChild(freewayElement);
344
345        Element mlElement = theDoc.createElement(XML_TAGS.ML_TOT_VOL.tag);
346        mlElement.appendChild(theDoc.createTextNode(String.valueOf(this.MLTotVol)));
347        stationElement.appendChild(mlElement);
348
349        Element oppElement = theDoc.createElement(XML_TAGS.OPP_TOT_VOL.tag);
350        oppElement.appendChild(theDoc.createTextNode(String.valueOf(this.OppTotVol)));
351        stationElement.appendChild(oppElement);
352
353        Element loopsElement = theDoc.createElement(XML_TAGS.LOOPS.tag);
354        stationElement.appendChild(loopsElement);
355
356        for (LoopDetector loop : loops)
357        {
358            loop.toXML(loopsElement);
359        }
360    }
361
362    /**
363     * Enum for freeway direction.
364     *
365     * @author John A. Torres
366     * @version 9/10/2017
367     */
368    public static enum DIRECTION
369    {
370        NORTH,
371        SOUTH,
372        EAST,
373        WEST;
374
375        // All the first letters of the values, in order.
376        private static String allLetters = "NSEW";
377
378        /**
379         * Return the first letter of this enum.
380         *
381         * @return String first letter of this enum.
382         */
383        public String getLetter()
384        {
385            return this.toString().substring(0, 1);
386        }
387       
388        public DIRECTION getOpposite()
389        {
390            switch (this)
391            {
392                case NORTH:
393                    return SOUTH;
394                case SOUTH:
395                    return NORTH;
396                case EAST:
397                    return WEST;
398                case WEST:
399                    return EAST;
400            }
401            return null;
402        }
403
404        /**
405         * Returns a direction given its first character.
406         *
407         * @param letter the first character of a direction
408         * @return direction corresponding to letter
409         * @pre letter must be one of allLetters
410         */
411        public static DIRECTION toDirection(String letter)
412        {
413            if(letter.indexOf(letter.charAt(0)) == -1)
414            {
415                return null;
416            }
417            return values()[allLetters.indexOf(letter.charAt(0))];
418        }
419    }
420   
421    @Override
422    public String toString()
423    {
424        return Integer.toString(this.ldsID);
425    }
426}
Note: See TracBrowser for help on using the repository browser.