@ -1,8 +1,11 @@
package seng302.Model ;
import javafx.animation.AnimationTimer ;
import javafx.application.Platform ;
import javafx.beans.property.StringProperty ;
import javafx.collections.FXCollections ;
import javafx.collections.ObservableArray ;
import javafx.collections.ObservableList ;
import org.geotools.referencing.GeodeticCalculator ;
import seng302.Controllers.RaceController ;
@ -27,12 +30,11 @@ public abstract class Race implements Runnable {
protected int scaleFactor ;
private int SLEEP_TIME = 100 ; //time in milliseconds to pause in a paced loop
protected int PRERACE_TIME = 100 ; //Integer.MAX_VALUE; //time in milliseconds to pause during pre-race
protected int PRERACE_TIME = 100 00 ; //Integer.MAX_VALUE; //time in milliseconds to pause during pre-race
private boolean timerEnabled = true ;
/ * *
* Initailiser for Race
*
* @param boats Takes in an array of boats that are participating in the race .
* @param legs Number of marks in order that the boats pass in order to complete the race .
* /
@ -50,7 +52,6 @@ public abstract class Race implements Runnable {
/ * *
* Constructor for Race class
*
* @param boats boats participating in the race .
* @param legs legs that there are in the race .
* /
@ -90,33 +91,21 @@ public abstract class Race implements Runnable {
* /
public void run ( ) {
setControllerListeners ( ) ;
preRace ( ) ;
if ( timerEnabled ) countdownTimer ( ) ;
initialiseBoats ( ) ;
if ( timerEnabled ) countdownTimer ( ) ;
simulateRace ( ) ;
}
public void disableTimer ( ) {
timerEnabled = false ;
}
/ * *
* Initialises the boats ,
* Sets the boats ' current to the first leg in the race
* Disable the timer
* /
private void preRace ( ) {
//show the boats participating.
ArrayList < GPSCoordinate > startPositons = getSpreadStartingPositions ( ) ;
for ( int i = 0 ; i < startingBoats . size ( ) ; i + + ) {
if ( startingBoats . get ( i ) ! = null ) {
startingBoats . get ( i ) . setCurrentLeg ( legs . get ( 0 ) ) ;
}
}
public void disableTimer ( ) {
timerEnabled = false ;
}
/ * *
* Prerace timer showing time until the race will begin , as a negative value
* Countdown timer until race starts . Use PRERACE_TIME to set countdown duration .
* /
protected void countdownTimer ( ) {
long currentTime = System . currentTimeMillis ( ) ;
@ -129,18 +118,15 @@ public abstract class Race implements Runnable {
long timeLoopEnded ;
while ( currentTime < = startTime ) {
if ( controller ! = null ) controller . updateMap ( startingBoats ) ;
timeLeft = startTime - currentTime ;
if ( timeLeft = = 0 & & controller ! = null ) {
updateTime ( "Race is starting..." ) ;
} else {
currentTimeInSeconds = timeLeft / 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 ) ) ;
}
updateTime ( String . format ( "Time until race starts: %02d:%02d:%02d" , hours , minutes , remainingSeconds ) ) ;
}
try {
timeLoopEnded = System . currentTimeMillis ( ) ;
@ -153,8 +139,8 @@ public abstract class Race implements Runnable {
}
/ * *
* Takes elapsed time in minutes and scales it , converts to hh : mm : ss format
* @return String formatted race time , scaled
* Takes total time elapsed and format to hour : minute : second
* @return Formatted time as string
* /
protected String calcTimer ( ) {
long minutes ;
@ -162,24 +148,24 @@ public abstract class Race implements Runnable {
long remainingSeconds ;
long hours ;
currentTimeInSeconds = totalTimeElapsed / 1000 ;
long scaledTimeInSeconds = currentTimeInSeconds * scaleFactor ;
minutes = scaledTimeInSeconds / 60 ;
remainingSeconds = scaledTimeInSeconds % 60 ;
currentTimeInSeconds = ( totalTimeElapsed / 1000 ) * scaleFactor ;
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 GUI race clock
* @param time
* Updates the calculated time to the timer label
* @param time The calculated time from calcTimer ( ) method
* /
protected void updateTime ( String time ) {
protected void updateTime ( String time ) {
Platform . runLater ( ( ) - > { controller . setTimer ( time ) ; } ) ;
}
Platform . runLater ( ( ) - > {
controller . setTimer ( time ) ;
} ) ;
private void updateFPS ( int fps ) {
Platform . runLater ( ( ) - > { controller . setFrames ( "FPS: " + fps ) ; } ) ;
}
/ * *
@ -188,14 +174,24 @@ public abstract class Race implements Runnable {
* /
private void simulateRace ( ) {
System . setProperty ( "javafx.animation.fullspeed" , "true" ) ;
new AnimationTimer ( ) {
long timeRaceStarted = System . currentTimeMillis ( ) ;
long timeLoopStarted ;
long timeLoopEnded ;
int fps = 0 ;
long timeCurrent = System . currentTimeMillis ( ) ;
while ( boatsFinished < startingBoats . size ( ) ) {
timeLoopStarted = System . currentTimeMillis ( ) ;
totalTimeElapsed = System . currentTimeMillis ( ) - timeRaceStarted ;
@Override
public void handle ( long arg0 ) {
/ * long timeLoopStarted ;
long timeLoopEnded ;
int fps = 0 ; * /
if ( controller ! = null ) controller . updateMap ( startingBoats ) ;
if ( boatsFinished < startingBoats . size ( ) ) {
//timeLoopStarted = System.currentTimeMillis();
totalTimeElapsed = System . currentTimeMillis ( ) - timeRaceStarted ;
for ( BoatInRace boat : startingBoats ) {
if ( boat ! = null & & ! boat . isFinished ( ) ) {
@ -204,26 +200,40 @@ public abstract class Race implements Runnable {
}
}
if ( controller ! = null ) controller . updateMap ( startingBoats ) ;
if ( timerEnabled ) updateTime ( calcTimer ( ) ) ;
//if (controller != null) controller.updateMap(startingBoats);
if ( timerEnabled )
updateTime ( calcTimer ( ) ) ;
}
fps + + ;
if ( ( System . currentTimeMillis ( ) - timeCurrent ) > 1000 ) {
updateFPS ( fps ) ;
fps = 0 ;
timeCurrent = System . currentTimeMillis ( ) ;
}
;
/ * fps + + ;
try {
timeLoopEnded = System . currentTimeMillis ( ) ;
Thread . sleep ( SLEEP_TIME - ( timeLoopEnded - timeLoopStarted ) ) ;
} catch ( InterruptedException e ) {
return ;
}
}
} * /
} ;
//System.out.println("Avg fps:" + fps/(totalTimeElapsed/1000));
} . start ( ) ;
}
/ * *
* Checks the position of the boat , this updates the boats current position .
*
* @param boat Boat that the postion is to be updated for .
* @param timeElapsed Time that has elapse since the start of the the race .
* @see BoatInRace
* /
protected void checkPosition ( BoatInRace boat , long timeElapsed ) {
if ( boat . getDistanceTravelledInLeg ( ) > boat . getCurrentLeg ( ) . getDistance ( ) ) {
if ( boat . getDistanceTravelledInLeg ( ) > boat . getCurrentLeg ( ) . getDistance ( ) ) {
// updateController();
//boat has passed onto new leg
if ( boat . getCurrentLeg ( ) . getName ( ) . equals ( "Finish" ) ) {
//boat has finished
@ -231,16 +241,13 @@ public abstract class Race implements Runnable {
boat . setFinished ( true ) ;
boat . setTimeFinished ( timeElapsed ) ;
} else {
//Calculate how much the boat overshot the marker by
boat . setDistanceTravelledInLeg ( boat . getDistanceTravelledInLeg ( ) - boat . getCurrentLeg ( ) . getDistance ( ) ) ;
//Move boat on to next leg
Leg nextLeg = legs . get ( boat . getCurrentLeg ( ) . getLegNumber ( ) + 1 ) ;
boat . setCurrentLeg ( nextLeg ) ;
//Add overshoot distance into the distance travelled for the next leg
boat . setDistanceTravelledInLeg ( boat . getDistanceTravelledInLeg ( ) ) ;
}
//Update the boat display table in the GUI to reflect the leg change
FXCollections . sort ( startingBoats , ( a , b ) - > b . getCurrentLeg ( ) . getLegNumber ( ) - a . getCurrentLeg ( ) . getLegNumber ( ) ) ;
FXCollections . sort ( startingBoats , ( a , b ) - > b . getCurrentLeg ( ) . getLegNumber ( ) - a . getCurrentLeg ( ) . getLegNumber ( ) ) ;
}
}
@ -248,12 +255,11 @@ public abstract class Race implements Runnable {
* Update call for the controller .
* /
protected void setControllerListeners ( ) {
if ( controller ! = null ) controller . setInfoTable ( this ) ;
if ( controller ! = null ) controller . setInfoTable ( this ) ;
}
/ * *
* Returns the boats that have started the race .
*
* @return ObservableList of BoatInRace class that participated in the race .
* @see ObservableList
* @see BoatInRace
@ -262,12 +268,12 @@ public abstract class Race implements Runnable {
return startingBoats ;
}
/ * *
* Updates the boat ' s gps coordinates depending on time elapsed
* @param boat
* @ param millisecondsElapsed
* This function is a function that generates the Race and populates the events list .
* Is automatically called by the initialiser function , so that simulateRace ( ) does not return an empty race .
* @ see Race # simulateRace ( )
* /
protected abstract void updatePosition ( BoatInRace boat , int millisecondsElapsed ) ;
/ * *