Warning: Can't use blame annotator:
svn blame failed on trunk/src/atmsdriver/ConsoleDriver.java: ("Can't find a temporary directory: Internal error", 20014)

source: tmcsimulator/trunk/src/atmsdriver/ConsoleDriver.java @ 139

Revision 139, 15.3 KB checked in by jdalbey, 9 years ago (diff)

ConsoleDriver?: Changed range from int to double.

RevLine 
1package atmsdriver;
2
3import atmsdriver.model.Highways;
4import atmsdriver.model.Station.DIRECTION;
5import atmsdriver.model.Highway;
6import atmsdriver.model.Station;
7import java.io.FileInputStream;
8import java.util.ArrayList;
9import java.util.Arrays;
10import java.util.List;
11import java.util.Properties;
12import java.util.Scanner;
13import java.util.logging.Level;
14import java.util.logging.Logger;
15import tmcsim.common.SimulationException;
16
17/**
18 * A console application to drive the ATMS Server.
19 *
20 * @author jdalbey, John A. Torres
21 * @version 10/11/2017
22 */
23public final class ConsoleDriver {
24    // highways model
25    private final Highways highways;
26   
27    // lists used for user input validation
28    private final List<Integer> routeNumInputList;
29    private final List<String> dotColorInputList;
30    /**
31     * Properties for the ConsoleDriver
32     */
33    private static Properties ConsoleDriverProperties;
34
35    /** Entry point for the application.
36     *
37     * @param args unused
38     */
39    public static void main(String[] args) {
40        try {
41            if (System.getProperty("ATMSDRIVER_PROPERTIES") != null) 
42            {
43                // Load properties of runtime parameters
44                if (!loadProperties()) 
45                {
46                    System.exit(0);
47                }       
48                // Create the Highway Model
49                Highways highways = new Highways(
50                    "config/vds_data/lds.txt",
51                    "config/vds_data/loop.txt",
52                    "config/vds_data/highwaysMeta.txt",
53                    ConsoleDriverProperties.getProperty(
54                        "FEPWriterHost"),
55                    Integer.parseInt(ConsoleDriverProperties.getProperty(
56                        "FEPWriterPort")));
57
58                // Construct the console driver using the highways model
59                ConsoleDriver driver = new ConsoleDriver(highways);
60                driver.runConsole();   
61            } else {
62                throw new Exception("ATMSDRIVER_PROPERTIES system property not defined.");
63            }
64        } catch (Exception e) {
65            Logger.getLogger("ConsoleDriver").logp(Level.SEVERE, "ConsoleDriver", "Main",
66                    "Error occured initializing application", e);
67            System.exit(-1);
68        }
69    }   
70    /**
71     * Load the properties file containing values for runtime parameters.
72     *
73     * @param propertiesFile
74     * @return
75     */
76    private static boolean loadProperties() 
77    {
78        // Load the properties file.
79        try {
80            ConsoleDriverProperties = new Properties();
81            ConsoleDriverProperties.load(new FileInputStream(System.getProperty("ATMSDRIVER_PROPERTIES")));
82        } catch (Exception e) {
83            Logger.getLogger("CosoleDriver").logp(Level.SEVERE, "ConsoleDriver",
84                    "Constructor", "Exception in reading properties file.", e);
85        }
86
87        return true;
88    }
89    /**
90     * Constructor. Sets the highways model and generates the input validation
91     * lists, and then runs the console driver application.
92     * @param highways
93     */
94    public ConsoleDriver(Highways highways) {
95        // set highways model
96        this.highways = highways;
97       
98        // set input validation lists
99        routeNumInputList = generateRouteNumInputList();
100        dotColorInputList = new ArrayList<>(Arrays.asList("R", "Y", "G"));       
101    }
102   
103    /**
104     * Generates the route number list, used for user input validation.
105     * @return list of route numbers.
106     */
107    private ArrayList<Integer> generateRouteNumInputList()
108    {
109        ArrayList<Integer> routeNums = new ArrayList<>();
110        // add the route number for each highway to the list
111        for(Highway hwy : highways.highways)
112        {
113            routeNums.add(hwy.routeNumber);
114        }
115        return routeNums;
116    }
117
118    /**
119     * Runs the console driver application.
120     */
121    public void runConsole() {
122        Scanner sc = new Scanner(System.in);
123        // Run continuously
124        while (true) {
125            // Get necessary values for colorization of highways
126            Integer routeNumber = getRouteNumber(sc);
127            DIRECTION direction = getDirection(sc, routeNumber);
128            Double postmile = getPostmile(sc, routeNumber, direction);
129            Double range = getRange(sc, postmile);
130            DOTCOLOR dotcolor = getDotColor(sc);
131           
132            // apply colorization to highways
133            applyColorToHighwayStretch(routeNumber, direction, postmile, range, dotcolor);
134        }
135    }
136   
137    /**
138     * Applies specified color to the specified highway stretch. Route number and
139     * direction specify the highway. Postmile and range specify the stretch of
140     * specified highway. Dot color is the color to be applied to the stretch.
141     *
142     * @param routeNumber highway route number
143     * @param direction highway direction
144     * @param postmile origin postmile value
145     * @param range range from origin postmile
146     * @param dotColor the color to be applied to specified highway stretch
147     */
148    public void applyColorToHighwayStretch(Integer routeNumber, DIRECTION direction, 
149            Double postmile, Double range, DOTCOLOR dotColor) {
150        System.out.println("Applying " + dotColor.name() + " dots to highway " 
151                + routeNumber + " " + direction.name() + " at postmile " 
152                + postmile + " with a range of " + range + " miles...");
153       
154        // Get the highway by route number
155        Highway highway = highways.getHighwayByRouteNumber(routeNumber);
156       
157        // start value for highway section, and end value for highway section
158        // by postmile
159        Double startPost;
160        Double endPost;
161       
162        // postmiles increase from s to n and w to e
163       
164        // if the direction is south or west
165        if(direction.equals(DIRECTION.SOUTH) || direction.equals(DIRECTION.WEST))
166        {
167            // add range value to startPost to get
168            // the end postmile value of the highway section
169            startPost = postmile;
170            endPost = postmile + range;
171           
172            // iterate through the stations, if within the specified highway
173            // stretch, update the station by direction and apply dot color
174            for(Station station : highway.stations)
175            {
176                if(station.postmile > startPost && station.postmile < endPost)
177                {
178                    station.updateByDirection(direction, dotColor);
179                }
180            }
181        }
182        // if the direction is north or east
183        else
184        {
185            //subtract range value from startPost
186            // to get the end postmile value of the highway section
187            startPost = postmile;
188            endPost = postmile - range;
189           
190            // iterate through the stations, if within the specified highway
191            // section, update the station by direction and apply dot color
192            for(Station station : highway.stations)
193            {
194                if(station.postmile < startPost && station.postmile > endPost)
195                {
196                    station.updateByDirection(direction, dotColor);
197                }
198            }
199        }
200        System.out.println("");
201        try {
202            highways.writeToFEP();
203        } catch (SimulationException ex) {
204            System.out.println("Skipping writeToFEP...");
205        }
206    }
207   
208    /**
209     * Gets the highway route number from user and validates the input.
210     *
211     * @param sc stdIn scanner
212     * @return highway route number
213     */
214    private Integer getRouteNumber(Scanner sc) {
215        Integer routeNum = null;
216        Boolean verified = false;
217       
218        // validation loop
219        while(!verified)
220        {
221            // Prints out available route numbers to user to select from
222            System.out.print("Available route numbers: [");
223            for(Integer rtNum : routeNumInputList)
224            {
225                System.out.print(rtNum.toString() + ", ");
226            }
227            System.out.print("]");
228            System.out.println("");
229           
230            // Prompt user to input a route number
231            System.out.println("Enter a route number: ");
232            routeNum = sc.nextInt();
233            System.out.println("");
234           
235            // validate the user's input
236            if(routeNumInputList.contains(routeNum))
237            {
238                verified = true;
239            }
240            else
241            {
242                System.out.println("Invalid route number, please re-enter: ");
243            }
244        }
245       
246        return routeNum;
247    }
248   
249    /**
250     * Gets the highway direction from the user and validates the input.
251     *
252     * @param sc stdIn scanner
253     * @return highway direction
254     */
255    private DIRECTION getDirection(Scanner sc, Integer routeNum) {
256        DIRECTION direction;
257        String directionInput = null;
258        Boolean verified = false;
259       
260        // validation loop
261        while(!verified)
262        {
263            // Get available directions for route
264            ArrayList<DIRECTION> availDirs = new ArrayList<>();
265            for(Station stn : highways.getHighwayByRouteNumber(routeNum).stations)
266            {
267                if(!availDirs.contains(stn.direction))
268                {
269                    availDirs.add(stn.direction);
270                }
271            }
272           
273            // prompt user for input
274            System.out.print("Available directions for highway " + routeNum + ": [");
275            for(DIRECTION dir : availDirs)
276            {
277                System.out.print(dir.getLetter() + ", ");
278            }
279            System.out.print("]");
280            System.out.println("");
281            System.out.println("Enter a direction:");
282            directionInput = sc.next().toUpperCase();
283            System.out.println("");
284           
285            // validate the user's input
286            if(availDirs.contains(DIRECTION.toDirection(directionInput)))
287            {
288                verified = true;
289            }
290            else
291            {
292                System.out.println("Invalid direction, please re-enter: ");
293            }
294        }
295       
296        return DIRECTION.toDirection(directionInput);
297    }
298   
299    /**
300     * Gets the starting/origin postmile value for the highway section from the
301     * user and validates the input.
302     *
303     * @param sc stdIn scanner
304     * @param routeNumber highway route number
305     * @param dir highway direction
306     * @return highway section start/origin postmile value
307     */
308    private Double getPostmile(Scanner sc, Integer routeNumber, DIRECTION dir) {
309        Double postmile = null;
310        Boolean verified = false;
311       
312        // validation loop
313        while(!verified)
314        {
315            // Get highway, and grab the floor and ceiling for postmile values
316            // from the highway stations to present to the user
317            Highway hwy = highways.getHighwayByRouteNumber(routeNumber);
318            Double floorPostmile = hwy.stations.get(0).postmile;
319            Double ceilPostmile = hwy.stations
320                    .get(hwy.stations.size() - 1).postmile;
321           
322            // present user with range of postmiles for given highway
323            System.out.println("Route " + hwy.routeNumber + " " + dir
324                    + " postmile range: [" + floorPostmile + ", " 
325                    + ceilPostmile + "]");
326           
327            // prompt user for postmile value
328            System.out.println("Enter a postmile value (Integer/Double): ");
329            postmile = sc.nextDouble();
330            System.out.println("");
331           
332            // validate user's input, ensures that the postmile is within given
333            // postmile range (floorPostmile, ceilPostmile)
334            if(postmile >= floorPostmile && postmile <= ceilPostmile)
335            {
336                verified = true;
337            }
338            else
339            {
340                System.out.println("Postmile must be within postmile range: [" + floorPostmile + ", " 
341                    + ceilPostmile + "] please re-enter: ");
342            }
343        }
344       
345        return postmile;
346    }
347   
348    /**
349     * Gets the range to extend the highway stretch from the start/origin postmile
350     * value from the user and validates the input.
351     *
352     * @param sc stdIn scanner
353     * @param postmile origin/start postmile value for highway stretch
354     * @return range value
355     */
356    private Double getRange(Scanner sc, Double postmile) {
357        Double range = null;
358        Boolean verified = false;
359       
360        // validation loop
361        while(!verified)
362        {
363            // prompt user for range value
364            System.out.println("Enter a range value (decimal):");
365            range = sc.nextDouble();
366            System.out.println("");
367           
368            // range must be greater than or equal to 0
369            if(range >= 0)
370            {
371                verified = true;
372            }
373            else
374            {
375                System.out.println("Range must be >= 0");
376            }
377        }
378       
379        return range;
380    }
381
382    /**
383     * Gets the dot color from the user, to be applied to specified highway
384     * stretch and validates the user's input.
385     *
386     * @param sc stdIn scanner
387     * @return dot color to be applied to highway stretch
388     */
389    private DOTCOLOR getDotColor(Scanner sc) {
390        DOTCOLOR dotColor;
391        String dotColorInput = null;
392        Boolean verified = false;
393       
394        // validationloop
395        while(!verified)
396        {
397            // prompt user for color
398            System.out.println("Enter a dot color (G/Y/R):");
399            dotColorInput = sc.next();
400            System.out.println("");
401            // validate user's input
402            if(dotColorInputList.contains(dotColorInput))
403            {
404                verified = true;
405            }
406            else
407            {
408                System.out.println("Invalid dot color, please re-enter: ");
409            }
410        }
411       
412        return DOTCOLOR.toDotColor(dotColorInput);
413    }
414   
415    /**
416     * Enum for highway status dot colors. Each color has associated volume
417     * and occupancy constants.
418     *
419     * @author John A. Torres, jdalbey
420     * @version 10/11/2017
421     */
422    public static enum DOTCOLOR {
423
424        RED(10,10),
425        YELLOW(5,5),
426        GREEN(0,0);
427       
428        // All the first letters of the values, in order.
429        private static String allLetters = "RYG";
430       
431        private int vol;  /* volume */
432        private int occ;  /* occupancy */     
433       
434        private DOTCOLOR(int v, int o)
435        {
436            vol = v;
437            occ = o;
438        }
439        /**
440         * Return the first letter of this enum.
441         *
442         * @return String first letter of this enum.
443         */
444        public String getLetter() {
445            return this.toString().substring(0, 1);
446        }
447
448        public int volume()
449        {
450            return vol;
451        }
452        public int occupancy()
453        {
454            return occ;
455        }
456        /**
457         * Returns a dot color given its first character.
458         *
459         * @param letter the first character of a dot color
460         * @return dot color corresponding to letter
461         * @pre letter must be one of allLetters
462         */
463        public static DOTCOLOR toDotColor(String letter) {
464            return values()[allLetters.indexOf(letter.charAt(0))];
465        }
466    } 
467}
Note: See TracBrowser for help on using the repository browser.