Merge branch 'raceLength' into 'master'
Race length AC's: - Scale map to selected duration of user See merge request !64
This commit is contained in:
@@ -21,7 +21,7 @@ public class App extends Application {
|
|||||||
public void start(Stage primaryStage) {
|
public void start(Stage primaryStage) {
|
||||||
try {
|
try {
|
||||||
//TODO should read a configuration file to configure server?
|
//TODO should read a configuration file to configure server?
|
||||||
Event raceEvent = new Event(false, 0);
|
Event raceEvent = new Event(false, 0, 5);
|
||||||
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -40,24 +40,17 @@ public class Event {
|
|||||||
private String raceXML;
|
private String raceXML;
|
||||||
private String regattaXML;
|
private String regattaXML;
|
||||||
private String boatXML;
|
private String boatXML;
|
||||||
|
|
||||||
private XMLFileType xmlFileType;
|
private XMLFileType xmlFileType;
|
||||||
|
|
||||||
private Polars boatPolars;
|
private Polars boatPolars;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data sources containing data from the xml files.
|
* Data sources containing data from the xml files.
|
||||||
*/
|
*/
|
||||||
RaceDataSource raceDataSource;
|
private RaceDataSource raceDataSource;
|
||||||
BoatDataSource boatDataSource;
|
private BoatDataSource boatDataSource;
|
||||||
RegattaDataSource regattaDataSource;
|
private RegattaDataSource regattaDataSource;
|
||||||
|
|
||||||
|
|
||||||
private ConnectionAcceptor connectionAcceptor;
|
private ConnectionAcceptor connectionAcceptor;
|
||||||
private LatestMessages latestMessages;
|
private LatestMessages latestMessages;
|
||||||
|
|
||||||
private CompositeCommand compositeCommand;
|
private CompositeCommand compositeCommand;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is used to allocate source IDs.
|
* This is used to allocate source IDs.
|
||||||
*/
|
*/
|
||||||
@@ -66,22 +59,17 @@ public class Event {
|
|||||||
private RaceLogic raceLogic;
|
private RaceLogic raceLogic;
|
||||||
|
|
||||||
private Thread raceThread;
|
private Thread raceThread;
|
||||||
|
|
||||||
private Thread connectionThread;
|
private Thread connectionThread;
|
||||||
|
|
||||||
private int mapIndex;
|
private int mapIndex;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs an event, using various XML files.
|
* Constructs an event, using various XML files.
|
||||||
* @param singlePlayer Whether or not to create a single player event.
|
* @param singlePlayer Whether or not to create a single player event.
|
||||||
* @param mapIndex Specifies which map to use.
|
* @param mapIndex Specifies which map to use.
|
||||||
* @throws EventConstructionException Thrown if we cannot create an Event for any reason.
|
* @throws EventConstructionException Thrown if we cannot create an Event for any reason.
|
||||||
*/
|
*/
|
||||||
public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException {
|
public Event(boolean singlePlayer, int mapIndex, int raceLength) throws
|
||||||
|
EventConstructionException {
|
||||||
PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
|
PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
|
||||||
this.mapIndex = mapIndex;
|
this.mapIndex = mapIndex;
|
||||||
String raceXMLFile;
|
String raceXMLFile;
|
||||||
@@ -125,8 +113,8 @@ public class Event {
|
|||||||
} else {
|
} else {
|
||||||
this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8));
|
this.raceXML = Event.setRaceXMLAtCurrentTimeToNow(XMLReader.readXMLFileToString(raceXMLFile, StandardCharsets.UTF_8));
|
||||||
this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle);
|
this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle);
|
||||||
this.raceXML = RaceXMLCreator.scaleRaceSize(raceXML, windSpeed, 15 * 60 * 1000);
|
this.raceXML = RaceXMLCreator.scaleRaceSize(raceXML,
|
||||||
|
windSpeed, raceLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8);
|
this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8);
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import java.time.ZonedDateTime;
|
|||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper Class for creating a Race XML
|
* Helper Class for creating a Race XML
|
||||||
@@ -212,13 +214,17 @@ public class RaceXMLCreator {
|
|||||||
double averageSpeed = (bestDownWindSpeed + bestUpWindSpeed) / 2;
|
double averageSpeed = (bestDownWindSpeed + bestUpWindSpeed) / 2;
|
||||||
double raceApproximateTime = getRaceLength(race, averageSpeed);
|
double raceApproximateTime = getRaceLength(race, averageSpeed);
|
||||||
double scale = milliseconds / raceApproximateTime;
|
double scale = milliseconds / raceApproximateTime;
|
||||||
|
Map<XMLCompoundMark, Boolean> hasBeenScaled = new HashMap<>();
|
||||||
for (XMLCorner cm: race.getCompoundMarkSequence().getCorner()){
|
for (XMLCorner cm: race.getCompoundMarkSequence().getCorner()){
|
||||||
int index = cm.getCompoundMarkID() - 1;
|
int index = cm.getCompoundMarkID() - 1;
|
||||||
XMLCompoundMark mark = race.getCourse().getCompoundMark().get(index);
|
XMLCompoundMark mark = race.getCourse().getCompoundMark().get(index);
|
||||||
for (XMLMark m: mark.getMark()){
|
if (!hasBeenScaled.containsKey(mark)) {
|
||||||
|
for (XMLMark m : mark.getMark()) {
|
||||||
scalePoint(m, center, scale);
|
scalePoint(m, center, scale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hasBeenScaled.put(mark, true);
|
||||||
|
}
|
||||||
for (XMLLimit limit: race.getCourseLimit().getLimit()){
|
for (XMLLimit limit: race.getCourseLimit().getLimit()){
|
||||||
scalePoint(limit, center, scale);
|
scalePoint(limit, center, scale);
|
||||||
}
|
}
|
||||||
@@ -319,8 +325,13 @@ public class RaceXMLCreator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sets the current race time of the xml
|
||||||
|
* @param raceXML race xml to alter
|
||||||
|
* @param racePrestartTime prestart time
|
||||||
|
* @param racePreparatoryTime preparatory time
|
||||||
|
* @deprecated this should be used from the RaceXMLCreator not from this function
|
||||||
|
*/
|
||||||
public static void setRaceXMLAtCurrentTimeToNow(XMLRace raceXML, long racePrestartTime, long racePreparatoryTime){
|
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.
|
//The start time is current time + 4 minutes. prestart is 3 minutes, and we add another minute.
|
||||||
long millisecondsToAdd = racePrestartTime + racePreparatoryTime;
|
long millisecondsToAdd = racePrestartTime + racePreparatoryTime;
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import javafx.application.Platform;
|
|||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Alert;
|
import javafx.scene.control.Alert;
|
||||||
import javafx.scene.control.ButtonType;
|
import javafx.scene.control.ButtonType;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.Slider;
|
||||||
import javafx.scene.image.Image;
|
import javafx.scene.image.Image;
|
||||||
import javafx.scene.image.ImageView;
|
import javafx.scene.image.ImageView;
|
||||||
import mock.app.Event;
|
import mock.app.Event;
|
||||||
@@ -28,8 +30,12 @@ import java.util.logging.Logger;
|
|||||||
*/
|
*/
|
||||||
public class HostGameController extends Controller {
|
public class HostGameController extends Controller {
|
||||||
private @FXML ImageView mapImage;
|
private @FXML ImageView mapImage;
|
||||||
|
private @FXML Slider sliderLength;
|
||||||
|
private @FXML Label lblLength;
|
||||||
private ArrayList<Image> listOfMaps;
|
private ArrayList<Image> listOfMaps;
|
||||||
private int currentMapIndex = 0;
|
private int currentMapIndex = 0;
|
||||||
|
private int selectedRaceLength; // in minutes
|
||||||
|
private final int MAX_RACE_LENGTH = 30; // in minutes
|
||||||
private DatagramSocket udpSocket;
|
private DatagramSocket udpSocket;
|
||||||
private MatchBrowserInterface matchBrowserInterface;
|
private MatchBrowserInterface matchBrowserInterface;
|
||||||
|
|
||||||
@@ -37,8 +43,33 @@ public class HostGameController extends Controller {
|
|||||||
loadMaps();
|
loadMaps();
|
||||||
this.udpSocket = MatchBrowserSingleton.getInstance().getUdpSocket();
|
this.udpSocket = MatchBrowserSingleton.getInstance().getUdpSocket();
|
||||||
this.matchBrowserInterface = MatchBrowserSingleton.getInstance().getMatchBrowserInterface();
|
this.matchBrowserInterface = MatchBrowserSingleton.getInstance().getMatchBrowserInterface();
|
||||||
|
setRaceLengthSlider();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the values and display for a slider object which allows a user
|
||||||
|
* to select how many minutes long they would like their race to be.
|
||||||
|
*/
|
||||||
|
private void setRaceLengthSlider(){
|
||||||
|
// set the listener to update the label
|
||||||
|
sliderLength.valueProperty().addListener((ov, old_val, new_val) -> {
|
||||||
|
selectedRaceLength = new_val.intValue();
|
||||||
|
if (selectedRaceLength == 1){
|
||||||
|
lblLength.setText(selectedRaceLength + " minute.");
|
||||||
|
} else {
|
||||||
|
lblLength.setText(selectedRaceLength + " minutes.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// set values and marks to be displayed
|
||||||
|
sliderLength.setMin(2);
|
||||||
|
sliderLength.setMax(MAX_RACE_LENGTH);
|
||||||
|
sliderLength.setShowTickLabels(true);
|
||||||
|
sliderLength.setMajorTickUnit(MAX_RACE_LENGTH-1);
|
||||||
|
sliderLength.setBlockIncrement(1);
|
||||||
|
|
||||||
|
sliderLength.getStylesheets().add("/css/slider.css");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,7 +95,8 @@ public class HostGameController extends Controller {
|
|||||||
*/
|
*/
|
||||||
public void hostGamePressed() {
|
public void hostGamePressed() {
|
||||||
try {
|
try {
|
||||||
App.game = new Event(false, currentMapIndex);
|
App.game = new Event(false, currentMapIndex,
|
||||||
|
selectedRaceLength*60*1000);
|
||||||
App.gameType = currentMapIndex;
|
App.gameType = currentMapIndex;
|
||||||
|
|
||||||
HttpMatchBrowserHost matchBrowserHost = new HttpMatchBrowserHost();
|
HttpMatchBrowserHost matchBrowserHost = new HttpMatchBrowserHost();
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
.slider .thumb {
|
||||||
|
-fx-background-image: url("/visualiser/images/sun.png");
|
||||||
|
-fx-background-size: 25px;
|
||||||
|
-fx-pref-height: 25px;
|
||||||
|
-fx-pref-width: 25px;
|
||||||
|
-fx-background-position: top;
|
||||||
|
-fx-background-repeat: no-repeat;
|
||||||
|
-fx-focus-color: transparent;
|
||||||
|
-fx-background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider .track {
|
||||||
|
-fx-control-inner-background: dodgerblue;
|
||||||
|
-fx-border-color: rgba(30, 144, 255, 0.44);
|
||||||
|
-fx-border-radius: 0.25em, 0.25em, 0.166667em;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
<?import javafx.geometry.Insets?>
|
<?import javafx.geometry.Insets?>
|
||||||
<?import javafx.scene.control.Button?>
|
<?import javafx.scene.control.Button?>
|
||||||
<?import javafx.scene.control.Label?>
|
<?import javafx.scene.control.Label?>
|
||||||
|
<?import javafx.scene.control.Slider?>
|
||||||
<?import javafx.scene.image.ImageView?>
|
<?import javafx.scene.image.ImageView?>
|
||||||
<?import javafx.scene.layout.AnchorPane?>
|
<?import javafx.scene.layout.AnchorPane?>
|
||||||
<?import javafx.scene.layout.ColumnConstraints?>
|
<?import javafx.scene.layout.ColumnConstraints?>
|
||||||
@@ -12,19 +13,20 @@
|
|||||||
|
|
||||||
<AnchorPane fx:id="hostWrapper" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="780.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="visualiser.Controllers.HostGameController">
|
<AnchorPane fx:id="hostWrapper" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="780.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="visualiser.Controllers.HostGameController">
|
||||||
<children>
|
<children>
|
||||||
<GridPane layoutY="14.0" AnchorPane.bottomAnchor="-14.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="14.0">
|
<GridPane layoutY="14.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
|
||||||
<columnConstraints>
|
<columnConstraints>
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="170.0" minWidth="10.0" prefWidth="170.0" />
|
<ColumnConstraints hgrow="NEVER" prefWidth="170.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
<ColumnConstraints hgrow="NEVER" prefWidth="100.0" />
|
||||||
<ColumnConstraints hgrow="SOMETIMES" maxWidth="170.0" minWidth="10.0" prefWidth="170.0" />
|
<ColumnConstraints hgrow="NEVER" prefWidth="170.0" />
|
||||||
</columnConstraints>
|
</columnConstraints>
|
||||||
<rowConstraints>
|
<rowConstraints>
|
||||||
<RowConstraints maxHeight="60.0" minHeight="60.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
<RowConstraints prefHeight="50.0" vgrow="NEVER" />
|
||||||
<RowConstraints minHeight="10.0" prefHeight="435.0" vgrow="SOMETIMES" />
|
<RowConstraints prefHeight="419.5" vgrow="NEVER" />
|
||||||
<RowConstraints maxHeight="80.0" minHeight="80.0" prefHeight="80.0" vgrow="SOMETIMES" />
|
<RowConstraints prefHeight="50.0" vgrow="NEVER" />
|
||||||
|
<RowConstraints prefHeight="80.0" vgrow="NEVER" />
|
||||||
</rowConstraints>
|
</rowConstraints>
|
||||||
<children>
|
<children>
|
||||||
<Button fx:id="hostGameBtn" mnemonicParsing="false" onAction="#hostGamePressed" text="Start Game" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="CENTER">
|
<Button fx:id="hostGameBtn" mnemonicParsing="false" onAction="#hostGamePressed" text="Start Game" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="3" GridPane.valignment="CENTER">
|
||||||
<font>
|
<font>
|
||||||
<Font size="20.0" />
|
<Font size="20.0" />
|
||||||
</font>
|
</font>
|
||||||
@@ -50,6 +52,16 @@
|
|||||||
<ImageView fx:id="mapImage" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
|
<ImageView fx:id="mapImage" pickOnBounds="true" preserveRatio="true" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.hgrow="ALWAYS" GridPane.rowIndex="1" GridPane.valignment="CENTER" GridPane.vgrow="ALWAYS" />
|
||||||
<Button fx:id="previousButton" maxHeight="80.0" maxWidth="80.0" mnemonicParsing="false" onAction="#previousImage" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
|
<Button fx:id="previousButton" maxHeight="80.0" maxWidth="80.0" mnemonicParsing="false" onAction="#previousImage" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
|
||||||
<Button fx:id="nextButton" maxHeight="80.0" maxWidth="80.0" mnemonicParsing="false" onAction="#nextImage" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
|
<Button fx:id="nextButton" maxHeight="80.0" maxWidth="80.0" mnemonicParsing="false" onAction="#nextImage" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER" />
|
||||||
|
<Slider fx:id="sliderLength" prefHeight="14.0" prefWidth="100.0" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets left="50.0" right="50.0" />
|
||||||
|
</GridPane.margin>
|
||||||
|
</Slider>
|
||||||
|
<Label fx:id="lblLength" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2" GridPane.valignment="BOTTOM">
|
||||||
|
<GridPane.margin>
|
||||||
|
<Insets />
|
||||||
|
</GridPane.margin>
|
||||||
|
</Label>
|
||||||
</children>
|
</children>
|
||||||
</GridPane>
|
</GridPane>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
Reference in New Issue
Block a user