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

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

vds_data/highways_fullmap.txt: removed lane num field, not necessary. ATMSDriver.java: removed System.out statement. FEPLine.java: renamed lineNum member to lineID. Highways.java: added example output for toCondensedFormat(boolean) method in method comments. LoopDetector?.java: removed spd member, not necessary, as we calculate speed form occ and vol. Station.java: conformed to above changes.

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 lineID;
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 lineID, int ldsID, int drop,
39            String location, List<LoopDetector> loops, int hwy,
40            DIRECTION direction, double postmile)
41    {
42        this.lineID = lineID;
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                loop.updateLoop(dotColor.volume(), dotColor.occupancy());
189            }
190        }
191       
192        this.MLTotVol = getMLTotVol();
193        this.OppTotVol = getOPPTotVol();
194    }
195   
196    /**
197     * Output for updateByDirection. Logs the update to the console.
198     *
199     * @param dotcolor
200     * @param OPP_ML
201     */
202    private void outputUpdateMessage(DOTCOLOR dotcolor, String OPP_ML)
203    {
204        System.out.printf("Updating %-3.3s %-5.5s %-3.3s lanes\t %-12.12s "
205                + "at postmile %-6.6s to %-7.7s\n", 
206                Integer.toString(this.routeNumber), this.direction.name(), 
207                OPP_ML, this.location, Double.toString(this.postmile), 
208                dotcolor.name());
209    }
210   
211    /**
212     * XML tags used for toXML() method.
213     */
214    private static enum XML_TAGS
215    {
216
217        STATION("Station"),
218        LDS_ID("LDS_ID"),
219        LINE_NUM("Line_Num"),
220        DROP("Drop"),
221        LOOPS("Loops"),
222        LOCATION("Location"),
223        POST_MILE("Post_Mile"),
224        DIRECTION("Direction"),
225        FREEWAY("Freeway"),
226        ML_TOT_VOL("ML_Tot_Vol"),
227        OPP_TOT_VOL("Opp_Tot_Vol");
228
229        String tag;
230
231        private XML_TAGS(String n)
232        {
233            tag = n;
234        }
235    }
236   
237    /**
238     * Returns the Station data in XMLFormat.
239     *
240     * @param currElem The current XML <Station> element
241     */
242    public void toXML(Element currElem)
243    {
244        Document theDoc = currElem.getOwnerDocument();
245
246        Element stationElement = theDoc.createElement(XML_TAGS.STATION.tag);
247        currElem.appendChild(stationElement);
248
249        Element ldsIDElement = theDoc.createElement(XML_TAGS.LDS_ID.tag);
250        ldsIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.ldsID)));
251        stationElement.appendChild(ldsIDElement);
252
253        Element lineNumElement = theDoc.createElement(XML_TAGS.LINE_NUM.tag);
254        lineNumElement.appendChild(theDoc.createTextNode(String.valueOf(this.lineID)));
255        stationElement.appendChild(lineNumElement);
256
257        Element dropElement = theDoc.createElement(XML_TAGS.DROP.tag);
258        dropElement.appendChild(theDoc.createTextNode(String.valueOf(this.drop)));
259        stationElement.appendChild(dropElement);
260
261        Element locationElement = theDoc.createElement(XML_TAGS.LOCATION.tag);
262        locationElement.appendChild(theDoc.createTextNode(this.location));
263        stationElement.appendChild(locationElement);
264
265        Element postMileElement = theDoc.createElement(XML_TAGS.POST_MILE.tag);
266        postMileElement.appendChild(theDoc.createTextNode(String.valueOf(this.postmile)));
267        stationElement.appendChild(postMileElement);
268
269        Element directionElement = theDoc.createElement(XML_TAGS.DIRECTION.tag);
270        directionElement.appendChild(theDoc.createTextNode("" + this.direction.getLetter()));
271        stationElement.appendChild(directionElement);
272
273        Element freewayElement = theDoc.createElement(XML_TAGS.FREEWAY.tag);
274        freewayElement.appendChild(theDoc.createTextNode(String.valueOf(this.routeNumber)));
275        stationElement.appendChild(freewayElement);
276
277        Element mlElement = theDoc.createElement(XML_TAGS.ML_TOT_VOL.tag);
278        mlElement.appendChild(theDoc.createTextNode(String.valueOf(this.MLTotVol)));
279        stationElement.appendChild(mlElement);
280
281        Element oppElement = theDoc.createElement(XML_TAGS.OPP_TOT_VOL.tag);
282        oppElement.appendChild(theDoc.createTextNode(String.valueOf(this.OppTotVol)));
283        stationElement.appendChild(oppElement);
284
285        Element loopsElement = theDoc.createElement(XML_TAGS.LOOPS.tag);
286        stationElement.appendChild(loopsElement);
287
288        for (LoopDetector loop : loops)
289        {
290            loop.toXML(loopsElement);
291        }
292    }
293
294    /**
295     * Enum for freeway direction.
296     *
297     * @author John A. Torres
298     * @version 9/10/2017
299     */
300    public static enum DIRECTION
301    {
302        NORTH,
303        SOUTH,
304        EAST,
305        WEST;
306
307        // All the first letters of the values, in order.
308        private static String allLetters = "NSEW";
309
310        /**
311         * Return the first letter of this enum.
312         *
313         * @return String first letter of this enum.
314         */
315        public String getLetter()
316        {
317            return this.toString().substring(0, 1);
318        }
319
320        /**
321         * Returns a direction given its first character.
322         *
323         * @param letter the first character of a direction
324         * @return direction corresponding to letter
325         * @pre letter must be one of allLetters
326         */
327        public static DIRECTION toDirection(String letter)
328        {
329            return values()[allLetters.indexOf(letter.charAt(0))];
330        }
331
332    }
333}
Note: See TracBrowser for help on using the repository browser.