Changeset 353 in tmcsimulator for trunk/src/atmsdriver/model
- Timestamp:
- 04/02/2019 06:30:15 PM (7 years ago)
- Location:
- trunk/src/atmsdriver/model
- Files:
-
- 2 edited
- 1 copied
-
Highway.java (modified) (2 diffs)
-
Highways.java (modified) (6 diffs)
-
StationComparator.java (copied) (copied from trunk/src/atmsdriver/model/Station.java) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/atmsdriver/model/Highway.java
r343 r353 16 16 * @author jdalbey 17 17 */ 18 final public class Highway 18 final public class Highway implements Comparable<Highway> 19 19 { 20 20 /** The identifying number for this highway, e.g., 101 */ … … 49 49 return Integer.toString(this.routeNumber); 50 50 } 51 52 @Override 53 public int compareTo(Highway other) 54 { 55 int otherRoute = ((Highway) other).routeNumber; 56 //ascending order 57 return this.routeNumber - otherRoute; 58 } 51 59 } -
trunk/src/atmsdriver/model/Highways.java
r345 r353 151 151 * Applies specified color to the specified highway stretch. Route number 152 152 * and direction specify the highway. Postmile and range specify the stretch 153 * of specified highway. Dot color is the color to be applied to the 154 * stretch. 155 * 153 * of specified highway. 154 * The purpose of this method is to modify the highway state to represent 155 * traffic conditions created by the Traffic Manager. These conditions 156 * originate in the traffic events file which specifies traffic congestion arising 157 * during the simulation. NOTE: Since these events describe congestion, 158 * the direction that the color should be applied is the REVERSE of the 159 * regular flow of traffic. 160 * So a request to apply red to 55 S from 8.5 for 2 miles means 161 * the stretch 8.5 -> 10.5 because sobo traffic normally flows toward 162 * decreasing postmiles and we want to do the reverse. 156 163 * @param routeNumber highway route number 157 * @param direction highway direction 164 * @param direction highway direction (for normal traffic flow) 158 165 * @param postmile origin postmile value 159 166 * @param range range from origin postmile … … 179 186 Double startPost; 180 187 Double endPost; 188 double epsilon = 0.001; 181 189 182 190 // postmiles increase from s to n and w to e 183 // handle increasing postmile directinons (north or east)184 if (direction.equals(Station.DIRECTION. NORTH) || direction.equals(Station.DIRECTION.EAST))191 // S or W directions backup in a positive postmile direction 192 if (direction.equals(Station.DIRECTION.SOUTH) || direction.equals(Station.DIRECTION.WEST)) 185 193 { 186 194 // add range value to startPost to get … … 191 199 // specifies a highway that doesn't exist in the network. 192 200 // Also the case where a desired postmile to color isn't in 193 // the network. 201 // the network. Ticket 118 194 202 // iterate through the stations, if within the specified highway 195 203 // stretch, update the station by direction and apply dot color … … 202 210 } 203 211 } 204 // handle decreasing postmile directions (south or west)212 // N or E directions backup in a negative postmile direction 205 213 else 206 214 { … … 581 589 pmList.load(s); 582 590 591 Collections.sort(highways); // Sort the highways for easier inspection 583 592 String header = "{\n" + 584 593 " \"type\": \"FeatureCollection\",\n" + … … 590 599 // Examine every station on this highway 591 600 StringBuilder lineout = new StringBuilder(); 601 Collections.sort(hwy.stations, new StationComparator()); 592 602 for (Station stat: hwy.stations) 593 603 { -
trunk/src/atmsdriver/model/StationComparator.java
r343 r353 1 1 package atmsdriver.model; 2 2 3 import atmsdriver.model.LoopDetector.DOTCOLOR; 4 import java.util.ArrayList; 5 import java.util.List; 6 import org.w3c.dom.Document; 7 import org.w3c.dom.Element; 3 import java.util.Comparator; 8 4 9 5 /** 10 * A Station (VDS or Vehicle Detector Station) represents a group of lane detectors 11 * across all lanes in one direction 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, vdsID, 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, jdalbey 19 * @version 9/10/2017, 3/22/2019 6 * Compare two stations by route and postmile. 7 * Used by Highways.toJson() so json is listed by route then postmile 8 * @author jdalbey 9 * @version 4/2/2019 20 10 */ 21 public final class Station implements Comparable11 public final class StationComparator implements Comparator 22 12 { 23 13 24 /* Static Station meta data */25 final public int lineID;26 final public int vdsID; // double check27 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 vdsID, int drop,40 String location, List<LoopDetector> loops, int hwy,41 DIRECTION direction, double postmile)42 {43 this.lineID = lineID;44 this.vdsID = vdsID;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 14 /** 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.vdsID)); 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. 15 * Compare two stations by route and postmile. 138 16 */ 139 17 @Override 140 public int compare To(Object otherStation)18 public int compare(Object a, Object b) 141 19 { 142 20 // check for identity 143 if ( this == otherStation)21 if (a == b) 144 22 { 145 23 return 0; 146 24 } 147 25 // check that Object is of type Station, if not throw exception 148 if (!( otherStationinstanceof Station))26 if (!(a instanceof Station && b instanceof Station)) 149 27 { 150 28 throw new ClassCastException("A Station object expected."); 151 29 } 152 153 // get difference of values 154 double otherStationPostmile = ((Station) otherStation).postmile; 155 double val = this.postmile - otherStationPostmile; 156 30 Station statA = (Station) a; 31 Station statB = (Station) b; 32 // compare by direction field first 33 int i = statA.direction.compareTo(statB.direction); 34 if (i != 0) return i; 35 36 // get difference of postmile values 37 double val = statA.postmile - statB.postmile; 38 157 39 // set appropriate comparable return value 158 40 int retval = 0; … … 169 51 } 170 52 171 /**172 * See if this station matches the specified attributes.173 * @param dir174 * @param postmile175 * @return true if this station's attributes match the given ones.176 */177 public boolean matches(DIRECTION dir, double postmile)178 {179 double val = this.postmile - postmile;180 return (Math.abs(val) < 0.01) && this.direction.equals(dir);181 }182 /**183 * Determine which lane fields to update based on given direction and update184 * all the loop detectors with the given color.185 *186 * @param direction desired highway direction187 * @param dotColor desired dot color188 */189 public void updateByDirection(DIRECTION direction, DOTCOLOR dotColor)190 {191 // Is this station going in the desired direction?192 if (direction.equals(this.direction))193 {194 outputUpdateMessage(dotColor, direction.toString());195 196 for (LoopDetector loop : loops)197 {198 // THIS DECISION ISN'T NEEDED after JD's BuildHighwayFile pgm199 // creates a highway map based on VDS instead of Controller (LDS).200 // if (loop.loopLocation.startsWith(laneDir))201 // {202 // UPDATE LOOP WITH VALUES203 loop.updateLoop(dotColor.volume(), dotColor.occupancy());204 // }205 }206 207 this.MLTotVol = getMLTotVol();208 this.OppTotVol = getOPPTotVol();209 }210 }211 /**212 * Return the color for the lanes in a given direction.213 * @return character representing color of this station's traffic flow214 * '@' = red, '+' = yellow, '-' = green215 */216 public char getColor()217 {218 /* For now just use the color of the first lane.219 * TODO: Average the color in ALL the lanes for the given direction */220 221 String laneDir = "";222 223 // THIS DECISION ISN'T NEEDED after JD's BuildHighwayFile pgm224 // creates a highway map based on VDS instead of Controller (LDS).225 // if (direction.equals(this.direction))226 // {227 // laneDir = "ML";228 // }229 // else if (direction.equals(this.direction.getOpposite()))230 // {231 // laneDir = "OS";232 // }233 // Search lanes to find specified direction234 for (LoopDetector loop : loops)235 {236 // THIS DECISION ISN'T NEEDED after JD's BuildHighwayFile pgm237 // creates a highway map based on VDS instead of Controller (LDS).238 // if (loop.loopLocation.substring(0,2).equals(laneDir))239 // {240 // Return color according to loop volume of first matching lane241 if (loop.vol == 1)242 {243 return '@';244 }245 if (loop.vol == 3)246 {247 return '+';248 }249 if (loop.vol == 0)250 {251 return '-';252 }253 // }254 }255 // Default case for when the route is not on this direction256 return ' ';257 }258 /**259 * Return the color name for the traffic volume of this station.260 */261 public String getColorName()262 {263 String colorName = "";264 switch (this.getColor())265 {266 case '@': colorName = "red";break;267 case '+': colorName = "yellow"; break;268 case '-': colorName = "lime";break;269 case ' ': colorName = "lime";break;270 }271 return colorName;272 }273 /**274 * Output for updateByDirection. Logs the update to the console.275 *276 * @param dotcolor277 * @param OPP_ML278 */279 private void outputUpdateMessage(DOTCOLOR dotcolor, String OPP_ML)280 {281 System.out.printf("Updating %-3.3s %-5.5s %-3.3s lanes\t %-12.12s "282 + "at postmile %-6.6s to %-7.7s\n",283 Integer.toString(this.routeNumber), this.direction.name(),284 OPP_ML, this.location, Double.toString(this.postmile),285 dotcolor.name());286 }287 288 /**289 * XML tags used for toXML() method.290 */291 private static enum XML_TAGS292 {293 294 STATION("Station"),295 LDS_ID("LDS_ID"),296 LINE_NUM("Line_Num"),297 DROP("Drop"),298 LOOPS("Loops"),299 LOCATION("Location"),300 POST_MILE("Post_Mile"),301 DIRECTION("Direction"),302 FREEWAY("Freeway"),303 ML_TOT_VOL("ML_Tot_Vol"),304 OPP_TOT_VOL("Opp_Tot_Vol");305 306 String tag;307 308 private XML_TAGS(String n)309 {310 tag = n;311 }312 }313 314 /**315 * Returns the Station data in XMLFormat.316 *317 * @param currElem The current XML <Station> element318 */319 public void toXML(Element currElem)320 {321 Document theDoc = currElem.getOwnerDocument();322 323 Element stationElement = theDoc.createElement(XML_TAGS.STATION.tag);324 currElem.appendChild(stationElement);325 326 Element ldsIDElement = theDoc.createElement(XML_TAGS.LDS_ID.tag);327 ldsIDElement.appendChild(theDoc.createTextNode(String.valueOf(this.vdsID)));328 stationElement.appendChild(ldsIDElement);329 330 Element lineNumElement = theDoc.createElement(XML_TAGS.LINE_NUM.tag);331 lineNumElement.appendChild(theDoc.createTextNode(String.valueOf(this.lineID)));332 stationElement.appendChild(lineNumElement);333 334 Element dropElement = theDoc.createElement(XML_TAGS.DROP.tag);335 dropElement.appendChild(theDoc.createTextNode(String.valueOf(this.drop)));336 stationElement.appendChild(dropElement);337 338 Element locationElement = theDoc.createElement(XML_TAGS.LOCATION.tag);339 locationElement.appendChild(theDoc.createTextNode(this.location));340 stationElement.appendChild(locationElement);341 342 Element postMileElement = theDoc.createElement(XML_TAGS.POST_MILE.tag);343 postMileElement.appendChild(theDoc.createTextNode(String.valueOf(this.postmile)));344 stationElement.appendChild(postMileElement);345 346 Element directionElement = theDoc.createElement(XML_TAGS.DIRECTION.tag);347 directionElement.appendChild(theDoc.createTextNode("" + this.direction.getLetter()));348 stationElement.appendChild(directionElement);349 350 Element freewayElement = theDoc.createElement(XML_TAGS.FREEWAY.tag);351 freewayElement.appendChild(theDoc.createTextNode(String.valueOf(this.routeNumber)));352 stationElement.appendChild(freewayElement);353 354 Element mlElement = theDoc.createElement(XML_TAGS.ML_TOT_VOL.tag);355 mlElement.appendChild(theDoc.createTextNode(String.valueOf(this.MLTotVol)));356 stationElement.appendChild(mlElement);357 358 Element oppElement = theDoc.createElement(XML_TAGS.OPP_TOT_VOL.tag);359 oppElement.appendChild(theDoc.createTextNode(String.valueOf(this.OppTotVol)));360 stationElement.appendChild(oppElement);361 362 Element loopsElement = theDoc.createElement(XML_TAGS.LOOPS.tag);363 stationElement.appendChild(loopsElement);364 365 for (LoopDetector loop : loops)366 {367 loop.toXML(loopsElement);368 }369 }370 371 /**372 * Enum for freeway direction.373 *374 * @author John A. Torres375 * @version 9/10/2017376 */377 public static enum DIRECTION378 {379 NORTH,380 SOUTH,381 EAST,382 WEST;383 384 // All the first letters of the values, in order.385 private static String allLetters = "NSEW";386 387 /**388 * Return the first letter of this enum.389 *390 * @return String first letter of this enum.391 */392 public String getLetter()393 {394 return this.toString().substring(0, 1);395 }396 397 public DIRECTION getOpposite()398 {399 switch (this)400 {401 case NORTH:402 return SOUTH;403 case SOUTH:404 return NORTH;405 case EAST:406 return WEST;407 case WEST:408 return EAST;409 }410 return null;411 }412 413 /**414 * Returns a direction given its first character.415 *416 * @param letter the first character of a direction417 * @return direction corresponding to letter418 * @pre letter must be one of allLetters419 */420 public static DIRECTION toDirection(String letter)421 {422 if(letter.indexOf(letter.charAt(0)) == -1)423 {424 return null;425 }426 return values()[allLetters.indexOf(letter.charAt(0))];427 }428 }429 430 @Override431 public String toString()432 {433 return Integer.toString(this.vdsID)+this.getColor();434 }435 53 }
Note: See TracChangeset
for help on using the changeset viewer.
