package atmsdriver; import tmcsim.highwaymodel.Highways; import tmcsim.highwaymodel.Station.DIRECTION; import tmcsim.highwaymodel.Highway; import tmcsim.highwaymodel.Station; import tmcsim.highwaymodel.LoopDetector.DOTCOLOR; import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; import tmcsim.common.SimulationException; /** * A console application to drive the ATMS Server. * Use for test driving the FEP Simulator. OBSOLETE as of completion of CPTMS. * * @author jdalbey, John A. Torres * @version 10/11/2017 */ public final class ConsoleTrafficDriver { // highways model private final Highways highways; // lists used for user input validation private final List routeNumInputList; /** * Properties for the ConsoleTrafficDriver */ private static Properties ConsoleDriverProperties; /** Entry point for the application. * * @param args unused */ public static void main(String[] args) { try { if (System.getProperty("ATMSDRIVER_PROPERTIES") != null) { // Load properties of runtime parameters if (!loadProperties()) { System.exit(0); } // Create the Highway Model Highways highways = new Highways( "config/vds_data/highways_fullmap.txt"); // Construct the console driver using the highways model ConsoleTrafficDriver driver = new ConsoleTrafficDriver(highways); driver.runConsole(); } else { throw new Exception("ATMSDRIVER_PROPERTIES system property not defined."); } } catch (Exception e) { Logger.getLogger("ConsoleDriver").logp(Level.SEVERE, "ConsoleDriver", "Main", "Error occured initializing application", e); System.exit(-1); } } /** * Load the properties file containing values for runtime parameters. * * @param propertiesFile * @return */ private static boolean loadProperties() { // Load the properties file. try { ConsoleDriverProperties = new Properties(); ConsoleDriverProperties.load(new FileInputStream(System.getProperty("ATMSDRIVER_PROPERTIES"))); } catch (Exception e) { Logger.getLogger("ConsoleDriver").logp(Level.SEVERE, "ConsoleDriver", "Constructor", "Exception in reading properties file.", e); } return true; } /** * Constructor. Sets the highways model and generates the input validation * lists, and then runs the console driver application. * @param highways */ public ConsoleTrafficDriver(Highways highways) { // set highways model this.highways = highways; // set input validation lists routeNumInputList = generateRouteNumInputList(); } /** * Generates the route number list, used for user input validation. * @return list of route numbers. */ private ArrayList generateRouteNumInputList() { ArrayList routeNums = new ArrayList<>(); // add the route number for each highway to the list for(Highway hwy : highways.highways) { routeNums.add(hwy.routeNumber); } return routeNums; } /** * Runs the console driver application. */ public void runConsole() { Scanner sc = new Scanner(System.in); char choice = 'A'; // Run continuously while (choice != 'Q') { // Get necessary values for colorization of highways Integer routeNumber = getRouteNumber(sc); DIRECTION direction = getDirection(sc, routeNumber); Double postmile = getPostmile(sc, routeNumber, direction); Double range = getRange(sc, postmile); DOTCOLOR dotcolor = getDotColor(sc); // apply colorization to highways highways.applyColorToHighwayStretch(routeNumber, direction, postmile, range, dotcolor); System.out.println("Add another entry or Send now? (A/S)"); choice = sc.next().toUpperCase().trim().charAt(0); System.out.println(""); if (choice == 'S') { // Send highway model to FEP for transmit to ATMS highways.toJson(); System.out.println("Add another entry or Quit? (A/Q)"); choice = sc.next().toUpperCase().trim().charAt(0); } } } /** * Gets the highway route number from user and validates the input. * * @param sc stdIn scanner * @return highway route number */ private Integer getRouteNumber(Scanner sc) { Integer routeNum = null; Boolean verified = false; // validation loop while(!verified) { // Prints out available route numbers to user to select from System.out.print("Available route numbers: ["); for(Integer rtNum : routeNumInputList) { System.out.print(rtNum.toString() + ", "); } System.out.print("]"); System.out.println(""); // Prompt user to input a route number System.out.println("Enter a route number: "); routeNum = sc.nextInt(); System.out.println(""); // validate the user's input if(routeNumInputList.contains(routeNum)) { verified = true; } else { System.out.println("Invalid route number, please re-enter: "); } } return routeNum; } /** * Gets the highway direction from the user and validates the input. * * @param sc stdIn scanner * @return highway direction */ private DIRECTION getDirection(Scanner sc, Integer routeNum) { DIRECTION direction; String directionInput = null; Boolean verified = false; // validation loop while(!verified) { // Get available directions for route ArrayList availDirs = new ArrayList<>(); for(Station stn : highways.getHighwayByRouteNumber(routeNum).stations) { if(!availDirs.contains(stn.direction)) { availDirs.add(stn.direction); } } // prompt user for input System.out.print("Available directions for highway " + routeNum + ": ["); for(DIRECTION dir : availDirs) { System.out.print(dir.getLetter() + ", "); } System.out.print("]"); System.out.println(""); System.out.println("Enter a direction:"); directionInput = sc.next().toUpperCase(); System.out.println(""); // validate the user's input if(availDirs.contains(DIRECTION.toDirection(directionInput))) { verified = true; } else { System.out.println("Invalid direction, please re-enter: "); } } return DIRECTION.toDirection(directionInput); } /** * Gets the starting/origin postmile value for the highway section from the * user and validates the input. * * @param sc stdIn scanner * @param routeNumber highway route number * @param dir highway direction * @return highway section start/origin postmile value */ private Double getPostmile(Scanner sc, Integer routeNumber, DIRECTION dir) { Double postmile = null; Boolean verified = false; // validation loop while(!verified) { // Get highway, and grab the floor and ceiling for postmile values // from the highway stations to present to the user Highway hwy = highways.getHighwayByRouteNumber(routeNumber); Double floorPostmile = hwy.stations.get(0).postmile; Double ceilPostmile = hwy.stations .get(hwy.stations.size() - 1).postmile; // present user with range of postmiles for given highway System.out.println("Route " + hwy.routeNumber + " " + dir + " postmile range: [" + floorPostmile + ", " + ceilPostmile + "]"); // prompt user for postmile value System.out.println("Enter a postmile value (Integer/Double): "); postmile = sc.nextDouble(); System.out.println(""); // validate user's input, ensures that the postmile is within given // postmile range (floorPostmile, ceilPostmile) if(postmile >= floorPostmile && postmile <= ceilPostmile) { verified = true; } else { System.out.println("Postmile must be within postmile range: [" + floorPostmile + ", " + ceilPostmile + "] please re-enter: "); } } return postmile; } /** * Gets the range to extend the highway stretch from the start/origin postmile * value from the user and validates the input. * * @param sc stdIn scanner * @param postmile origin/start postmile value for highway stretch * @return range value */ private Double getRange(Scanner sc, Double postmile) { Double range = null; Boolean verified = false; // validation loop while(!verified) { // prompt user for range value System.out.println("Enter a range value (decimal):"); range = sc.nextDouble(); System.out.println(""); // range must be greater than or equal to 0 if(range >= 0) { verified = true; } else { System.out.println("Range must be >= 0"); } } return range; } /** * Gets the dot color from the user, to be applied to specified highway * stretch and validates the user's input. * * @param sc stdIn scanner * @return dot color to be applied to highway stretch */ private DOTCOLOR getDotColor(Scanner sc) { DOTCOLOR dotColor; String dotColorInput = null; Boolean verified = false; // validationloop while(!verified) { // prompt user for color System.out.println("Enter a dot color (G/Y/R):"); dotColorInput = sc.next().toUpperCase(); System.out.println(""); // validate user's input if(DOTCOLOR.allLetters.contains(dotColorInput)) { verified = true; } else { System.out.println("Invalid dot color, please re-enter: "); } } return DOTCOLOR.toDotColor(dotColorInput); } }