diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java index f8177612..a588a754 100644 --- a/racevisionGame/src/main/java/mock/app/Event.java +++ b/racevisionGame/src/main/java/mock/app/Event.java @@ -63,6 +63,8 @@ public class Event { private Thread connectionThread; + private int mapIndex; + @@ -76,8 +78,10 @@ public class Event { // System.out.println(XMLUtilities.validateXML(this.getClass().getClassLoader().getResource("mock/mockXML/iMapLayout.xml").toString() // , this.getClass().getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd"))); - + this.mapIndex = mapIndex; String raceXMLFile; + String boatsXMLFile = "mock/mockXML/boatTest.xml"; + String regattaXMLFile = "mock/mockXML/regattaTest.xml"; switch (mapIndex){ case 0:raceXMLFile = "mock/mockXML/raceSixPlayers.xml"; break; @@ -87,11 +91,15 @@ public class Event { break; case 3: raceXMLFile = "mock/mockXML/mMapLayout.xml"; break; + case 4: + raceXMLFile = "mock/mockXML/raceTutorial.xml"; + boatsXMLFile = "mock/mockXML/boatTutorial.xml"; + regattaXMLFile = "mock/mockXML/regattaTutorial.xml"; + break; default: raceXMLFile = "mock/mockXML/raceSixPlayers.xml"; } - String boatsXMLFile = "mock/mockXML/boatTest.xml"; - String regattaXMLFile = "mock/mockXML/regattaTest.xml"; + if (singlePlayer) { raceXMLFile = "mock/mockXML/raceSinglePlayer.xml"; @@ -103,7 +111,9 @@ public class Event { //this.raceXML = RaceXMLCreator.alterRaceToWind(raceXMLFile, 90); this.raceXML = XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8); this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8)); - + if(mapIndex==4){ + this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8), 1000, 5000); + } this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8); this.regattaXML = XMLReader.readXMLFileToString(regattaXMLFile, StandardCharsets.UTF_8); @@ -186,9 +196,15 @@ public class Event { * @return String containing edited xml */ public static String setRaceXMLAtCurrentTimeToNow(String raceXML) { + return setRaceXMLAtCurrentTimeToNow(raceXML, Constants.RacePreStartTime, Constants.RacePreparatoryTime); + } + public static String setRaceXMLAtCurrentTimeToNow(String raceXML, long racePreStartTime, long racePreparatoryTime){ //The start time is current time + 4 minutes. prestart is 3 minutes, and we add another minute. - long millisecondsToAdd = Constants.RacePreStartTime + Constants.RacePreparatoryTime; + + long millisecondsToAdd = racePreStartTime + racePreparatoryTime; + + long secondsToAdd = millisecondsToAdd / 1000; //Scale the time using our time scalar. secondsToAdd = secondsToAdd / Constants.RaceTimeScale; @@ -198,7 +214,6 @@ public class Event { raceXML = raceXML.replace("RACE_CREATION_TIME", dateFormat.format(creationTime)); raceXML = raceXML.replace("RACE_START_TIME", dateFormat.format(creationTime.plusSeconds(secondsToAdd))); - return raceXML; } diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index 6c098ebe..5804b8ae 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -62,7 +62,7 @@ public class RaceXMLCreator { * @throws SAXException error in schema file * @throws ParserConfigurationException error in parsing the schema file */ - public static String alterRaceToWind(String s, double degrees) throws XMLReaderException, InvalidRaceDataException, JAXBException, IOException, SAXException, ParserConfigurationException { + public static String alterRaceToWind(String s, double degrees, boolean tutorial) throws XMLReaderException, InvalidRaceDataException, JAXBException, IOException, SAXException, ParserConfigurationException { RaceXMLReader reader = new RaceXMLReader(s, XMLFileType.ResourcePath); XMLRace race = XMLUtilities.xmlToClass( @@ -70,7 +70,11 @@ public class RaceXMLCreator { RaceXMLCreator.class.getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd"), XMLRace.class); - setRaceXMLAtCurrentTimeToNow(race); + if(tutorial){ + setRaceXMLAtCurrentTimeToNow(race, 1000l, 5000l); + } else { + setRaceXMLAtCurrentTimeToNow(race); + } double raceOriginalBearing = getLineAngle(getLeewardGate(reader).getMark1Position(), getWindwardGate(reader).getMark1Position()); @@ -81,6 +85,7 @@ public class RaceXMLCreator { return XMLUtilities.classToXML(race); } + /** * Rotate the features in a race such as the boundary, and the marks. * @param race the race to alter @@ -168,14 +173,11 @@ public class RaceXMLCreator { } - /** - * Sets the xml description of the race to show the race was created now, and starts in 4 minutes - * @param raceXML The race.xml contents. - */ - public static void setRaceXMLAtCurrentTimeToNow(XMLRace raceXML) { + + public static void setRaceXMLAtCurrentTimeToNow(XMLRace raceXML, long racePrestartTime, long racePreparatoryTime){ //The start time is current time + 4 minutes. prestart is 3 minutes, and we add another minute. - long millisecondsToAdd = Constants.RacePreStartTime + Constants.RacePreparatoryTime; + long millisecondsToAdd = racePrestartTime + racePreparatoryTime; long secondsToAdd = millisecondsToAdd / 1000; //Scale the time using our time scalar. secondsToAdd = secondsToAdd / Constants.RaceTimeScale; @@ -186,4 +188,13 @@ public class RaceXMLCreator { raceXML.getRaceStartTime().setTime(dateFormat.format(creationTime.plusSeconds(secondsToAdd))); } + /** + * Sets the xml description of the race to show the race was created now, and starts in 4 minutes + * @param raceXML The race.xml contents. + */ + public static void setRaceXMLAtCurrentTimeToNow(XMLRace raceXML) { + setRaceXMLAtCurrentTimeToNow(raceXML, Constants.RacePreStartTime, Constants.RacePreparatoryTime); + + } + } diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java index 48b02f41..b0403cac 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java @@ -12,6 +12,7 @@ import javafx.scene.chart.LineChart; import javafx.scene.control.*; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; +import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import javafx.scene.layout.StackPane; import javafx.scene.shape.MeshView; @@ -23,9 +24,9 @@ import shared.dataInput.RaceDataSource; import shared.model.Leg; import shared.model.Mark; import visualiser.app.App; +import visualiser.enums.TutorialState; import visualiser.gameController.ControllerClient; import visualiser.gameController.Keys.ControlKey; -import visualiser.gameController.Keys.KeyFactory; import visualiser.layout.Subject3D; import visualiser.layout.View3D; import visualiser.model.Sparkline; @@ -35,6 +36,7 @@ import visualiser.model.VisualiserRaceState; import visualiser.utils.GPSConverter; import java.io.IOException; import java.net.URL; +import java.util.*; import java.util.Optional; import java.util.logging.Level; import java.util.logging.Logger; @@ -49,6 +51,10 @@ public class RaceViewController extends Controller { private KeyFactory keyFactory = new KeyFactory(); private boolean infoTableShow = true; // shown or hidden private boolean isHost; + private TutorialState currentState; + private ArrayList tutorialStates; + private boolean isTutorial = false; + private String keyToPress; private View3D view3D; private ObservableList viewSubjects; @@ -68,6 +74,9 @@ public class RaceViewController extends Controller { private @FXML TableColumn boatSpeedColumn; private @FXML LineChart sparklineChart; + private @FXML Label tutorialText; + + /** * Displays a specified race. * Intended to be called on loading the scene. @@ -101,11 +110,24 @@ public class RaceViewController extends Controller { if(controlKey != null) { try { controlKey.onAction(); // Change key state if applicable + + //Check if current race is a tutorial + if (isTutorial){ + //Check if current tutorial state has the same boat protocol code as key press + if (controlKey.getProtocolCode().equals(currentState.getAction())){ + //Update tutorial + checkTutorialState(); + } + } + controllerClient.sendKey(controlKey); event.consume(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); Logger.getGlobal().log(Level.WARNING, "RaceViewController was interrupted on thread: " + Thread.currentThread() + "while sending: " + controlKey, e); + Logger.getGlobal().log(Level.WARNING, "RaceController was interrupted on thread: " + Thread.currentThread() + "while sending: " + controlKey, e); + } catch (Exception e) { + e.printStackTrace(); } } @@ -145,6 +167,7 @@ public class RaceViewController extends Controller { initialiseFps(); initialiseInfoTable(); initialiseView3D(); + initialiseArrow(); initialiseRaceClock(); raceTimer(); // start the timer new Sparkline(this.raceState, this.sparklineChart); @@ -212,9 +235,33 @@ public class RaceViewController extends Controller { if (key != null) { switch (key.toString()) { case "Zoom In": + //Check if race is a tutorial + if (isTutorial) { + //Check if the current tutorial state is zoom-in + if (currentState.equals(TutorialState.ZOOMIN)) { + try { + //Update tutorial + checkTutorialState(); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + } view3D.updateDistance(-10); break; case "Zoom Out": + //Check if race is a tutorial + if(isTutorial) { + //Check if current tutorial state is zoom-out + if (currentState.equals(TutorialState.ZOOMOUT)) { + try { + //Update tutorial + checkTutorialState(); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + } view3D.updateDistance(10); break; } @@ -222,6 +269,9 @@ public class RaceViewController extends Controller { }); } + + + /** * Initialises the frame rate functionality. This allows for toggling the * frame rate, and connect the fps label to the race's fps property. @@ -324,6 +374,45 @@ public class RaceViewController extends Controller { }); } + + + /** + * Displays a specified race. + * @param visualiserRace Object modelling the race. + * @param controllerClient Socket Client that manipulates the controller. + * @param isHost is user a host + */ + public void startRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) { + + this.visualiserRace = visualiserRace; + this.controllerClient = controllerClient; + this.isHost = isHost; + + + //Check if the game is a tutorial + if (parent.getGameType()==4){ + isTutorial = true; + tutorialText.setVisible(true); + tutorialStates = new ArrayList<>(Arrays.asList(TutorialState.values())); + + currentState = tutorialStates.get(0); + tutorialStates.remove(0); + + searchMapForKey("Upwind"); + + tutorialText.setText("Welcome to the tutorial! Exit at anytime with ESC. \nWe will first learn how to turn upwind. Press " + keyToPress + " to turn upwind."); + + } else { + isTutorial = false; + tutorialText.setVisible(false); + } + + initialiseRace(); + + //Display this controller. + racePane.setVisible(true); + } + /** * Transition from the race view to the finish view. */ @@ -333,6 +422,16 @@ public class RaceViewController extends Controller { fc.loadFinish(raceState.getBoats()); } + + /** + * Initialises the arrow controller with data from the race to observe. + * @param race The race to observe. + */ + private void initialiseArrow(VisualiserRaceEvent race) { + arrowController.setWindProperty(race.getVisualiserRaceState().windProperty()); + } + + /** * Timer which monitors the race. */ @@ -393,4 +492,108 @@ public class RaceViewController extends Controller { infoTableShow = !infoTableShow; } + /** + * Get the next tutorial state + */ + private void updateTutorialState(){ + //Next tutorial state is popped from list + currentState = tutorialStates.get(0); + tutorialStates.remove(0); + } + + /** + * Search key map for key given string of command + * @param command the command of the key + */ + private void searchMapForKey(String command){ + //For loop through keyFactory + for (Map.Entry entry: keyFactory.getKeyState().entrySet()){ + if(entry.getValue().toString().equals(command)){ + + //Found next key required to press + keyToPress = entry.getKey(); + } + } + } + + /** + * Updates tutorial state and gui display for tutorial text + * @throws Exception Exception thrown + */ + private void checkTutorialState() throws Exception { + //Switch statement to check what the current tutorial state is + switch (currentState){ + case UPWIND: + //Set next key to press as the downwind key + searchMapForKey("Downwind"); + //Update tutorial text + tutorialText.setText("Nice! To turn downwind press " + keyToPress + "."); + updateTutorialState(); + break; + case DOWNWIND: + //Set next key to press as the tack/gybe key + searchMapForKey("Tack/Gybe"); + //Update tutorial text + tutorialText.setText("Nice! To tack or gybe press " + keyToPress + "."); + updateTutorialState(); + break; + case TACKGYBE: + //Set next key to press as the VMG key + searchMapForKey("VMG"); + //Update tutorial text + tutorialText.setText("Nice! To use VMG press " + keyToPress + ". This will turn the boat."); + updateTutorialState(); + break; + case VMG: + //Set next key to press as the sails-in key + searchMapForKey("Toggle Sails"); + //Update tutorial text + tutorialText.setText("Nice! To sails in press " + keyToPress + ". This will stop the boat."); + updateTutorialState(); + break; + case SAILSIN: + //Set next key to press as the sails-out key + searchMapForKey("Toggle Sails"); + //Update tutorial text + tutorialText.setText("Nice! To sails out press " + keyToPress + " again. The will start moving again."); + updateTutorialState(); + break; + case SAILSOUT: + //Set next key to press as the zoom-in key + searchMapForKey("Zoom In"); + //Update tutorial text + tutorialText.setText("Nice! To zoom in press " + keyToPress + "."); + updateTutorialState(); + break; + case ZOOMIN: + //Set next key to press as the zoom-out key + searchMapForKey("Zoom Out"); + //Update tutorial text + tutorialText.setText("Nice! You will also be able to zoom into boats and marks by clicking them. To zoom out press " + keyToPress + "."); + updateTutorialState(); + break; + case ZOOMOUT: + //Finished tutorial. Display pop-up for exiting the tutorial + tutorialText.setText("Congratulations! You're done!"); + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Finished Tutorial"); + alert.setHeaderText("You have finished the tutorial."); + alert.setContentText("Now you know the controls you are ready to race!"); + Optional result = alert.showAndWait(); + if (result.get() == ButtonType.OK) { + parent.endEvent(); + racePane.setVisible(false); + App.app.showMainStage(App.getStage()); + } + break; + default: + //State not found. Exit tutorial to title menu + parent.endEvent(); + racePane.setVisible(false); + App.app.showMainStage(App.getStage()); + break; + } + + } + } \ No newline at end of file diff --git a/racevisionGame/src/main/java/visualiser/Controllers/TitleController.java b/racevisionGame/src/main/java/visualiser/Controllers/TitleController.java index 20d5bb9a..721833f4 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/TitleController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/TitleController.java @@ -1,11 +1,28 @@ package visualiser.Controllers; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Parent; +import javafx.scene.Scene; +import javafx.scene.control.Button; +import javafx.scene.control.Label; import javafx.scene.control.RadioButton; +import javafx.scene.image.Image; +import javafx.scene.image.ImageView; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.Pane; import javafx.stage.Modality; +import javafx.stage.Stage; +import mock.app.Event; +import mock.exceptions.EventConstructionException; +import javafx.stage.WindowEvent; import visualiser.app.App; import java.io.IOException; +import java.net.URL; +import java.util.ResourceBundle; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Controller for the opening title window. @@ -16,6 +33,9 @@ import java.io.IOException; public class TitleController extends Controller { private @FXML RadioButton dayModeRD; private @FXML RadioButton nightModeRD; + private @FXML Label tutorialLabel; + private @FXML Pane menuPane; + private @FXML ImageView imgSun; /** * Method called when the 'host a game' button is pressed. @@ -40,7 +60,10 @@ public class TitleController extends Controller { */ public void setDayMode(){ dayModeRD.getScene().getStylesheets().clear(); + menuPane.getStylesheets().clear(); + imgSun.setImage(new Image(getClass().getResource("/visualiser/images/sun.png").toExternalForm())); dayModeRD.getScene().getStylesheets().add("/css/dayMode.css"); + menuPane.setStyle("-fx-background-color: #6be6ff;"); nightModeRD.setSelected(false); App.dayMode = true; } @@ -50,7 +73,10 @@ public class TitleController extends Controller { */ public void setNightMode(){ nightModeRD.getScene().getStylesheets().clear(); + menuPane.getStylesheets().clear(); + imgSun.setImage(new Image(getClass().getResource("/visualiser/images/sunsleep.png").toExternalForm())); nightModeRD.getScene().getStylesheets().add("/css/nightMode.css"); + menuPane.setStyle("-fx-background-color: #1f2c60;"); dayModeRD.setSelected(false); App.dayMode = false; } @@ -67,4 +93,12 @@ public class TitleController extends Controller { } } + + public void tutorialStartPressed() throws IOException { + titleWrapper.setVisible(false); + parent.setGameType(4); + parent.beginGame(); + + } + } \ No newline at end of file diff --git a/racevisionGame/src/main/java/visualiser/app/App.java b/racevisionGame/src/main/java/visualiser/app/App.java index ccb25d07..316387c9 100644 --- a/racevisionGame/src/main/java/visualiser/app/App.java +++ b/racevisionGame/src/main/java/visualiser/app/App.java @@ -3,6 +3,7 @@ package visualiser.app; import javafx.animation.FadeTransition; import javafx.application.Application; import javafx.application.Platform; +import javafx.beans.property.ReadOnlyObjectProperty; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.concurrent.Task; @@ -13,6 +14,7 @@ import javafx.geometry.Rectangle2D; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.scene.control.Label; +import javafx.scene.control.ListView; import javafx.scene.control.ProgressBar; import javafx.scene.effect.DropShadow; import javafx.scene.image.Image; @@ -87,7 +89,7 @@ public class App extends Application { ); updateMessage("Preparing ingredients . . ."); - Thread.sleep(200); + Thread.sleep(100); for (int i = 0; i < burgerFilling.size(); i++) { Thread.sleep(100); updateProgress(i + 1, burgerFilling.size()); diff --git a/racevisionGame/src/main/java/visualiser/enums/TutorialState.java b/racevisionGame/src/main/java/visualiser/enums/TutorialState.java new file mode 100644 index 00000000..ab811a43 --- /dev/null +++ b/racevisionGame/src/main/java/visualiser/enums/TutorialState.java @@ -0,0 +1,66 @@ +package visualiser.enums; + +import javafx.scene.input.KeyCode; +import network.Messages.BoatAction; +import network.Messages.Enums.BoatActionEnum; +import visualiser.gameController.Keys.ControlKey; +import static visualiser.app.App.keyFactory; + +import java.util.ArrayList; + +/** + * State of which stage the tutorial is currently in + */ +public enum TutorialState { + + /** + * State for upwind in tutorial + */ + UPWIND(BoatActionEnum.UPWIND), + + /** + * State for downwind in tutorial + */ + DOWNWIND(BoatActionEnum.DOWNWIND), + + /** + * State for tacking/gybing in tutorial + */ + TACKGYBE(BoatActionEnum.TACK_GYBE), + + /** + * State for vmg in tutorial + */ + VMG(BoatActionEnum.AUTO_PILOT), + + /** + * State for sails-in in tutorial + */ + SAILSIN(BoatActionEnum.SAILS_IN), + + /** + * State for sails-out in tutorial + */ + SAILSOUT(BoatActionEnum.SAILS_OUT), + + /** + * State for zoom-in in tutorial + */ + ZOOMIN(null), + + /** + * State for zoom-out in tutorial + */ + ZOOMOUT(null); + + private BoatActionEnum action; + + TutorialState(BoatActionEnum action){ + this.action = action; + } + + public BoatActionEnum getAction(){ + return action; + } + +} diff --git a/racevisionGame/src/main/resources/mock/mockXML/boatTutorial.xml b/racevisionGame/src/main/resources/mock/mockXML/boatTutorial.xml new file mode 100644 index 00000000..023c5090 --- /dev/null +++ b/racevisionGame/src/main/resources/mock/mockXML/boatTutorial.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/racevisionGame/src/main/resources/mock/mockXML/raceSinglePlayer.xml b/racevisionGame/src/main/resources/mock/mockXML/raceSinglePlayer.xml index e9e9378a..c4efcd17 100644 --- a/racevisionGame/src/main/resources/mock/mockXML/raceSinglePlayer.xml +++ b/racevisionGame/src/main/resources/mock/mockXML/raceSinglePlayer.xml @@ -5,7 +5,6 @@ RACE_CREATION_TIME - diff --git a/racevisionGame/src/main/resources/mock/mockXML/raceTutorial.xml b/racevisionGame/src/main/resources/mock/mockXML/raceTutorial.xml new file mode 100644 index 00000000..47519d00 --- /dev/null +++ b/racevisionGame/src/main/resources/mock/mockXML/raceTutorial.xml @@ -0,0 +1,43 @@ + + + 9999 + FLEET + RACE_CREATION_TIME + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/racevisionGame/src/main/resources/mock/mockXML/regattaTutorial.xml b/racevisionGame/src/main/resources/mock/mockXML/regattaTutorial.xml new file mode 100644 index 00000000..d7f6b9e7 --- /dev/null +++ b/racevisionGame/src/main/resources/mock/mockXML/regattaTutorial.xml @@ -0,0 +1,10 @@ + + 0 + Race Tutorial + Tutorial + -36.82791529 + 174.81218919 + 0.00 + 12 + 14.1 + \ No newline at end of file diff --git a/racevisionGame/src/main/resources/visualiser/images/sunsleep.png b/racevisionGame/src/main/resources/visualiser/images/sunsleep.png new file mode 100644 index 00000000..e52b2674 Binary files /dev/null and b/racevisionGame/src/main/resources/visualiser/images/sunsleep.png differ diff --git a/racevisionGame/src/main/resources/visualiser/mock/mockXML/raceXML/raceTutorial.xml b/racevisionGame/src/main/resources/visualiser/mock/mockXML/raceXML/raceTutorial.xml new file mode 100644 index 00000000..db7a6978 --- /dev/null +++ b/racevisionGame/src/main/resources/visualiser/mock/mockXML/raceXML/raceTutorial.xml @@ -0,0 +1,91 @@ + + + + + 99999999 + + Match + + 2011-08-06T13:25:00-0000 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/racevisionGame/src/main/resources/visualiser/scenes/raceView.fxml b/racevisionGame/src/main/resources/visualiser/scenes/raceView.fxml index 8733a73e..c4180e76 100644 --- a/racevisionGame/src/main/resources/visualiser/scenes/raceView.fxml +++ b/racevisionGame/src/main/resources/visualiser/scenes/raceView.fxml @@ -1,5 +1,11 @@ + + + + + + @@ -28,81 +34,89 @@ AnchorPane.topAnchor="0.0" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="visualiser.Controllers.RaceViewController"> - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/racevisionGame/src/test/java/shared/dataInput/BoatsXMLTest.java b/racevisionGame/src/test/java/shared/dataInput/BoatsXMLTest.java deleted file mode 100644 index 35e21a0e..00000000 --- a/racevisionGame/src/test/java/shared/dataInput/BoatsXMLTest.java +++ /dev/null @@ -1,47 +0,0 @@ -//package seng302.Mock; -// -//import org.junit.Before; -//import org.junit.Test; -// -//import java.util.HashMap; -//import java.util.Map; -// -//import static org.junit.Assert.assertEquals; -// -///** -// * Created by jjg64 on 21/04/17. -// */ -//public class BoatsXMLTest { -// private BoatXMLReader boatXMLReader; -// -// @Before -// public void setup() { -// try { -// boatXMLReader = new BoatXMLReader("mockXML/boatXML/boatTest.xml", false); -// } catch (Exception e) { -// e.printStackTrace(); -// //fail("Cannot find mockXML/raceXML/raceTest.xml in the resources folder"); -// } -// } -// -// @Test -// public void testInvalidParticipant() { -// Map inputParticipants = new HashMap<>(); -// inputParticipants.put(420, new StreamedBoat(420)); -// boatXMLReader.setParticipants(inputParticipants); -// boatXMLReader.read(); -// assertEquals(boatXMLReader.getBoats().size(), 0); -// } -// -// @Test -// public void testValidParticipant() { -// Map inputParticipants = new HashMap<>(); -// inputParticipants.put(101, new StreamedBoat(101)); -// boatXMLReader.setParticipants(inputParticipants); -// boatXMLReader.read(); -// assertEquals(boatXMLReader.getBoats().size(), 1); -// StreamedBoat boat = (StreamedBoat) boatXMLReader.getBoats().get(0); -// assertEquals(boat.getSourceID(), 101); -// } -// -//} diff --git a/racevisionGame/src/test/java/shared/dataInput/FailBoatXMLTest.java b/racevisionGame/src/test/java/shared/dataInput/FailBoatXMLTest.java deleted file mode 100644 index a299c2bf..00000000 --- a/racevisionGame/src/test/java/shared/dataInput/FailBoatXMLTest.java +++ /dev/null @@ -1,26 +0,0 @@ -//package seng302.Mock; -// -//import org.junit.Test; -//import org.xml.sax.SAXException; -// -//import javax.xml.parsers.ParserConfigurationException; -//import java.io.IOException; -//import java.text.ParseException; -// -///** -// * Created by jjg64 on 1/05/17. -// */ -//public class FailBoatXMLTest { -// private final String path = "mockXML/boatXML/"; -// -// @Test(expected = NumberFormatException.class) -// public void invalidSourceID() throws SAXException, ParserConfigurationException, ParseException, IOException { -// new BoatXMLReader(path + "invalidSourceID.xml"); -// } -// -// @Test(expected = NullPointerException.class) -// public void insufficientInformation() throws SAXException, ParserConfigurationException, ParseException, IOException { -// new BoatXMLReader(path + "insufficientInformation.xml"); -// } -// -//} diff --git a/racevisionGame/src/test/java/shared/model/RaceTest.java b/racevisionGame/src/test/java/shared/model/RaceTest.java deleted file mode 100644 index 3334aefd..00000000 --- a/racevisionGame/src/test/java/shared/model/RaceTest.java +++ /dev/null @@ -1,345 +0,0 @@ -//package shared.model; -// -// -//import mock.model.Polars; -//import org.junit.Before; -//import org.junit.Ignore; -//import org.junit.Test; -//import org.mockito.Mockito; -//import org.xml.sax.SAXException; -// -//import javax.xml.parsers.ParserConfigurationException; -//import java.io.IOException; -//import java.text.ParseException; -//import java.util.ArrayList; -// -//import static org.junit.Assert.*; -//import static org.mockito.Mockito.*; -// -///** -// * Created by esa46 on 15/03/17. -// */ -//public class RaceTest{ -// -// -// private CompoundMark ORIGIN; -// -// private CompoundMark THREE_NM_FROM_ORIGIN; -// -// private CompoundMark FIFTEEN_NM_FROM_ORIGIN; -// -// private ArrayList TEST_LEGS = new ArrayList<>(); -// -// private int START_LEG_DISTANCE = 3; -// private int MIDDLE_LEG_DISTANCE = 12; -// -// private Leg START_LEG; -// -// private Leg MIDDLE_LEG; -// -// private Leg FINISH_LEG; -// -// -// @Before -// public void setUp() { -// -// ORIGIN = new CompoundMark( -// 1, -// "origin compound", -// new Mark(1, "test origin 1", new GPSCoordinate(0, 0)) ); -// -// -// THREE_NM_FROM_ORIGIN = new CompoundMark( -// 2, -// "3 NM from origin compound", -// new Mark(2, "test mark 2", new GPSCoordinate(0.050246769, 0)) ); -// -// -// FIFTEEN_NM_FROM_ORIGIN = new CompoundMark( -// 3, -// "15 NM from origin compound", -// new Mark(3, "test mark 3", new GPSCoordinate(0.251233845, 0)) ); -// -// -// START_LEG = new Leg("Start", ORIGIN, THREE_NM_FROM_ORIGIN, 0); -// -// -// MIDDLE_LEG = new Leg("Middle", THREE_NM_FROM_ORIGIN, FIFTEEN_NM_FROM_ORIGIN, 1); -// -// -// FINISH_LEG = new Leg("Finish", FIFTEEN_NM_FROM_ORIGIN, FIFTEEN_NM_FROM_ORIGIN, 2); -// -// -// TEST_LEGS.add(START_LEG); -// TEST_LEGS.add(MIDDLE_LEG); -// TEST_LEGS.add(FINISH_LEG); -// } -// -// @Ignore -// @Test -// public void countdownTimerSendsBoatLocations() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml", new Polars()); -// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource); -// Race testRace = new Race(raceDataSource, mockOutput); -// testRace.initialiseBoats(); -// testRace.countdownTimer.handle(1); -// verify(mockOutput, atLeast(boatDataSource.getBoats().size())).parseBoatLocation(anyInt(), anyDouble(), anyDouble(), anyDouble(), anyDouble(), anyLong()); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void countdownTimerSendsRaceStatusMessages() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml", new Polars())); -// Race testRace = new Race(dataSource, mockOutput); -// testRace.initialiseBoats(); -// testRace.countdownTimer.handle(1); -// verify(mockOutput, atLeast(1)).parseRaceStatus(any()); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void checkPositionFinishedUpdatesNumberFinishedBoats() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml", new Polars())); -// Race testRace = new Race(dataSource, mockOutput); -// testRace.initialiseBoats(); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(FINISH_LEG); -// testBoat.setDistanceTravelledInLeg(1); -// testRace.checkPosition(testBoat, 1); -// -// assertEquals(testRace.getNumberOfActiveBoats(), 0); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void checkPositionSetFinishedBoatVelocityTo0() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml", new Polars())); -// Race testRace = new Race(dataSource, mockOutput); -// testRace.initialiseBoats(); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(FINISH_LEG); -// testBoat.setDistanceTravelledInLeg(1); -// testRace.checkPosition(testBoat, 1); -// -// assertEquals(testBoat.getCurrentSpeed(), 0, 1e-8); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void checkPositionSetsFinishTime() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml", new Polars())); -// Race testRace = new Race(dataSource, mockOutput); -// testRace.initialiseBoats(); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(FINISH_LEG); -// testBoat.setDistanceTravelledInLeg(1); -// testRace.checkPosition(testBoat, 1); -// -// assertEquals(testBoat.getTimeFinished(), 1, 1e-8); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void checkPositionUnfinishedDoesntUpdateNumberFinishedBoats() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml", new Polars())); -// Race testRace = new Race(dataSource, mockOutput); -// testRace.initialiseBoats(); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(START_LEG); -// testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE); -// testRace.checkPosition(testBoat, 1); -// -// assertEquals(testRace.getNumberOfActiveBoats(), 1); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// -// @Ignore -// @Test -// public void distanceTravelledBeforeUpdatingLegIsRetained() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// RaceDataSource dataSource = new RaceXMLReader("mockXML/raceTest.xml", new BoatXMLReader("mockXML/boatTest.xml", new Polars())); -// Race testRace = new Race(dataSource, mockOutput); -// testRace.initialiseBoats(); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(START_LEG); -// testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE + 1); -// testRace.checkPosition(testBoat, 0); -// -// assertEquals(testBoat.getDistanceTravelledInLeg(), 1, 1e-7); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void doNotFinishAnswersYesIf100PercentChance() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml", new Polars()); -// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource); -// Race testRace = new Race(raceDataSource, mockOutput); -// -// testRace.setDnfChance(100); -// assertTrue(testRace.doNotFinish()); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void doNotFinishAnswersNoIf0PercentChance() { -// -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml", new Polars()); -// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource); -// Race testRace = new Race(raceDataSource, mockOutput); -// testRace.setDnfChance(0); -// assertFalse(testRace.doNotFinish()); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void boatsAreSetToDNF() { -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml", new Polars()); -// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource); -// Race testRace = new Race(raceDataSource, mockOutput); -// testRace.setDnfChance(100); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(START_LEG); -// testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE + 1); -// testRace.checkPosition(testBoat, 1); -// assertEquals(testBoat.getCurrentLeg().getName(), "DNF"); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// -// } -// -// @Ignore -// @Test -// public void updatePositionIgnoresFinishedBoats() { -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml", new Polars()); -// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource); -// Race testRace = new Race(raceDataSource, mockOutput); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(FINISH_LEG); -// testBoat.setCurrentPosition(ORIGIN.getAverageGPSCoordinate()); -// testRace.updatePosition(testBoat, 1, 1); -// assertEquals(testBoat.getCurrentPosition(), ORIGIN.getAverageGPSCoordinate()); -// -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void updatePositionChangesBoatPosition() { -// try { -// MockOutput mockOutput = Mockito.mock(MockOutput.class); -// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml", new Polars()); -// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource); -// Race testRace = new Race(raceDataSource, mockOutput); -// testRace.initialiseBoats(); -// Boat testBoat = testRace.getBoats().get(0); -// testBoat.setCurrentLeg(START_LEG); -// testBoat.setDistanceTravelledInLeg(START_LEG_DISTANCE - 1); -// testBoat.setCurrentPosition(ORIGIN.getAverageGPSCoordinate()); -// testRace.updatePosition(testBoat, 100, 100); -// assertFalse(testBoat.getCurrentPosition() == ORIGIN.getAverageGPSCoordinate()); -// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -// e.printStackTrace(); -// fail(); -// } -// } -// -// @Ignore -// @Test -// public void windDirectionCorrectValues(){ -//// try { -//// MockOutput mockOutput = Mockito.mock(MockOutput.class); -//// BoatDataSource boatDataSource = new BoatXMLReader("mockXML/boatTest.xml"); -//// RaceDataSource raceDataSource = new RaceXMLReader("mockXML/raceTest.xml", boatDataSource); -//// Race testRace = new Race(raceDataSource, mockOutput); -//// testRace.setChangeWind(1); -//// testRace.setWindDir(65535); -//// testRace.changeWindDir(); -//// assertEquals(100, testRace.getWind()); -//// } catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) { -//// e.printStackTrace(); -//// fail(); -//// } -// } -// -// -//} diff --git a/racevisionGame/src/test/java/visualiser/model/VisualiserRaceTest.java b/racevisionGame/src/test/java/visualiser/model/VisualiserRaceTest.java deleted file mode 100644 index ef5e691a..00000000 --- a/racevisionGame/src/test/java/visualiser/model/VisualiserRaceTest.java +++ /dev/null @@ -1,100 +0,0 @@ -//package visualiser.model; -// -// -//import org.junit.Before; -//import org.junit.Test; -//import shared.dataInput.RaceXMLReader; -//import shared.dataInput.XMLReader; -//import shared.exceptions.InvalidRaceDataException; -//import shared.model.GPSCoordinate; -// -//import java.nio.charset.StandardCharsets; -//import java.util.List; -// -//import static org.junit.Assert.assertEquals; -//import static org.junit.Assert.fail; -// -///** -// * Tests only work on the current version of mockXML/raceXML/raceTest.xml -// */ -//public class VisualiserRaceTest { -// private RaceXMLReader streamedCourseXMLReader; -// private List boundary; -// -// @Before -// public void setup() { -// try { -// streamedCourseXMLReader = new RaceXMLReader(XMLReader.readXMLFileToString("mockXML/raceXML/raceTest.xml", StandardCharsets.UTF_8)); -// boundary = streamedCourseXMLReader.getBoundary(); -// } catch (InvalidRaceDataException e) { -// e.printStackTrace(); -// fail("Cannot find mockXML/raceXML/raceTest.xml in the resources folder"); -// } -// } -// -// @Test -// public void testAllBoundaryPointsRead() { -// assertEquals(boundary.size(), 10); -// } -// -// @Test -// public void testBoundaryPointData() { -// // First point -// assertEquals(boundary.get(0).getLatitude(), -36.8325, 1e-6); -// assertEquals(boundary.get(0).getLongitude(), 174.8325, 1e-6); -// -// // Last point -// assertEquals(boundary.get(boundary.size() - 1).getLatitude(), -36.83417, 1e-6); -// assertEquals(boundary.get(boundary.size() - 1).getLongitude(), 174.84767, 1e-6); -// } -// -// @Test -// public void testMapEdges() { -// double maxLatitude = streamedCourseXMLReader.getMapBottomRight().getLatitude() - streamedCourseXMLReader.getPadding(); -// double maxLongitude = streamedCourseXMLReader.getMapBottomRight().getLongitude() - streamedCourseXMLReader.getPadding(); -// double minLatitude = streamedCourseXMLReader.getMapTopLeft().getLatitude() - streamedCourseXMLReader.getPadding(); -// double minLongitude = streamedCourseXMLReader.getMapTopLeft().getLongitude() - streamedCourseXMLReader.getPadding(); -// -// assertEquals(maxLatitude, -36.81033, 1e-6); -// assertEquals(maxLongitude, 174.88217, 1e-6); -// assertEquals(minLatitude, -36.83417, 1e-6); -// assertEquals(minLongitude, 174.81983, 1e-6); -// } -// -// @Test -// public void testRaceSettings() { -// -// } -// -// @Test -// public void correctLegSequence() { -// List legs = streamedCourseXMLReader.getLegs(); -// String[] expectedNames = { -// "StartLine", -// "M1", -// "M2", -// "Gate" -// }; -// for(int i = 0; i < legs.size(); i++) { -// assertEquals(expectedNames[i], legs.get(i).getName()); -// } -// } -// -// /** -// * raceTest.xml is not compliant with this test. Markers are positioned far out of bounds. -// */ -// @Test -// @Ignore -// public void markersWithinRaceBoundaries() { -// GPSCoordinate topLeft = streamedCourseXMLReader.getMapTopLeft(); -// GPSCoordinate bottomRight = streamedCourseXMLReader.getMapBottomRight(); -// -// for(Marker compoundMark : streamedCourseXMLReader.getMarkers()) { -// GPSCoordinate centre = compoundMark.getAverageGPSCoordinate(); -// assertTrue(centre.getLatitude() < bottomRight.getLatitude()); -// assertTrue(centre.getLatitude() > topLeft.getLatitude()); -// assertTrue(centre.getLongitude() > bottomRight.getLongitude()); -// assertTrue(centre.getLongitude() < topLeft.getLongitude()); -// } -// } -//} diff --git a/settings/keyBindings.xml b/settings/keyBindings.xml index 2b807e17..8aa46d6c 100644 --- a/settings/keyBindings.xml +++ b/settings/keyBindings.xml @@ -1,5 +1,5 @@ - + SPACE @@ -10,8 +10,8 @@ - DOWN - + LEFT + X @@ -22,12 +22,12 @@ - Z - + RIGHT + - UP - + Z +