package seng302.Controllers; import javafx.animation.AnimationTimer; import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; import org.xml.sax.SAXException; import seng302.Mock.*; import seng302.Model.Boat; import seng302.Model.RaceClock; import seng302.RaceDataSource; import seng302.RaceXMLReader; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.net.URL; import java.text.ParseException; import java.util.List; import java.util.ResourceBundle; /** * Created by esa46 on 6/04/17. */ public class StartController extends Controller { @FXML private GridPane start; @FXML private AnchorPane startWrapper; @FXML private TableView boatNameTable; @FXML private TableColumn boatNameColumn; @FXML private TableColumn boatCodeColumn; @FXML private Label timeZoneTime; @FXML private Label timer; @FXML private int PRERACE_TIME = 15000; @FXML Button oneMinButton; @FXML Button fiveMinButton; @FXML Button fifteenMinButton; private RaceClock raceClock; private RaceDataSource raceData; private long timeLeft = 1; /** * Begins the race with a scale factor of 15 */ public void startRace1Min() { startRace(15); } /** * Begins the race with a scale factor of 3 */ public void startRace5Min() { startRace(3); } /** * Begins the race with a scale factor of 1 */ public void startRaceNoScaling() { startRace(1); } private void startRace(int raceScale){ oneMinButton.setDisable(true); fiveMinButton.setDisable(true); fifteenMinButton.setDisable(true); countdownTimer(raceScale); } @Override public void initialize(URL location, ResourceBundle resources){ raceData = null; try { StreamedCourse streamedCourse = new StreamedCourse(new BoatXMLReader("mockXML/boatXML/boatTest.xml")); streamedCourse.setStreamedCourseXMLReader(new StreamedCourseXMLReader("mockXML/raceXML/raceTest.xml")); streamedCourse.setRegattaXMLReader(new RegattaXMLReader("mockXML/regattaXML/regattaTest.xml")); raceData = streamedCourse; } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } catch (StreamedCourseXMLException e) { e.printStackTrace(); } initialiseTables(); setRaceClock(); } public AnchorPane startWrapper(){ return startWrapper; } private void initialiseTables() { List boats = raceData.getBoats(); ObservableList observableBoats = FXCollections.observableArrayList(boats); boatNameTable.setItems(observableBoats); boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().getName()); boatCodeColumn.setCellValueFactory(new PropertyValueFactory<>("abbrev")); } /** * Updates the calculated time to the timer label * * @param time The calculated time from calcTimer() method */ protected void updateTime(String time) { Platform.runLater(() -> { timer.setText(time); }); } /** * Countdown timer until race starts. Use PRERACE_TIME to set countdown duration. */ protected void countdownTimer(int scaleFactor) { new AnimationTimer() { long currentTime = System.currentTimeMillis(); long startTime = currentTime + (PRERACE_TIME/scaleFactor); long minutes; long currentTimeInSeconds; long remainingSeconds; long hours; @Override public void handle(long arg0) { timeLeft = startTime - currentTime; if (timeLeft <= 0) { updateTime("Race is starting..."); stop(); parent.beginRace(scaleFactor, raceData); startWrapper.setVisible(false); } else { currentTimeInSeconds = (timeLeft*scaleFactor) / 1000; minutes = currentTimeInSeconds / 60; remainingSeconds = currentTimeInSeconds % 60; hours = minutes / 60; minutes = minutes % 60; updateTime(String.format("Race Clock: -%02d:%02d:%02d", hours, minutes, remainingSeconds)); } currentTime = System.currentTimeMillis(); } }.start(); } protected void setRaceClock() { raceClock = new RaceClock(raceData.getZonedDateTime()); timeZoneTime.textProperty().bind(raceClock.timeStringProperty()); new AnimationTimer() { @Override public void handle(long arg0) { if (timeLeft > 0) { raceClock.updateTime(); } else { stop(); } } }.start(); } }