Merge branch 'wind_(story53)' into 'master'

Wind (story53)

AC:

Note: "Back" means that the wind shifts counterclockwise while "veer" means clockwise. Shifts should follow the following patterns:

1. The wind should usually oscillate regularly around a mean (several minutes per oscillation and no more than 5 degrees either way.)
2. Occasionally it will either "back" or "veer" (a few degrees a minute, up to 180 degrees shift), and then return to oscillations.

Acceptance criteria:

- The wind direction follows the above patterns during a race.

* Test wind works at 0 to small degree amounts.


See merge request !36
main
Fan-Wu Yang 8 years ago
commit ba13713ba1

@ -4,6 +4,9 @@ import mock.dataInput.PolarParser;
import mock.exceptions.EventConstructionException; import mock.exceptions.EventConstructionException;
import mock.model.*; import mock.model.*;
import mock.model.commandFactory.CompositeCommand; import mock.model.commandFactory.CompositeCommand;
import mock.model.wind.RandomWindGenerator;
import mock.model.wind.ShiftingWindGenerator;
import mock.model.wind.WindGenerator;
import mock.xml.RaceXMLCreator; import mock.xml.RaceXMLCreator;
import network.Messages.LatestMessages; import network.Messages.LatestMessages;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
@ -18,11 +21,8 @@ import shared.model.Constants;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.TransformerException;
import java.io.IOException; import java.io.IOException;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.ArrayList; import java.util.ArrayList;
@ -124,14 +124,10 @@ public class Event {
this.compositeCommand = new CompositeCommand(); this.compositeCommand = new CompositeCommand();
this.latestMessages = new LatestMessages(); this.latestMessages = new LatestMessages();
//Create and start race. WindGenerator windGenerator = new ShiftingWindGenerator(
WindGenerator windGenerator = new RandomWindGenerator(
Bearing.fromDegrees(225), Bearing.fromDegrees(225),
Bearing.fromDegrees(215), 12
Bearing.fromDegrees(235), );
12d,
8d,
16d );
RaceLogic newRace = new RaceLogic( RaceLogic newRace = new RaceLogic(
new MockRace( new MockRace(
boatDataSource, boatDataSource,

@ -1,5 +1,6 @@
package mock.model; package mock.model;
import mock.model.wind.WindGenerator;
import javafx.animation.AnimationTimer; import javafx.animation.AnimationTimer;
import mock.model.collider.ColliderRegistry; import mock.model.collider.ColliderRegistry;
import mock.xml.*; import mock.xml.*;

@ -1,11 +1,9 @@
package mock.model; package mock.model.wind;
import shared.model.Bearing; import shared.model.Bearing;
import shared.model.Wind; import shared.model.Wind;
import java.util.Random;
/** /**
* This class generates Wind objects for use in a MockRace. * This class generates Wind objects for use in a MockRace.
* Initialised with a baseline wind speed and direction, and keeps it constant. * Initialised with a baseline wind speed and direction, and keeps it constant.

@ -1,4 +1,4 @@
package mock.model; package mock.model.wind;
import shared.model.Bearing; import shared.model.Bearing;

@ -0,0 +1,152 @@
package mock.model.wind;
import shared.model.Bearing;
import shared.model.Wind;
import java.util.Random;
public class ShiftingWindGenerator implements WindGenerator {
private Bearing baselineBearing;
private double baseLineSpeed;
private double windSpeedVariance = 5;
private double bearingVariance = 5; // In degrees
private double oscillationVariance = 0.25;
private double oscillationPeriod = 1e3 * 60 * 1; // In milliseconds
private double shiftTime = 1e3 * 60;
private double shiftedSoFar = 0;
private double timeOfLastOscillationReset = 0;
private double timeOfLastChange = 0;
private double timeOfLastShift = 0; // Back / veer
private boolean anticlockwise = false;
private boolean shiftAnticlockwise = false;//true for Back, false for veer
private boolean shiftThisRace = Math.random() > 0.5;
/**
* Constructor
* @param baselineBearing baseline bearing for wind
* @param baseLineSpeed base line speed for wind
*/
public ShiftingWindGenerator(Bearing baselineBearing, double baseLineSpeed) {
this.baselineBearing = baselineBearing;
this.baseLineSpeed = baseLineSpeed;
initialiseOscillationDirection();
}
@Override
public Wind generateBaselineWind() {
return new Wind(baselineBearing, baseLineSpeed);
}
@Override
public Wind generateNextWind(Wind currentWind) {
return changeWind(currentWind);
}
/**
* @param wind the wind to change
* @return the changed wind
*/
private Wind changeWind(Wind wind) {
Wind newWind = new Wind(wind.getWindDirection(), wind.getWindSpeed());
oscillateWind(newWind);
if (shiftThisRace){shiftWind(newWind);}
changeWindSpeed(newWind);
timeOfLastChange = System.currentTimeMillis();
return newWind;
}
/**
* moves the wind 5 degrees up and down
* @param wind the wind to oscillate
*/
private void oscillateWind(Wind wind) {
double timeSinceLastOscillationReset = System.currentTimeMillis() - timeOfLastOscillationReset;
double timeSinceLastChange = System.currentTimeMillis() - timeOfLastChange;
double newBearing = wind.getWindDirection().degrees();
double degreeChange = timeSinceLastChange * 2 * bearingVariance / oscillationPeriod;
degreeChange = (1 - oscillationVariance) * degreeChange + (2 * oscillationVariance) * degreeChange * Math.random();
if (timeSinceLastOscillationReset >= oscillationPeriod) {
timeOfLastOscillationReset = System.currentTimeMillis();
anticlockwise = !anticlockwise;
}
if (anticlockwise) {
newBearing -= degreeChange;
if (newBearing < baselineBearing.degrees() - bearingVariance) {
anticlockwise = !anticlockwise;
timeOfLastOscillationReset = System.currentTimeMillis();
} else {
wind.setWindDirection(Bearing.fromDegrees(newBearing % 360));
}
} else {
newBearing += degreeChange;
if (newBearing > baselineBearing.degrees() + bearingVariance) {
anticlockwise = !anticlockwise;
timeOfLastOscillationReset = System.currentTimeMillis();
} else {
wind.setWindDirection(Bearing.fromDegrees(newBearing % 360));
}
}
}
/**
* Slowly shifts the wind up to 180 degrees from where it started
* @param wind the wind to change
*/
private void shiftWind(Wind wind) {
double timeSinceLastShift = System.currentTimeMillis() - timeOfLastShift;
double newBearing = wind.getWindDirection().degrees();
double degreeChange = 7;
if (timeSinceLastShift >= shiftTime){
shiftedSoFar += degreeChange;
if (shiftedSoFar >= 180){
shiftAnticlockwise = Math.random() > 0.5;
shiftedSoFar = 0;
System.out.println("Swapping");
}
timeOfLastShift = System.currentTimeMillis();
if (shiftAnticlockwise){
newBearing -= degreeChange;
wind.setWindDirection(Bearing.fromDegrees(newBearing % 360));
} else {
newBearing += degreeChange;
wind.setWindDirection(Bearing.fromDegrees(newBearing % 360));
}
}
}
/**
* Change the wind speed
* @param wind the wind to change
*/
private void changeWindSpeed(Wind wind) {
double offsetAngle = (wind.getWindDirection().radians() - baselineBearing.radians());
double offset = Math.sin(offsetAngle) * windSpeedVariance;
double newWindSpeed = baseLineSpeed + offset;
wind.setWindSpeed(newWindSpeed);
}
/**
* starts the wind oscillation direction
*/
private void initialiseOscillationDirection() {
anticlockwise = new Random().nextBoolean();
timeOfLastOscillationReset = System.currentTimeMillis();
}
public void setBearingVariance(double maxBearingVariance) {
this.bearingVariance = maxBearingVariance;
}
public void setWindSpeedVariance(double windSpeedVariance) {
this.windSpeedVariance = windSpeedVariance;
}
public void setOscillationPeriod(double oscillationPeriod) {
this.oscillationPeriod = oscillationPeriod;
}
}

@ -1,4 +1,4 @@
package mock.model; package mock.model.wind;
import shared.model.Wind; import shared.model.Wind;

@ -48,4 +48,11 @@ public class Wind {
return windSpeed; return windSpeed;
} }
public void setWindSpeed(double windSpeed) {
this.windSpeed = windSpeed;
}
public void setWindDirection(Bearing windDirection) {
this.windDirection = windDirection;
}
} }

@ -3,7 +3,6 @@ package visualiser.Controllers;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import visualiser.app.App;
import visualiser.gameController.ControllerClient; import visualiser.gameController.ControllerClient;
import visualiser.model.VisualiserBoat; import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRaceEvent; import visualiser.model.VisualiserRaceEvent;
@ -40,6 +39,7 @@ public class MainController extends Controller {
* Transitions from the StartController screen (displays pre-race information) to the RaceController (displays the actual race). * Transitions from the StartController screen (displays pre-race information) to the RaceController (displays the actual race).
* @param visualiserRace The object modelling the race. * @param visualiserRace The object modelling the race.
* @param controllerClient Socket Client that manipulates the controller. * @param controllerClient Socket Client that manipulates the controller.
* @param isHost if the client is the host of a race or not.
*/ */
public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) { public void beginRace(VisualiserRaceEvent visualiserRace, ControllerClient controllerClient, Boolean isHost) {
raceController.startRace(visualiserRace, controllerClient, isHost); raceController.startRace(visualiserRace, controllerClient, isHost);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

@ -1,5 +1,7 @@
package mock.model; package mock.model;
import mock.model.wind.ConstantWindGenerator;
import mock.model.wind.WindGenerator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import shared.model.Bearing; import shared.model.Bearing;

@ -1,7 +1,8 @@
package mock.model; package mock.model;
import mock.dataInput.PolarParserTest; import mock.dataInput.PolarParserTest;
import network.Messages.LatestMessages; import mock.model.wind.ConstantWindGenerator;
import mock.model.wind.WindGenerator;
import shared.dataInput.*; import shared.dataInput.*;
import shared.exceptions.InvalidBoatDataException; import shared.exceptions.InvalidBoatDataException;
import shared.exceptions.InvalidRaceDataException; import shared.exceptions.InvalidRaceDataException;
@ -9,8 +10,6 @@ import shared.exceptions.InvalidRegattaDataException;
import shared.model.Bearing; import shared.model.Bearing;
import shared.model.Constants; import shared.model.Constants;
import static org.junit.Assert.*;
public class MockRaceTest { public class MockRaceTest {
//TODO //TODO

@ -1,5 +1,6 @@
package mock.model; package mock.model;
import mock.model.wind.RandomWindGenerator;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import shared.model.Bearing; import shared.model.Bearing;

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.8.0_111" class="java.beans.XMLDecoder">
<object class="java.util.HashMap">
<void method="put">
<string>SPACE</string>
<object class="visualiser.gameController.Keys.VMGKey"/>
</void>
<void method="put">
<string>SHIFT</string>
<object class="visualiser.gameController.Keys.SailsToggleKey"/>
</void>
<void method="put">
<string>DOWN</string>
<object class="visualiser.gameController.Keys.DownWindKey"/>
</void>
<void method="put">
<string>X</string>
<object class="visualiser.gameController.Keys.ZoomOutKey"/>
</void>
<void method="put">
<string>ENTER</string>
<object class="visualiser.gameController.Keys.TackGybeKey"/>
</void>
<void method="put">
<string>Z</string>
<object class="visualiser.gameController.Keys.ZoomInKey"/>
</void>
<void method="put">
<string>UP</string>
<object class="visualiser.gameController.Keys.UpWindKey"/>
</void>
</object>
</java>
Loading…
Cancel
Save