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