diff --git a/network/src/main/java/seng302/Networking/Utils/RaceStatus.java b/network/src/main/java/seng302/Networking/Utils/RaceStatus.java index 4823e3a8..24bf7521 100644 --- a/network/src/main/java/seng302/Networking/Utils/RaceStatus.java +++ b/network/src/main/java/seng302/Networking/Utils/RaceStatus.java @@ -47,6 +47,10 @@ public class RaceStatus extends AC35Data{ return raceID; } + /** + * @deprecated use status booleans + * @return race status number + */ public int getRaceStatus() { return raceStatus; @@ -76,4 +80,48 @@ public class RaceStatus extends AC35Data{ { return boatStatusMessages; } + + public boolean isNotActive() { + return raceStatus == 0; + } + + public boolean isWarning() { + return raceStatus == 1; + } + + public boolean isPreparatory() { + return raceStatus == 2; + } + + public boolean isStarted() { + return raceStatus == 3; + } + + public boolean isFinished() { + return raceStatus == 4; + } + + public boolean isRetired() { + return raceStatus == 5; + } + + public boolean isAbandoned() { + return raceStatus == 6; + } + + public boolean isPostponed() { + return raceStatus == 7; + } + + public boolean isTerminated() { + return raceStatus == 8; + } + + public boolean isStartTimeSet() { + return raceStatus != 9; + } + + public boolean isPrestart() { + return raceStatus == 10; + } } diff --git a/visualiser/src/main/java/seng302/Controllers/MainController.java b/visualiser/src/main/java/seng302/Controllers/MainController.java index 33706b2f..5f87b049 100644 --- a/visualiser/src/main/java/seng302/Controllers/MainController.java +++ b/visualiser/src/main/java/seng302/Controllers/MainController.java @@ -5,6 +5,7 @@ import javafx.fxml.FXML; import javafx.scene.layout.AnchorPane; import seng302.Model.Boat; import seng302.Model.BoatInRace; +import seng302.Model.RaceClock; import seng302.RaceDataSource; import seng302.VisualiserInput; @@ -25,8 +26,8 @@ public class MainController extends Controller { @FXML FinishController finishController; - public void beginRace(VisualiserInput visualiserInput) { - raceController.startRace(visualiserInput); + public void beginRace(VisualiserInput visualiserInput, RaceClock raceClock) { + raceController.startRace(visualiserInput, raceClock); } public void enterLobby(Socket socket) { diff --git a/visualiser/src/main/java/seng302/Controllers/RaceController.java b/visualiser/src/main/java/seng302/Controllers/RaceController.java index 07ba2586..f43c1d5c 100644 --- a/visualiser/src/main/java/seng302/Controllers/RaceController.java +++ b/visualiser/src/main/java/seng302/Controllers/RaceController.java @@ -123,7 +123,7 @@ public class RaceController extends Controller { * * @param visualiserInput input from network */ - public void startRace(VisualiserInput visualiserInput) { + public void startRace(VisualiserInput visualiserInput, RaceClock raceClock) { StreamedRace newRace = new StreamedRace(visualiserInput, this); //newRace.initialiseBoats(); @@ -148,8 +148,8 @@ public class RaceController extends Controller { race.setVisible(true); //Initialize save annotation array, fps listener, and annotation listeners - RaceClock raceClock = new RaceClock(visualiserInput.getCourse().getZonedDateTime()); timeZone.setText(raceClock.getTimeZone()); + timer.textProperty().bind(raceClock.durationProperty()); initializeFPS(); initializeAnnotations(); @@ -168,7 +168,7 @@ public class RaceController extends Controller { * @param time time that the label will be updated to */ public void setTimer(String time) { - timer.setText(time); + //timer.setText(time); } /** diff --git a/visualiser/src/main/java/seng302/Controllers/StartController.java b/visualiser/src/main/java/seng302/Controllers/StartController.java index e60ab38b..587f4f70 100644 --- a/visualiser/src/main/java/seng302/Controllers/StartController.java +++ b/visualiser/src/main/java/seng302/Controllers/StartController.java @@ -22,6 +22,8 @@ import java.net.Socket; import java.net.URL; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.time.Duration; +import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.*; @@ -41,14 +43,14 @@ public class StartController extends Controller implements Observer { @FXML private Label timeZoneTime; @FXML private Label timer; @FXML private Label raceStatusLabel; - @FXML private int PRERACE_TIME = 10; + + private ZonedDateTime startingTime; //@FXML Button fifteenMinButton; private RaceClock raceClock; private StreamedCourse raceData; - private long timeLeft = 1; private int raceStat; private VisualiserInput visualiserInput; @@ -86,47 +88,21 @@ public class StartController extends Controller implements Observer { 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. */ protected void countdownTimer() { new AnimationTimer() { - long currentTime = System.currentTimeMillis(); - long startTime = currentTime + PRERACE_TIME; - DateFormat timerFormat = new SimpleDateFormat("'Race Clock:' -HH:mm:ss"); @Override public void handle(long arg0) { - System.out.println(raceStat); - timeLeft = startTime - currentTime; raceStat = visualiserInput.getRaceStatus().getRaceStatus(); raceStatusLabel.setText("Race Status: " + visualiserInput.getRaceStatus().getRaceStatus()); if (raceStat==2 || raceStat == 3) { - updateTime("Race is starting..."); stop(); - parent.beginRace(visualiserInput); + parent.beginRace(visualiserInput, raceClock); startWrapper.setVisible(false); start.setVisible(false); - } - else if (raceStat==4 || raceStat==8) { - updateTime("Race has ended. Waiting for next race."); - } - else if (raceStat==10 || raceStat==1){ - updateTime(timerFormat.format(currentTime)); - } - currentTime = System.currentTimeMillis(); } }.start(); } @@ -134,26 +110,22 @@ public class StartController extends Controller implements Observer { private void setRaceClock() { raceClock = new RaceClock(raceData.getZonedDateTime()); timeZoneTime.textProperty().bind(raceClock.timeStringProperty()); - - new AnimationTimer() { - @Override - public void handle(long arg0) { - raceClock.updateTime(); - } - }.start(); + raceClock.run(); } private void setStartingTime() { String dateFormat = "'Starting time:' HH:mm dd/MM/YYYY"; Platform.runLater(()-> { long utcTime = visualiserInput.getRaceStatus().getExpectedStartTime(); - raceStartLabel.setText(DateTimeFormatter.ofPattern(dateFormat).format(raceClock.getLocalTime(utcTime))); + raceClock.setStartingTime(raceClock.getLocalTime(utcTime)); + raceStartLabel.setText(DateTimeFormatter.ofPattern(dateFormat).format(raceClock.getStartingTime())); + timer.textProperty().bind(raceClock.durationProperty()); }); } private void setCurrentTime() { Platform.runLater(()-> - raceClock.setTime(raceClock.getLocalTime(visualiserInput.getRaceStatus().getCurrentTime())) + raceClock.setUTCTime(visualiserInput.getRaceStatus().getCurrentTime()) ); } @@ -168,8 +140,8 @@ public class StartController extends Controller implements Observer { } if (((StreamedCourse) o).hasReadCourse()) { Platform.runLater(() -> { - while(visualiserInput.getRaceStatus() == null); setRaceClock(); + while(visualiserInput.getRaceStatus() == null); // TODO - replace with observer on VisualiserInput setStartingTime(); setCurrentTime(); }); diff --git a/visualiser/src/main/java/seng302/Mock/StreamedRace.java b/visualiser/src/main/java/seng302/Mock/StreamedRace.java index 7cd47d1d..eabd348e 100644 --- a/visualiser/src/main/java/seng302/Mock/StreamedRace.java +++ b/visualiser/src/main/java/seng302/Mock/StreamedRace.java @@ -65,7 +65,9 @@ public class StreamedRace extends Race { boat.setCurrentLeg(legs.get(legNumber)); } - if (boatStatus == BoatStatus.DNF) { + if (boatStatus == BoatStatus.RACING) { + boat.addTrackPoint(boat.getCurrentPosition()); + } else if (boatStatus == BoatStatus.DNF) { boat.setDnf(true); } else if (boatStatus == BoatStatus.FINISHED || legNumber == raceData.getLegs().size()) { boatsFinished++; diff --git a/visualiser/src/main/java/seng302/Model/Race.java b/visualiser/src/main/java/seng302/Model/Race.java index 3484cbad..2c1a66fa 100644 --- a/visualiser/src/main/java/seng302/Model/Race.java +++ b/visualiser/src/main/java/seng302/Model/Race.java @@ -22,7 +22,6 @@ import java.util.Random; * Created by fwy13 on 3/03/17. */ public abstract class Race implements Runnable { - //protected Boat[] startingBoats; protected ObservableList startingBoats; protected List legs; protected RaceController controller; @@ -32,8 +31,6 @@ public abstract class Race implements Runnable { protected int scaleFactor; private int lastFPS = 20; - private int PRERACE_TIME = 0; //time in milliseconds to pause during pre-race - private boolean timerEnabled = true; //boolean to determine if timer is ran /** * Initailiser for Race @@ -105,81 +102,7 @@ public abstract class Race implements Runnable { public void run() { setControllerListeners(); initialiseBoats(); - if (timerEnabled) countdownTimer(); - //simulateRace(); - } - - /** - * Disable the timer - */ - public void disableTimer() { - timerEnabled = false; - } - - - /** - * Countdown timer until race starts. Use PRERACE_TIME to set countdown duration. - */ - protected void countdownTimer() { - new AnimationTimer() { - long currentTime = System.currentTimeMillis(); - long startTime = currentTime + (PRERACE_TIME/scaleFactor); - long minutes; - long currentTimeInSeconds; - long remainingSeconds; - long hours; - long timeLeft; - - @Override - public void handle(long arg0) { - timeLeft = startTime - currentTime; - if (timeLeft <= 0 && controller != null) { - updateTime("Race is starting..."); - stop(); - simulateRace(); - } else { - currentTimeInSeconds = (timeLeft*scaleFactor) / 1000; - minutes = currentTimeInSeconds / 60; - remainingSeconds = currentTimeInSeconds % 60; - hours = minutes / 60; - minutes = minutes % 60; - if (controller != null) { - updateTime(String.format("Race clock: -%02d:%02d:%02d", hours, minutes, remainingSeconds)); - } - } - currentTime = System.currentTimeMillis(); - } - }.start(); - } - - /** - * Takes total time elapsed and format to hour:minute:second - * - * @return Formatted time as string - */ - protected String calcTimer() { - long minutes; - long currentTimeInSeconds; - long remainingSeconds; - long hours; - - currentTimeInSeconds = (totalTimeElapsed * scaleFactor) / 1000; - minutes = currentTimeInSeconds / 60; - remainingSeconds = currentTimeInSeconds % 60; - hours = minutes / 60; - minutes = minutes % 60; - return String.format("Race clock: %02d:%02d:%02d", hours, minutes, remainingSeconds); - } - - /** - * Updates the calculated time to the timer label - * - * @param time The calculated time from calcTimer() method - */ - protected void updateTime(String time) { - Platform.runLater(() -> { - controller.setTimer(time); - }); + simulateRace(); } @@ -222,15 +145,12 @@ public abstract class Race implements Runnable { if (boat != null && !boat.isFinished()) { updatePosition(boat, Math.round(1000 / lastFPS) > 20 ? 15 : Math.round(1000 / lastFPS)); checkPosition(boat, totalTimeElapsed); - boat.addTrackPoint(boat.getCurrentPosition()); } if (boat.isFinished()){ boatsFinished++; } } //System.out.println(boatsFinished + ":" + startingBoats.size()); - if (timerEnabled) - updateTime(calcTimer()); } else { controller.finishRace(startingBoats); stop(); @@ -266,7 +186,6 @@ public abstract class Race implements Runnable { */ protected void setControllerListeners() { if (controller != null) controller.setInfoTable(this); - //if (finishController != null) finishController.setFinishTable(this); } /** diff --git a/visualiser/src/main/java/seng302/Model/RaceClock.java b/visualiser/src/main/java/seng302/Model/RaceClock.java index 83679454..e5af8fae 100644 --- a/visualiser/src/main/java/seng302/Model/RaceClock.java +++ b/visualiser/src/main/java/seng302/Model/RaceClock.java @@ -2,6 +2,7 @@ package seng302.Model; import com.github.bfsmith.geotimezone.TimeZoneLookup; import com.github.bfsmith.geotimezone.TimeZoneResult; +import javafx.animation.AnimationTimer; import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; import seng302.GPSCoordinate; @@ -17,15 +18,18 @@ import java.util.Date; /** * Created by Gondr on 19/04/2017. */ -public class RaceClock { +public class RaceClock implements Runnable { private long lastTime; private ZoneId zoneId; private ZonedDateTime time; + private ZonedDateTime startingTime; private StringProperty timeString; + private StringProperty duration; public RaceClock(ZonedDateTime zonedDateTime) { this.zoneId = zonedDateTime.getZone(); this.timeString = new SimpleStringProperty(); + this.duration = new SimpleStringProperty(); this.time = zonedDateTime; setTime(time); } @@ -44,6 +48,15 @@ public class RaceClock { return LocalDateTime.now(zone).atZone(zone); } + public void run() { + new AnimationTimer() { + @Override + public void handle(long now) { + updateTime(); + } + }.start(); + } + /** * Sets time to arbitrary zoned time. * @@ -53,6 +66,13 @@ public class RaceClock { this.time = time; this.timeString.set(DateTimeFormatter.ofPattern("HH:mm:ss dd/MM/YYYY Z").format(time)); this.lastTime = System.currentTimeMillis(); + if(startingTime != null) { + long seconds = Duration.between(startingTime.toLocalDateTime(), time.toLocalDateTime()).getSeconds(); + if(seconds < 0) + duration.set(String.format(String.format("Starting in: %02d:%02d:%02d", -seconds/3600, -(seconds%3600)/60, -seconds%60))); + else + duration.set(String.format(String.format("Time: %02d:%02d:%02d", seconds/3600, (seconds%3600)/60, seconds%60))); + } } /** @@ -64,6 +84,14 @@ public class RaceClock { setTime(utcTime.toInstant().atZone(this.zoneId)); } + public ZonedDateTime getStartingTime() { + return startingTime; + } + + public void setStartingTime(ZonedDateTime startingTime) { + this.startingTime = startingTime; + } + /** * Get ZonedDateTime corresponding to local time zone and given UTC time. * @param time time in mills @@ -83,6 +111,14 @@ public class RaceClock { setTime(time); } + public String getDuration() { + return duration.get(); + } + + public StringProperty durationProperty() { + return duration; + } + public String getTimeZone() { return zoneId.toString(); } diff --git a/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java b/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java index 064e4149..1d3a7bfa 100644 --- a/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java +++ b/visualiser/src/main/java/seng302/Model/ResizableRaceCanvas.java @@ -203,10 +203,12 @@ public class ResizableRaceCanvas extends ResizableCanvas { public void drawMarkers() { for(Marker marker: markers) { GraphCoordinate mark1 = this.map.convertGPS(marker.getMark1()); + // removed drawing of lines between the marks as only + // the start and finish line should have a line drawn if(marker.isCompoundMark()) { GraphCoordinate mark2 = this.map.convertGPS(marker.getMark2()); - // TODO - improve colour coding of markers - displayLine(mark1, mark2, Color.GREEN); + displayPoint(mark1, Color.LIMEGREEN); + displayPoint(mark2, Color.LIMEGREEN); } else { displayPoint(mark1, Color.GREEN); }