You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

276 lines
7.4 KiB

package visualiser.Controllers;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
import mock.model.commandFactory.CompositeCommand;
import network.Messages.Enums.RaceStatusEnum;
import network.Messages.Enums.RequestToJoinEnum;
import network.Messages.LatestMessages;
import shared.dataInput.*;
import shared.enums.XMLFileType;
import shared.exceptions.InvalidBoatDataException;
import shared.exceptions.InvalidRaceDataException;
import shared.exceptions.InvalidRegattaDataException;
import shared.exceptions.XMLReaderException;
import visualiser.gameController.ControllerClient;
import visualiser.model.VisualiserRaceState;
import visualiser.network.ServerConnection;
import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRaceEvent;
import java.io.IOException;
import java.net.Socket;
import java.net.URL;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Controller to for waiting for the race to start.
*/
public class StartController extends Controller {
@FXML private GridPane start;
@FXML private AnchorPane startWrapper;
/**
* The name of the race/regatta.
*/
@FXML private Label raceTitleLabel;
/**
* The time the race starts at.
*/
@FXML private Label raceStartLabel;
/**
* The current time at the race location.
*/
@FXML private Label timeZoneTime;
/**
* Time until the race starts.
*/
@FXML private Label timer;
@FXML private TableView<VisualiserBoat> boatNameTable;
@FXML private TableColumn<VisualiserBoat, String> boatNameColumn;
@FXML private TableColumn<VisualiserBoat, String> boatCodeColumn;
/**
* The status of the race.
*/
@FXML private Label raceStatusLabel;
/**
* The race + connection to server.
*/
private VisualiserRaceEvent visualiserRaceEvent;
/**
* Writes BoatActions to outgoing message queue.
*/
private ControllerClient controllerClient;
private boolean isHost;
/**
* Ctor.
*/
public StartController() {
}
@Override
public void initialize(URL location, ResourceBundle resources) {
}
/**
* Starts the race.
*/
private void startRace() {
//Initialise the boat table.
initialiseBoatTable(this.visualiserRaceEvent.getVisualiserRaceState());
//Initialise the race name.
initialiseRaceName(this.visualiserRaceEvent.getVisualiserRaceState());
//Initialises the race clock.
initialiseRaceClock(this.visualiserRaceEvent.getVisualiserRaceState());
//Starts the race countdown timer.
countdownTimer();
}
public AnchorPane startWrapper(){
return startWrapper;
}
/**
* Initialises the boat table that is to be shown on the pane.
* @param visualiserRace The race to get data from.
*/
private void initialiseBoatTable(VisualiserRaceState visualiserRace) {
//Get the boats.
ObservableList<VisualiserBoat> boats = visualiserRace.getBoats();
//Populate table.
boatNameTable.setItems(boats);
boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().nameProperty());
boatCodeColumn.setCellValueFactory(cellData -> cellData.getValue().countryProperty());
}
/**
* Initialises the race name which is shown on the pane.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceName(VisualiserRaceState visualiserRace) {
raceTitleLabel.setText(visualiserRace.getRegattaName());
}
/**
* Initialises the race clock/timer labels for the start time, current time, and remaining time.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClock(VisualiserRaceState visualiserRace) {
//Start time.
initialiseRaceClockStartTime(visualiserRace);
//Current time.
initialiseRaceClockCurrentTime(visualiserRace);
//Remaining time.
initialiseRaceClockDuration(visualiserRace);
}
/**
* Initialises the race current time label.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClockStartTime(VisualiserRaceState visualiserRace) {
raceStartLabel.setText(visualiserRace.getRaceClock().getStartingTimeString());
visualiserRace.getRaceClock().startingTimeProperty().addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> {
raceStartLabel.setText(newValue);
});
});
}
/**
* Initialises the race current time label.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClockCurrentTime(VisualiserRaceState visualiserRace) {
visualiserRace.getRaceClock().currentTimeProperty().addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> {
timeZoneTime.setText(newValue);
});
});
}
/**
* Initialises the race duration label.
* @param visualiserRace The race to get data from.
*/
private void initialiseRaceClockDuration(VisualiserRaceState visualiserRace) {
visualiserRace.getRaceClock().durationProperty().addListener((observable, oldValue, newValue) -> {
Platform.runLater(() -> {
timer.setText(newValue);
});
});
}
/**
* Countdown timer until race starts.
*/
private void countdownTimer() {
new AnimationTimer() {
@Override
public void handle(long arg0) {
//Get the current race status.
RaceStatusEnum raceStatus = visualiserRaceEvent.getVisualiserRaceState().getRaceStatusEnum();
//Display it.
raceStatusLabel.setText("Race Status: " + raceStatus.name());
//If the race has reached the preparatory phase, or has started...
if (raceStatus == RaceStatusEnum.PREPARATORY || raceStatus == RaceStatusEnum.STARTED) {
//Stop this timer.
stop();
//Hide this, and display the race controller.
startWrapper.setVisible(false);
//start.setVisible(false);//TODO is this needed?
parent.beginRace(visualiserRaceEvent, controllerClient, isHost);
}
}
}.start();
}
/**
* Show starting information for a race given a socket.
* @param socket network source of information
* @param isHost is user a host
*/
public void enterLobby(Socket socket, Boolean isHost) {
try {
this.isHost = isHost;
this.visualiserRaceEvent = new VisualiserRaceEvent(socket, RequestToJoinEnum.PARTICIPANT);
this.controllerClient = visualiserRaceEvent.getControllerClient();
startWrapper.setVisible(true);
startRace();
} catch (IOException e) {
//TODO should probably let this propagate, so that we only enter this scene if everything works
Logger.getGlobal().log(Level.WARNING, "Could not connect to server.", e);
}
}
}