From 92504f7d922a1dc58b3e1295a96db046821d436f Mon Sep 17 00:00:00 2001 From: Fennel Kora Date: Thu, 2 May 2024 22:35:22 -0400 Subject: [PATCH] actual final state, removing compiled files --- .project | 11 ++ Climate.java | 99 ++++++++++------ DrivingRoute.txt | 12 -- DrivingRoute1.txt | 12 ++ DrivingRoute2.txt | 7 ++ Entertainment.java | 11 +- HelperFunctions.java | 38 +++++- RoadSensor.java | 38 ++++-- Route.java | 23 ++-- SelfDrivingRoadtrip.java | 249 ++++++++++++++++++++++++++++++++++++++- Vehicle.java | 115 +++++++++++------- 11 files changed, 499 insertions(+), 116 deletions(-) delete mode 100644 DrivingRoute.txt create mode 100644 DrivingRoute1.txt create mode 100644 DrivingRoute2.txt diff --git a/.project b/.project index e513f1d..d6dc9e2 100644 --- a/.project +++ b/.project @@ -14,4 +14,15 @@ org.eclipse.jdt.core.javanature + + + 1714702259358 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/Climate.java b/Climate.java index eee6e1e..d7f963c 100644 --- a/Climate.java +++ b/Climate.java @@ -1,14 +1,37 @@ //for all arrays, index 0 is driver's side, index 1 is passenger's side -public class Climate { - private int[] targetTemp; //array to store temp preference entered by user - private int[] currentTemp; //stores current internal temp from last check +public class Climate implements Runnable { + private int[] targetTemp = new int[2]; //array to store temp preference entered by user + private int[] currentTemp = new int[2]; //stores current internal temp from last check private int externalTemp; //stores current external temp from last check - private boolean[] coolingActive; //whether cooling is toggled on (true) or off (false) - private boolean[] heatingActive; //whether heating is toggled on (true) or off (false) + private boolean[] coolingActive = new boolean[2]; //whether cooling is toggled on (true) or off (false) + private boolean[] heatingActive = new boolean[2]; //whether heating is toggled on (true) or off (false) public enum fanLevels {OFF, LOW, MED, HI}; //standardization of fan levels - fanLevels[] fanSpeed; //array to store fan speeds, zones match temp indices + fanLevels[] fanSpeed = new fanLevels[2];; //array to store fan speeds, zones match temp indices + public void run() { + while (currentTemp[0] != targetTemp[0] || currentTemp[1] != targetTemp[1]) { + displayInformation(); + activateClimate(); + adjustClimate(0); + adjustClimate(1); + HelperFunctions.sleep(1); + } + System.out.println("Climate adjustment complete"); + HelperFunctions.pressEnterToContinue(); + } + + public Climate() { + targetTemp = new int[2]; + currentTemp = new int[2]; + targetTemp[0] = 72; + targetTemp[1] = 74; + updateCurrentTemps(); + fanSpeed = new fanLevels[2]; + fanSpeed[0] = fanLevels.LOW; + fanSpeed[1] = fanLevels.LOW; + } + public void setTargetTemp(int driverZone, int passengerZone) { //temp range should be between 65 F and 90 F, these if statements prohibit temps outside that range if (driverZone < 65) {driverZone = 65;} @@ -39,52 +62,57 @@ public class Climate { } public void activateClimate() { - updateCurrentTemps(); //check current temps before actioning logic - if (externalTemp >= avgTargetTemp()) { //puts logic into "cooling" mode - //driver's side - if (targetTemp[0]+1 < currentTemp[0]) {coolingActive[0] = true;} //provides 1 deg buffer to prevent excessive activation/deactivation - if (targetTemp[0] >= currentTemp[0]) {coolingActive[0] = false;} - //passenger's side - if (targetTemp[1]+1 < currentTemp[1]) {coolingActive[1] = true;} - if (targetTemp[1] >= currentTemp[1]) {coolingActive[1] = false;} - } else if (externalTemp < avgTargetTemp()) { //puts logic into "heating" mode - //driver's side - if (targetTemp[0]-1 > currentTemp[0]) {heatingActive[0] = true;} - if (targetTemp[0] <= currentTemp[0]) {heatingActive[0] = false;} - //passenger's side - if (targetTemp[1]-1 > currentTemp[1]) {heatingActive[1] = true;} - if (targetTemp[1] <= currentTemp[1]) {heatingActive[1] = false;} - } + //driver's side + if (targetTemp[0]+1 < currentTemp[0]) {coolingActive[0] = true;} //provides 1 deg buffer to prevent excessive activation/deactivation + if (targetTemp[0] >= currentTemp[0]) {coolingActive[0] = false;} + //passenger's side + if (targetTemp[1]+1 < currentTemp[1]) {coolingActive[1] = true;} + if (targetTemp[1] >= currentTemp[1]) {coolingActive[1] = false;} + //driver's side + if (targetTemp[0]-1 > currentTemp[0]) {heatingActive[0] = true;} + if (targetTemp[0] <= currentTemp[0]) {heatingActive[0] = false;} + //passenger's side + if (targetTemp[1]-1 > currentTemp[1]) {heatingActive[1] = true;} + if (targetTemp[1] <= currentTemp[1]) {heatingActive[1] = false;} + } + + private void adjustClimate(int zone) { + if (coolingActive[zone]) { + currentTemp[zone] = currentTemp[zone] - 1; + } + if (heatingActive[zone]) { + currentTemp[zone] = currentTemp[zone] + 1; + } } public void setFanSpeeds(String driver, String passenger) { //maps a string passed in to the appropriate enum value switch (driver) { - case "OFF": + case "OFF": case "1": fanSpeed[0] = fanLevels.OFF; break; - case "LOW": + case "LOW": case "2": fanSpeed[0] = fanLevels.LOW; break; - case "MED": + case "MED": case "3": fanSpeed[0] = fanLevels.MED; break; - case "HI": + case "HI": case "4": fanSpeed[0] = fanLevels.HI; break; } switch (passenger) { - case "OFF": + case "OFF": case "1": fanSpeed[1] = fanLevels.OFF; break; - case "LOW": - fanSpeed[2] = fanLevels.LOW; + case "LOW": case "2": + fanSpeed[1] = fanLevels.LOW; break; - case "MED": - fanSpeed[3] = fanLevels.MED; + case "MED": case "3": + fanSpeed[1] = fanLevels.MED; break; - case "HI": - fanSpeed[4] = fanLevels.HI; + case "HI": case "4": + fanSpeed[1] = fanLevels.HI; break; } } @@ -93,4 +121,9 @@ public class Climate { String[] workingString = {fanSpeed[0].toString(), fanSpeed[1].toString()}; return workingString; } + + private void displayInformation() { + System.out.print("Left | Current: " + currentTemp[0] + "; Set: " + targetTemp[0] + " || "); + System.out.print("Right| Current: " + currentTemp[1] + "; Set: " + targetTemp[1] + "\n"); + } } diff --git a/DrivingRoute.txt b/DrivingRoute.txt deleted file mode 100644 index 8eb57e3..0000000 --- a/DrivingRoute.txt +++ /dev/null @@ -1,12 +0,0 @@ -STRAIGHT;0.2;20;0.00 -LEFT;0.044;20;0.00 -LEFT;0.1;35;0.00 -LEFT;3.0;45;0.00 -RIGHT;2.3;50;0.00 -LEFT;0.3;50;0.00 -STRAIGHT;9.6;70;0.00 -STRAIGHT;0.3;50;0.00 -RIGHT;0.2;35;0.00 -LEFT;0.2;35;0.00 -LEFT;0.4;35;0.00 -RIGHT;0.08;20;0.00 diff --git a/DrivingRoute1.txt b/DrivingRoute1.txt new file mode 100644 index 0000000..55f9785 --- /dev/null +++ b/DrivingRoute1.txt @@ -0,0 +1,12 @@ +STRAIGHT;0.2;20;0.00;EFSC Melbourne Campus +LEFT;0.044;20;0.00;EFSC Melbourne Campus +LEFT;0.1;35;0.00;Post Rd. WEST +LEFT;3.0;45;0.00;Wickham Rd. SOUTH +RIGHT;2.3;50;0.00;Eau Gallie Blvd. WEST +LEFT;0.3;50;0.00;I-95 SOUTH Onramp +STRAIGHT;9.6;70;0.00;I-95 SOUTH +STRAIGHT;0.3;50;0.00;Malabar Rd. Exit Ramp +RIGHT;0.2;35;0.00;Malabar Rd. WEST +LEFT;0.2;35;0.00;San Filippo Dr. SOUTH +LEFT;0.4;35;0.00;Community College Pkwy. EAST +RIGHT;0.08;20;0.00;EFSC Palm Bay Campus diff --git a/DrivingRoute2.txt b/DrivingRoute2.txt new file mode 100644 index 0000000..1476228 --- /dev/null +++ b/DrivingRoute2.txt @@ -0,0 +1,7 @@ +STRAIGHT;0.2;20;0.00;EFSC Melbourne Campus +LEFT;0.044;20;0.00;EFSC Melbourne Campus +RIGHT;1.4;35;0.00;Post Rd. EAST +RIGHT;4.4;50;0.00;US-1 SOUTH +RIGHT;9.2;50;0.00;Babcock St. SOUTH +RIGHT;1.1;35;0.00;Community College Pkwy. WEST +LEFT;0.01;20;0.00;EFSC Palm Bay Campus \ No newline at end of file diff --git a/Entertainment.java b/Entertainment.java index 0f39cd3..a65d3eb 100644 --- a/Entertainment.java +++ b/Entertainment.java @@ -2,8 +2,13 @@ import java.lang.Class; public class Entertainment { public String activeMediaSource; - public String[] nowPlayingMetadata; + public String nowPlayingMetadata; public boolean playState; //true for playing, false for paused + + public Entertainment() { + activeMediaSource = ""; + nowPlayingMetadata = ""; + } public Entertainment(String[] sourceParams) { //loads previously played media source at instantiation, Vehicle class handles storing data selectSource(sourceParams[0], sourceParams[1]); @@ -13,10 +18,10 @@ public class Entertainment { //source is a string selection from RADIO, USB, AUX, BLUETOOTH //params are a delimited string with a URI and metadata activeMediaSource = source; - nowPlayingMetadata = params.split(";", 0); + nowPlayingMetadata = params; } - public String[] getMetadata() { + public String getMetadata() { return nowPlayingMetadata; } } diff --git a/HelperFunctions.java b/HelperFunctions.java index 40fef60..61cbef3 100644 --- a/HelperFunctions.java +++ b/HelperFunctions.java @@ -2,6 +2,7 @@ import java.util.Vector; import java.nio.file.Paths; import java.util.Scanner; import java.io.IOException; +import java.util.concurrent.*; //a collection of helper functions to act as responses for otherwise //external calls in this implementation for demo purposes @@ -26,13 +27,34 @@ public class HelperFunctions { public Vector routingAPI(double[] startCoords, String destinationAddress, Boolean tollsFlag, Boolean hwyFlag) { //method simulates a call to translate two pairs of coords into a driving route //for demo purposes returns a pregenerated set of move instructions - //located in DrivingRoute.txt as semicolon delimited strings for direction, distance, and speedLimit + //located in DrivingRoute.txt as semicolon delimited strings for direction, distance, and speedLimit Vector routeArray = new Vector(); if (tollsFlag && hwyFlag) { //provides a result that both avoid tolls and major highways + try (Scanner infile = new Scanner(Paths.get("DrivingRoute2.txt"))) { + while (infile.hasNext()) { + routeArray.addElement(infile.nextLine().split(";")); + } + } catch (IOException e) { + System.err.println("File handling error"); + } } else if (tollsFlag && !hwyFlag) { //provides a result that avoids tolls but not major highways + try (Scanner infile = new Scanner(Paths.get("DrivingRoute1.txt"))) { + while (infile.hasNext()) { + routeArray.addElement(infile.nextLine().split(";")); + } + } catch (IOException e) { + System.err.println("File handling error"); + } } else if (!tollsFlag && hwyFlag) { //provides a result that does not avoid tolls and does avoid major highways + try (Scanner infile = new Scanner(Paths.get("DrivingRoute2.txt"))) { + while (infile.hasNext()) { + routeArray.addElement(infile.nextLine().split(";")); + } + } catch (IOException e) { + System.err.println("File handling error"); + } } else if (!tollsFlag && !hwyFlag) { //provides a result that does not avoid tolls or major highways - try (Scanner infile = new Scanner(Paths.get("DrivingRoute.txt"))) { + try (Scanner infile = new Scanner(Paths.get("DrivingRoute1.txt"))) { while (infile.hasNext()) { routeArray.addElement(infile.nextLine().split(";")); } @@ -52,4 +74,16 @@ public class HelperFunctions { public int externalTempSensors() { return 88; } + + public static void sleep(int time) { //helper function to sleep 1 second + try {TimeUnit.SECONDS.sleep(time);} //sleep for 1-15 second to simulate traffic light + catch (InterruptedException e) {System.err.println("Sleep interrupted");} + } + + public static void pressEnterToContinue() { + System.out.println("Press Enter key to continue..."); + try { + System.in.read(); + } catch(Exception e) {} + } } diff --git a/RoadSensor.java b/RoadSensor.java index 63634d6..0fbe421 100644 --- a/RoadSensor.java +++ b/RoadSensor.java @@ -1,3 +1,5 @@ +import java.util.concurrent.TimeUnit; + public class RoadSensor { private boolean hazardDetected; //flag for whether a hazard is detected private String roadwayDetails; //stores road quality details, eg wet, uneven @@ -16,7 +18,7 @@ public class RoadSensor { return 45; } - public int identifyHazard() { + public static boolean identifyHazard() { //image processing algorithms from external cameras would //review data and identify a hazard //types of hazards could be @@ -25,17 +27,35 @@ public class RoadSensor { //lane closure //pedestrian on roadway //stationary object on roadway - //for testing, this function will return 0 to signal no hazard detected - //for testing purposes, this function will roll a 1/100 chance of detecting a hazard + //for testing purposes, this function will roll a 1/100 chance of detecting a hazard + //and a value of 1 means a hazard was detected double detection = Math.floor(Math.random()*100); - if (detection == 1) { return 1; } - else { return 0; } + if (detection == 1) { return true; } + else { return false; } } - public int detectTrafficLight() { //rolls a 1 in 5 that a traffic light will be detected when approaching an intersection + public static boolean detectTrafficLight() { //rolls a 1 in 5 that a traffic light will be detected when approaching an intersection double detection = Math.floor(Math.random()*5); - if (detection == 1) { return 1; } - else { return 0; } + if (detection == 1) { return true; } + else { return false; } + } + + public static int roadQuality(String type) { + //function to check road state + //for testing purposes, these checks are being separated + //so they can proc independently during a roadtrip + double rand = 0; + switch (type) { + case "WET": + rand = Math.floor(Math.random()*10); + if (rand == 1) {return 1;} + else {return 0;} + case "SURFACE": { + rand = Math.floor(Math.random()*20); + if (rand == 1) {return 1;} + else {return 0;} + } + } + return 1; } - } diff --git a/Route.java b/Route.java index ed5f7f4..fab4d33 100644 --- a/Route.java +++ b/Route.java @@ -8,20 +8,19 @@ public class Route { private boolean hwyFlag; //stores user preference for whether to avoid major highways public Vector timeEstimate; //time estimate in seconds public Vector tollsAmount; //stores toll amount if toll roads are used - private Destination currentDestination = new Destination(); + public Destination currentDestination = new Destination(); public Route() { this.routeSequences = new Vector>(); this.timeEstimate = new Vector(); this.tollsAmount = new Vector(); + this.routeSelected = -1; } public Route(String destination) { setRouteDestination(destination); this.timeEstimate = new Vector(); this.tollsAmount = new Vector(); - tollsFlag = false; - hwyFlag = false; } private void updateCurrentLocation() { @@ -39,21 +38,27 @@ public class Route { updateCurrentLocation(); HelperFunctions apiCallToRouting = new HelperFunctions(); //route option 1 + tollsFlag = false; + hwyFlag = false; routeSequences.add(apiCallToRouting.routingAPI(currentLocation, currentDestination.getDestinationAddress(), tollsFlag, hwyFlag)); timeEstimate.add(estimateTime(routeSequences.get(0))); tollsAmount.add(estimateTolls(routeSequences.get(0))); //route option 2 + tollsFlag = false; + hwyFlag = true; routeSequences.add(apiCallToRouting.routingAPI(currentLocation, currentDestination.getDestinationAddress(), tollsFlag, hwyFlag)); timeEstimate.add(estimateTime(routeSequences.get(1))); tollsAmount.add(estimateTolls(routeSequences.get(1))); - //route option 3 - routeSequences.add(apiCallToRouting.routingAPI(currentLocation, currentDestination.getDestinationAddress(), tollsFlag, hwyFlag)); - timeEstimate.add(estimateTime(routeSequences.get(2))); - tollsAmount.add(estimateTolls(routeSequences.get(2))); } - public int enumRoutes() { - return routeSequences.size(); + public String[] enumRoutes() { + //for testing, values are hardcoded. Would generate headings based on route characteristics ideally + String[] routeNames = {"1. via I-95 SOUTH\n\tNo Tolls\n\tUses Highways", "2. via US-1 and Babcock St.\n\tNo Tolls\n\tAvoids Highways"}; + return routeNames; + } + + public int countRoutesAvailable() { + return routeSequences.size(); } public void selectRoute(int userSelection) { diff --git a/SelfDrivingRoadtrip.java b/SelfDrivingRoadtrip.java index 5053863..9d0ace4 100644 --- a/SelfDrivingRoadtrip.java +++ b/SelfDrivingRoadtrip.java @@ -1,15 +1,252 @@ import java.util.Scanner; -import java.util.concurrent.*; public class SelfDrivingRoadtrip { public static void main(String[] args) { Vehicle myVehicle = new Vehicle(); + Entertainment nowPlaying = new Entertainment(); + Climate climate = new Climate(); Scanner userInput = new Scanner(System.in); - myVehicle.currentRoute.setRouteDestination("250 Community College Pkwy SE, Palm Bay, FL 32909"); - System.out.println("Number of available routes: " + myVehicle.currentRoute.enumRoutes()); - int tmp = userInput.nextInt(); - myVehicle.currentRoute.selectRoute(tmp); - myVehicle.navigateRoute(); + int userSelection = -1; + while (userSelection != 0) { + userSelection = -1; + + System.out.print("\033[H\033[2J"); + //Show current destination on main menu + System.out.print("Current Destination: "); + if (myVehicle.currentRoute.currentDestination.getDestinationAddress() != null) { + System.out.print(myVehicle.currentRoute.currentDestination.getDestinationAddress() + "\n"); + } else {System.out.print("None Selected\n");} + + //Show current route on main menu + System.out.print("Current Route: "); + if (myVehicle.currentRoute.getRouteSelected() == -1) { + System.out.print("None Selected\n"); + } else { + String[] routes = myVehicle.currentRoute.enumRoutes(); + String[] splitNames = routes[myVehicle.currentRoute.getRouteSelected()].split("\n"); + System.out.print(splitNames[0] + "\n"); + } + + //Show current fuel level on main menu + System.out.printf("Fuel Level: %.0f%%\n", myVehicle.getFuelLevel()*100); + + //Show current media source on Main Menu + System.out.print("Now Playing: " + nowPlaying.getMetadata() + "\n\n"); + + mainMenu(); + userSelection = userInput.nextInt(); + switch (userSelection) { + case 1: //destination selection menu + while (userSelection != 0) { + destinationMenu(); + userSelection = userInput.nextInt(); + if (userSelection == 0) { + userSelection = -1; + break; + } + else if (userSelection == 1) { + System.out.println("Destination 1 selected"); + myVehicle.currentRoute.setRouteDestination("250 Community College Pkwy SE, Palm Bay, FL 32909"); + userSelection = -1; + HelperFunctions.sleep(3); + break; + } else { + System.out.println("Please select a valid option."); + userSelection = -1; + HelperFunctions.sleep(3); + } + } + break; + case 2: //route selection menu + if (myVehicle.currentRoute.currentDestination.getDestinationAddress() == null) { + System.out.println("Please select a destination first."); + userSelection = -1; + break; + } + while (userSelection != 0) { + routesMenu(myVehicle.currentRoute.enumRoutes()); + userSelection = userInput.nextInt(); + if (userSelection == 0) { + userSelection = -1; + break; + } + else if (userSelection <= myVehicle.currentRoute.countRoutesAvailable()) { + myVehicle.currentRoute.selectRoute(userSelection - 1); + System.out.println("Route " + userSelection + " selected"); + userSelection = -1; + HelperFunctions.sleep(3); + break; + } else { + System.out.println("Please select a valid option."); + userSelection = -1; + HelperFunctions.sleep(3); + } + } + break; + case 3: //start navigation + System.out.println("Start navigation"); + myVehicle.run(); + System.out.println("Navigation complete, destination reached."); + HelperFunctions.pressEnterToContinue(); + break; + case 4: //entertainment controls + while (userSelection != 0) { + entertainmentMenu(); + userSelection = userInput.nextInt(); + + if (userSelection == 0) { + userSelection = -1; + break; + } else if (userSelection == 1) { + nowPlaying.selectSource("RADIO", "FM 104.1"); + userSelection = -1; + break; + } else if (userSelection == 2) { + nowPlaying.selectSource("AUX", "AUX Input"); + userSelection = -1; + break; + } else if (userSelection == 3) { + nowPlaying.selectSource("BLUETOOTH", "Bluetooth Device"); + userSelection = -1; + break; + } else { + System.out.println("Please select a valid option"); + userSelection = -1; + } + } + break; + case 5: //climate controls + while (userSelection != 0) { + climateMenu(); + userSelection = -1; + userSelection = userInput.nextInt(); + if (userSelection == 0) { + userSelection = -1; + break; + } else if (userSelection == 1) { + userSelection = -1; + climateTempMenu(climate.getCurrentTemps(), climate.getTargetTemps()); + userSelection = userInput.nextInt(); + if (userSelection == 0) { + userSelection = -1; + } else if (userSelection == 1) { + System.out.print("Enter new left target temp (65-90F): "); + climate.setTargetTemp(userInput.nextInt(), climate.getTargetTemps()[1]); + } else if (userSelection == 2) { + System.out.print("Enter new right target temp (65-90F): "); + climate.setTargetTemp(climate.getTargetTemps()[0], userInput.nextInt()); + } + } else if (userSelection == 2) { + userSelection = -1; + climateFanMenu(climate.getFanSpeeds()); + userSelection = userInput.nextInt(); + if (userSelection == 0) { + userSelection = -1; + } else if (userSelection == 1) { + userSelection = -1; + climateFanSpeedMenu(); + userSelection = userInput.nextInt(); + climate.setFanSpeeds(Integer.toString(userSelection), climate.getFanSpeeds()[1]); + } else if (userSelection == 2) { + userSelection = -1; + climateFanSpeedMenu(); + userSelection = userInput.nextInt(); + climate.setFanSpeeds(climate.getFanSpeeds()[0], Integer.toString(userSelection)); + } + } else if (userSelection == 3) { + userSelection = -1; + climate.run(); + } + } + } + } + + userInput.close(); + } + + public static void mainMenu() { + System.out.println("Main Menu\n=========\n"); + System.out.println("1. Set Destination"); + System.out.println("2. Select Route"); + System.out.println("3. Start Navigation"); + System.out.println("4. Entertainment Controls"); + System.out.println("5. Climate Controls"); + System.out.println("0. Turn Off"); + System.out.print("\nSelection: "); + } + + public static void destinationMenu() { + System.out.print("\033[H\033[2J"); + System.out.println("Destinations\n=============\n"); + System.out.println("Select a Destination\n"); + System.out.println("0. Go Back"); + System.out.println("1. EFSC Palm Bay Campus\n 250 Community College Pkwy SE, Palm Bay, FL 32909"); + System.out.print("\nSelection: "); + } + + public static void routesMenu(String[] routes) { + System.out.print("\033[H\033[2J"); + System.out.println("Routes Available\n================\n"); + System.out.println("Select a Route\n"); + System.out.println("0. Go Back"); + for (String el : routes) { + System.out.println(el); + } + System.out.print("\nSelection: "); + } + + public static void entertainmentMenu() { + System.out.print("\033[H\033[2J"); + System.out.println("Media\n=====\n"); + System.out.println("Select a Source\n"); + System.out.println("0. Go Back"); + System.out.println("1. Radio"); + System.out.println("2. AUX"); + System.out.println("3. Bluetooth"); + System.out.print("\nSelection: "); + } + + public static void climateMenu() { + System.out.print("\033[H\033[2J"); + System.out.println("Climate Controls\n===============\n"); + System.out.println("Select an option\n"); + System.out.println("0. Go Back"); + System.out.println("1. Set Temperature"); + System.out.println("2. Set Fan Speed"); + System.out.println("3. Run Climate Adjustments"); //only necessary while application is non-concurrent + System.out.print("\nSelection: "); + } + + public static void climateTempMenu(int[] currentTemps, int[] targetTemps) { + System.out.print("\033[H\033[2J"); + System.out.println("Temperature Controls\n===================\n"); + System.out.println("Select an option\n"); + System.out.println("0. Go Back"); + System.out.println("1. Set Left Temperature | Current: " + currentTemps[0] + "; Set: " + targetTemps[0]); + System.out.println("2. Set Right Temperature | Current: " + currentTemps[1] + "; Set: " + targetTemps[1]); + System.out.print("\nSelection: "); + } + + public static void climateFanMenu(String[] speeds) { + System.out.print("\033[H\033[2J"); + System.out.println("Fan Controls\n============\n"); + System.out.println("Select an option\n"); + System.out.println("0. Go Back"); + System.out.println("1. Set Left Fan Speed | Current: " + speeds[0]); + System.out.println("2. Set Right Fan Speed | Current: " + speeds[1]); + System.out.print("\nSelection: "); + } + + public static void climateFanSpeedMenu() { + System.out.print("\033[H\033[2J"); + System.out.println("Set Fan Speed\n=============\n"); + System.out.println("Select an option\n"); + System.out.println("0. Go Back"); + System.out.println("1. OFF"); + System.out.println("2. LOW"); + System.out.println("3. MED"); + System.out.println("4. HI"); + System.out.print("\nSelection: "); } } diff --git a/Vehicle.java b/Vehicle.java index f99d27c..f76cc85 100644 --- a/Vehicle.java +++ b/Vehicle.java @@ -1,10 +1,11 @@ -import java.util.concurrent.*; - public class Vehicle implements Runnable{ private Integer currentSpeed; private Integer targetSpeed; - private double fuelLevel; + private double fuelLevel; //percentage of full tank + private double fuelEconomy = 0.03125; //gallons consumed per mile of travel (32 MPG) + private double tripOdometer; //miles traveled in current trip private double distanceRemaining; + private String currentLocation; public Route currentRoute = new Route(); public void run() { @@ -12,42 +13,46 @@ public class Vehicle implements Runnable{ } public Vehicle() { - fuelLevel = getFuelLevel(); + fuelLevel = 1; //12 gallon tank as full currentSpeed = 0; - currentRoute.setRouteDestination("250 Community College Pkwy SE, Palm Bay, FL 32909"); + //currentRoute.setRouteDestination("250 Community College Pkwy SE, Palm Bay, FL 32909"); } public void setTargetSpeed(int newSpeed) {targetSpeed = newSpeed;} public int getCurrentSpeed() {return currentSpeed;} - public double getFuelLevel() {return fuelLevel;} + public double getFuelLevel() { + updateFuelLevel(); + return fuelLevel; + } public void updateFuelLevel() { //would check fuel sensor and update accordingly - fuelLevel = 0.75; + fuelLevel = (12 - (tripOdometer * fuelEconomy))/12; } public void navigateRoute() { - System.out.println("Start navigation"); - boolean turnCompleted = false; + int isRoadWet = RoadSensor.roadQuality("WET"); //check whether road is wet + boolean turnCompleted = false; //flag to validate completion of moveset instruction + + //at start of trip, check for whether road is wet + if (isRoadWet == 1) {System.out.println("Road is wet, trip will have reduced speed for safety.");} for (String[] el : currentRoute.getSelectedRouteSteps()) { - RoadSensor trafficSensor = new RoadSensor(); - if (targetSpeed > 20 && trafficSensor.detectTrafficLight() == 1 && el[0] != "STRAIGHT") { - //simulates stopping at traffic lights on major roadways - //for demo purposes, the spherical cow in a vacuum is that this only happens at turns - long sleepTime = Double.valueOf(Math.floor(Math.random()*15)).longValue(); - while (sleepTime > 0) { - System.out.println("Traffic light detected, waiting..."); - try {TimeUnit.SECONDS.sleep(1);} //sleep for 1-15 second to simulate traffic light - catch (InterruptedException e) {System.err.println("Sleep interrupted");} - } - System.out.println("Resuming navigation"); - } - - turnCompleted = false; //flag to validate completion of moveset instruction + turnCompleted = false; distanceRemaining = Double.parseDouble(el[1]); targetSpeed = Integer.parseInt(el[2]); - while (!turnCompleted) { - if (currentSpeed < 15 || el[0] == "STRAIGHT") { + currentLocation = el[4]; + int isRoadUneven = RoadSensor.roadQuality("SURFACE"); + + //checks for presence of traffic light before completing next moveset to simulate cross-traffic + if (targetSpeed > 20 && RoadSensor.detectTrafficLight() && el[0] != "STRAIGHT") { + vehicleHalt("Traffic light"); + } + + //checks whether road surface is degraded on current road to drive more cautiously + if (isRoadUneven == 1) {System.out.println("Road surface is uneven, speed will be reduced.");} + + while (!turnCompleted) { //move action routines to transition between movesets + if (currentSpeed <= 15 || el[0] == "STRAIGHT") { changeDirection(el[0]); turnCompleted = true; } else { @@ -55,40 +60,46 @@ public class Vehicle implements Runnable{ } } - while (distanceRemaining > 0) { - System.out.printf("%.2f miles to next instruction\n", distanceRemaining); - System.out.println("Current Speed: " + currentSpeed + " MPH"); - controlThrottle(); - distanceRemaining = distanceRemaining - (Double.valueOf(currentSpeed)/3600); //travel distance in one second - try {TimeUnit.SECONDS.sleep(1);} //sleep action for 1 second to simulate continuous movement - catch (InterruptedException e) {System.err.println("Sleep interrupted");} + while (distanceRemaining > 0) { //forward motion routines to drive current road segment + if (RoadSensor.identifyHazard()) { + vehicleHalt("Hazard"); + } else { + displayInformation(); //displays current route and state information to console + controlThrottle(isRoadWet + isRoadUneven); + tripOdometer += Double.valueOf(currentSpeed)/3600; + distanceRemaining = distanceRemaining - (Double.valueOf(currentSpeed)/3600); //travel distance in one second + HelperFunctions.sleep(1); //sleep 1 second to simulate continuous movement + } } } - System.out.println("Navigation complete, destination reached."); } public void changeDirection(String direction) { switch (direction) { case "LEFT": - System.out.println("Turning left..."); + System.out.println("Turning left...\n"); break; case "RIGHT": - System.out.println("Turning right..."); + System.out.println("Turning right...\n"); break; case "STRAIGHT": - System.out.println("Continuing straight..."); + System.out.println("Continuing straight...\n"); break; } } - public void controlThrottle() { - if (currentSpeed < targetSpeed && (targetSpeed - currentSpeed) > 6) { //normal acceleration + public void controlThrottle(int unsafeCondition) { + int safeTargetSpeed = targetSpeed; + //adjust driving speed for road conditions. 5 MPH reduction per unsafe condition detected + if (targetSpeed > 20) {safeTargetSpeed = targetSpeed - (5 * unsafeCondition);} + + if (currentSpeed < safeTargetSpeed && (safeTargetSpeed - currentSpeed) > 6) { //normal acceleration currentSpeed = currentSpeed + 6; - } else if (currentSpeed < targetSpeed && (targetSpeed - currentSpeed) <= 6) { //partial acceleration to reach speed limit - currentSpeed = currentSpeed + (targetSpeed - currentSpeed); - } else if (currentSpeed > targetSpeed) { //deceleration by coasting + } else if (currentSpeed < safeTargetSpeed && (safeTargetSpeed - currentSpeed) <= 6) { //partial acceleration to reach speed limit + currentSpeed = currentSpeed + (safeTargetSpeed - currentSpeed); + } else if (currentSpeed > safeTargetSpeed) { //deceleration by coasting currentSpeed--; - } else if (currentSpeed == targetSpeed) { + } else if (currentSpeed == safeTargetSpeed) { //do nothing } } @@ -98,4 +109,24 @@ public class Vehicle implements Runnable{ if (currentSpeed >= 10) {currentSpeed -= 10;} else if (currentSpeed < 10) {currentSpeed = 0;} } + + public void vehicleHalt(String type) { //helper function to simulate a environmentally-driven vehicle stop + long sleepTime = Double.valueOf(Math.floor((Math.random()*10)+5)).longValue(); //wait time, between 5 and 15 seconds + while (sleepTime > 0) { + System.out.println(type + " detected, stopping (" + sleepTime + ")..."); + while (currentSpeed > 0) {applyBrakes();} + HelperFunctions.sleep(1); //sleep 1 second to simulate time for obstruction to clear + sleepTime--; + } + System.out.println(type + " cleared, resuming navigation\n"); + } + + public void displayInformation() { + //System.out.print("\033[H\033[2J"); + System.out.printf("%.2f miles to next instruction\n", distanceRemaining); + System.out.println("Current Location: " + currentLocation); + System.out.println("Current Speed: " + currentSpeed + " MPH\n"); + } + + }