Changeset 422 in tmcsimulator for trunk/src/tmcsim/highwaymodel/Highways.java
- Timestamp:
- 06/23/2019 10:27:35 AM (7 years ago)
- Location:
- trunk/src/tmcsim/highwaymodel
- Files:
-
- 1 added
- 1 copied
-
. (added)
-
Highways.java (copied) (copied from trunk/src/atmsdriver/model/Highways.java) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/tmcsim/highwaymodel/Highways.java
r398 r422 1 package atmsdriver.model;1 package tmcsim.highwaymodel; 2 2 3 3 import atmsdriver.trafficeventseditor.TrafficLaneEvent; 4 import atmsdriver.model.LoopDetector.DOTCOLOR; 5 import atmsdriver.model.Station.DIRECTION; 4 import tmcsim.highwaymodel.Station.DIRECTION; 6 5 import java.io.File; 7 6 import java.io.FileInputStream; 8 7 import java.io.FileNotFoundException; 9 import java.io.IOException;10 import java.io.PrintWriter;11 import java.io.StringWriter;12 import java.io.Writer;13 import java.net.Socket;14 8 import java.util.ArrayList; 15 9 import java.util.Collections; … … 21 15 import java.util.logging.Level; 22 16 import java.util.logging.Logger; 23 import javax.xml.parsers.DocumentBuilder;24 import javax.xml.parsers.DocumentBuilderFactory;25 import javax.xml.transform.OutputKeys;26 import javax.xml.transform.Transformer;27 import javax.xml.transform.TransformerFactory;28 import javax.xml.transform.dom.DOMSource;29 import javax.xml.transform.stream.StreamResult;30 import org.w3c.dom.Document;31 import org.w3c.dom.Element;32 import tmcsim.common.SimulationException;33 17 34 18 /** 35 * The Highways class aggregates all Highway instances within a geographic36 * region, and all of the FEPLines within an electronic detector network, in the37 * same geographic region. An instance of Highways.java comprises the underlying38 * model for the ATMSDriver application.19 * Highways represents California state highways supervised by CalTrans. 20 * The highways have sensors to detect traffic flow. In the simulation 21 * the traffic flow is artificially created and Highways maintains the 22 * current levels of traffic flow throughout the network. 39 23 * 40 * Highways uses method writeToFEP() to communicate with the FEP Simulator. It 41 * creates a socket client which sends the FEP Simulator a highways status 42 * message over the socket. This message is sent in the format required by the 43 * FEP Simulator. 24 * Highways builds an internal representation of the highway network 25 * from VDS data (obtained from PeMS) The current state of the network 26 * is output to a json file for use by CPTMS. 44 27 * 45 * 46 * @author John A. Torres 28 * @author John A. Torres, jdalbey 47 29 */ 48 30 final public class Highways 49 31 { 50 51 final private String FEPHostName;52 final private int FEPPortNum;53 54 final private List<FEPLine> lines;55 32 final public List<Highway> highways; 56 33 57 public Highways(String highwaysMapFileName, String FEPHostName, int FEPPortNum) 58 { 59 // load FEP Lines 60 lines = loadLines(highwaysMapFileName); 61 // build highways data structure 62 this.highways = buildHighways(); 63 64 // write to FEP host and port number 65 this.FEPHostName = FEPHostName; 66 this.FEPPortNum = FEPPortNum; 67 } 68 69 private ArrayList<Highway> buildHighways() 70 { 34 public Highways(String highwaysMapFileName) 35 { 36 // build highways data structure 37 this.highways = buildHighwayNetwork(highwaysMapFileName); 38 } 39 40 private ArrayList<Highway> buildHighwayNetwork(String highwaysMapFileName) 41 { 42 // NOTE: Could this method be streamlined? Is it necessary to have the 43 // second data structure? 71 44 System.out.println("Building highways..."); 72 45 // The list of highways to return … … 76 49 Map<Integer, ArrayList<Station>> highwayMap = new HashMap<>(); 77 50 78 // iterate through FEPLines and get data to add to the above map79 for (FEPLine line : lines)80 {81 // grab all stations from the current FEPLine82 ArrayList<Station> lineStations = (ArrayList<Station>) line.stations;83 // iterate through each station in the list of stations84 for (Station station : lineStations)85 {51 // Open the postmile file and scan each line 52 File file = new File(highwaysMapFileName); 53 try 54 { 55 Scanner scanner = new Scanner(file); 56 while (scanner.hasNext()) 57 { 58 Station station = loadStation(scanner); 86 59 Integer hwyNum = station.routeNumber; 87 60 // if the map does not contain an entry for the highway, create … … 101 74 } 102 75 } 103 } 104 76 }catch (FileNotFoundException e) { 77 e.printStackTrace(); 78 } 105 79 // get the set of highway numbers 106 80 Set<Integer> hwyKeys = highwayMap.keySet(); … … 229 203 } 230 204 205 231 206 /** 232 * Loads all FEPLines from the specified highways map file. 233 * 234 * @param highwaysMapFileName 235 * @return List of FEPLines 236 */ 237 private ArrayList<FEPLine> loadLines(String highwaysMapFileName) 238 { 239 ArrayList<FEPLine> lines = new ArrayList<>(); 240 try 241 { 242 Scanner sc = new Scanner(new File(highwaysMapFileName)); 243 // first line of file contains number of FEP Lines 244 String firstLine = sc.nextLine(); 245 Scanner linesc = new Scanner(firstLine); 246 int numLines = linesc.nextInt(); 247 linesc.close(); 248 // FOR each FEP Line 249 for (int i = 0; i < numLines; i++) 250 { 251 lines.add(loadLine(sc)); 252 } 253 sc.close(); 254 255 } catch (FileNotFoundException ex) 256 { 257 Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 258 } 259 return lines; 260 } 261 262 /** 263 * Load all the stations for a single FEP Line from the highways map file. 264 * 265 * @param sc scanner at the current FEPLine line 266 * @return FEPLine 267 */ 268 private FEPLine loadLine(Scanner sc) 207 * Loads a single Station from the postmile coordinates file 208 * @param sc scanner at the current station line 209 * @return Station 210 */ 211 private Station loadStation(Scanner sc) 269 212 { 270 213 String line = sc.nextLine(); 271 214 Scanner scline = new Scanner(line); 272 // Get the attributes of this FEP Line 273 int lineNum = scline.nextInt(); 274 int count = scline.nextInt(); 275 int numStations = scline.nextInt(); 215 scline.useDelimiter(","); 276 216 277 // initialze stations array 278 ArrayList<Station> stations = new ArrayList<>(); 279 // Read all the stations for thie FEP Line 280 for (int i = 0; i < numStations; i++) 281 { 282 stations.add(loadStation(sc, lineNum)); 283 } 284 285 return new FEPLine(lineNum, stations, count); 286 } 287 288 /** 289 * Loads a single Station from the highways map file 290 * @param sc scanner at the current station line 291 * @param lineNum the FEPLine number for the station 292 * @return Station 293 */ 294 private Station loadStation(Scanner sc, int lineNum) 295 { 296 String line = sc.nextLine(); 297 Scanner scline = new Scanner(line); 298 299 int ldsID = scline.nextInt(); 300 int drop = scline.nextInt(); 301 int fwy = scline.nextInt(); 302 DIRECTION dir = DIRECTION.toDirection(scline.next()); 303 double postmile = scline.nextDouble(); 304 int numLoops = scline.nextInt(); 305 String location = getStationLoc(line); 217 String route = scline.next(); // FWY DIR POSTMILE 218 scline.next(); // skip lat 219 scline.next(); // skip long 220 String description = scline.next(); // the description of the location 221 222 Scanner rteScan = new Scanner(route); 223 int fwy = rteScan.nextInt(); 224 DIRECTION dir = DIRECTION.toDirection(rteScan.next()); 225 double postmile = rteScan.nextDouble(); 226 306 227 ArrayList<LoopDetector> loops = new ArrayList<>(); 307 for (int i = 0; i < numLoops; i++) 308 { 309 loops.add(loadLoop(sc)); 310 } 311 312 return new Station(lineNum, ldsID, drop, location, loops, fwy, dir, postmile); 313 } 314 315 /** 316 * Loads a single loop from the highways map file 317 * 318 * @param sc scanner at the current loop line 319 * @return LoopDetector 320 */ 321 private LoopDetector loadLoop(Scanner sc) 322 { 323 String line = sc.nextLine(); 324 Scanner scline = new Scanner(line); 325 326 int loopID = scline.nextInt(); 327 String loopLocID = scline.next(); 328 String loopLoc = scline.next(); 329 scline.close(); 330 return new LoopDetector(loopID, loopLocID, loopLoc); 331 } 332 333 /** 334 * Scans the LoopDetector line and grabs the String location from the line. 335 * 336 * @param line the line containing the location 337 * @return A String loop location. 338 */ 339 private String getLoopLoc(String line) 340 { 341 Scanner sc = new Scanner(line); 342 sc.nextInt(); 343 344 // GRABS FROM CURRENT TO END OF LINE 345 sc.useDelimiter("\\z"); 346 String loc = sc.next().trim(); 347 sc.close(); 348 return loc; 349 } 350 351 /** 352 * Scans the Station line and grabs the String location from the line. 353 * 354 * @param line the line containing the location 355 * @return A String station location. 356 */ 357 private String getStationLoc(String line) 358 { 359 Scanner scline = new Scanner(line); 360 scline.nextInt(); 361 scline.nextInt(); 362 scline.nextInt(); 363 scline.next(); 364 scline.nextDouble(); 365 scline.nextInt(); 366 367 // GRABS FROM CURRENT TO END OF LINE 368 scline.useDelimiter("\\z"); 369 String loc = scline.next().trim(); 370 scline.close(); 371 return loc; 372 } 373 374 /** 375 * Creates a socket client that writes the Highways data to the FEP Simulator. 376 * 377 * @throws SimulationException 378 */ 379 public void writeToFEP() throws SimulationException 380 { 381 try 382 { 383 // Create the socket to the FEP Simulator 384 Socket sock = new Socket(FEPHostName, FEPPortNum); 385 PrintWriter out = new PrintWriter(sock.getOutputStream(), true); 386 387 // Print the number of bytes the highways data message contains 388 System.out.println("Highways sending " + this.toCondensedFormat(false).toCharArray().length + 1 + "bytes to FEPSIM."); 389 String outMsg = this.toCondensedFormat(false); 390 // Write the highways data over the socket 391 out.println(outMsg); 392 393 // close the socket 394 sock.close(); 395 } catch (java.net.ConnectException ex) 396 { 397 //Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 398 System.out.println("writeToFEP() can't connect, no data sent to FEP."); 399 throw new SimulationException(SimulationException.BINDING); 400 } catch (IOException ex) 401 { 402 //Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 403 System.out.println("Highway Model failed writing to FEPSim."); 404 throw new SimulationException(SimulationException.BINDING); 405 } 406 } 407 408 /** Returns a string of highways data. If MetaDataOnly is true, you get a full 409 * dump of the highways meta data, which does not include dynamic loop values, 410 * and does include the string location names. If MetaDataOnly is false, 411 * dynamic loop values are included, and unnecessary information like string 412 * location values are not included. 413 * 414 * The FEPSimulator takes in the toCondensedFormat() output, with a MetaDataOnly 415 * value of false, over the socket. 416 * 417 * The MetaDataOnly flag should be used to get a full dump of the highways 418 * information. This was used to get the highways_fullmap.txt output. 419 * 420 * @param MetaDataOnly Whether you want meta data, or a full dump for FEPSim 421 * @return String, highways data in condensed format 422 * 423 * Example toCondensedFormat(MetaDataOnly = false) output: 424 * 425 * 43 // "number of lines" 426 * 32 0 13 // "line id" "count num" "number of stations" 427 * 1210831 1 5 S 0.9 8 // "station id" "drop num" "route num"... 428 * // ..."direction" "postmile" "number of loops" 429 * 1210832 0.0 0 ML_1 // "loop id" "occ" "vol" 430 * 1210833 0.0 0 ML_2 // .. 431 * 1210834 0.0 0 ML_3 // .. 432 * 1210835 0.0 0 ML_4 // .. 433 * 1210836 0.0 0 PASSAGE // .. 434 * 1210837 0.0 0 DEMAND // .. 435 * 1210838 0.0 0 QUEUE // .. 436 * 1210839 0.0 0 RAMP_OFF // .. 437 * ... 438 * 439 * Example toCondensedFormat(MetaDataOnly = true) output: 440 * 441 * 43 // "number of lines" 442 * 32 0 13 // "line id" "count num" "number of stations" 443 * 1210831 1 5 S 0.9 8 CALAFIA // "station id" "drop num" "route num"... 444 * // ..."direction" "postmile"... 445 * // ..."number of loops" "string location" 446 * 1210832 ML_1 // "loop id" "loop location" 447 * 1210833 ML_2 // " " 448 * 1210834 ML_3 // " " 449 * 1210835 ML_4 // " " 450 * 1210836 PASSAGE // " " 451 * 1210837 DEMAND // " " 452 * 1210838 QUEUE // " " 453 * 1210839 RAMP_OFF // " " 454 * ... 455 */ 456 public String toCondensedFormat(boolean MetaDataOnly) 457 { 458 // first line: number of FEPLines 459 StringBuilder build = new StringBuilder(); 460 build.append(lines.size()); 461 build.append("\n"); 462 // append each fep line to the string 463 for(FEPLine line : lines) 464 { 465 build.append(line.toCondensedFormat(MetaDataOnly)); 466 } 467 // return the full condensed format string 468 return build.toString(); 469 } 470 471 /** 472 * Returns the Highways model data in XML format. 473 * Probably obsolete, since we aren't using exchange.xml any longer. 474 * @return highways data in XML format 475 */ 476 public String toXML() 477 { 478 String xml = null; 479 try 480 { 481 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 482 DocumentBuilder builder = factory.newDocumentBuilder(); 483 Document theDoc = builder.newDocument(); 484 485 Element networkElement = theDoc.createElement(XML_TAGS.NETWORK.tag); 486 theDoc.appendChild(networkElement); 487 488 for (FEPLine line : lines) 489 { 490 line.toXML(networkElement); 491 } 492 493 Transformer tf = TransformerFactory.newInstance().newTransformer(); 494 495 tf.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); 496 tf.setOutputProperty(OutputKeys.INDENT, "yes"); 497 tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); 498 499 Writer out = new StringWriter(); 500 tf.transform(new DOMSource(theDoc), new StreamResult(out)); 501 xml = out.toString(); 502 out.close(); 503 } catch (Exception ex) 504 { 505 Logger.getLogger(Highways.class.getName()).log(Level.SEVERE, null, ex); 506 } 507 return xml; 508 509 } 510 228 // For now we'll use just a dummy loop detector 229 LoopDetector detector = new LoopDetector(1,"ML","ML_1"); 230 loops.add(detector); 231 232 return new Station(11, 123, 99, description, loops, fwy, dir, postmile); 233 } 234 511 235 /** 512 236 * Returns a highway by given highway number. … … 531 255 } 532 256 533 /** Return a string representation of the Highways */257 /** Return a string representation of the Highways - for debugging */ 534 258 public String toString() 535 259 { … … 543 267 StringBuilder lineout = new StringBuilder(); 544 268 // Examine every station on this highway and direction 545 for (Station stat : hwy.stations)546 { 547 if (stat .direction.equals(dir))269 for (Station station: hwy.stations) 270 { 271 if (station.direction.equals(dir)) 548 272 { 549 273 //lineout.append("" + dir.getLetter() + stat.postmile); 550 lineout.append(stat .getColor());274 lineout.append(station.getColor().symbol()); 551 275 //lineout.append(" "); 552 276 } … … 616 340 String outString = currentPM.toJson(); 617 341 // replace the color code with the color name 618 String colorName=stat.getColor Name();342 String colorName=stat.getColor().htmlColor(); 619 343 outString = outString.replace("desiredcolor",colorName); 620 344 lineout.append(outString); … … 664 388 } 665 389 666 public void reset() 667 { 668 for(FEPLine line : lines) 669 { 670 for(Station stn : line.stations) 390 /** Reset all the traffic levels to free flowing (green) */ 391 public void reset() 392 { 393 for(Highway hwy: highways) 394 { 395 for(Station stn : hwy.stations) 671 396 { 672 397 for(LoopDetector ld : stn.loops) 673 398 { 674 ld.occ = 0; 675 ld.vol = 0; 399 ld.setAttributes(LoopDetector.DOTCOLOR.GREEN); 676 400 } 677 401 }
Note: See TracChangeset
for help on using the changeset viewer.
