Created a random place token generator.

Generates a location between any leg of the race in a random angle / distance of the radius of the centre point of the two gates to one of the gates

#story[1293]
This commit is contained in:
William Muir
2017-09-27 01:44:01 +13:00
parent 330ccd272d
commit 6d51ea3574
4 changed files with 97 additions and 41 deletions
+10 -37
View File
@@ -4,6 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Random; import java.util.Random;
@@ -38,6 +39,7 @@ import seng302.model.mark.MarkOrder;
import seng302.model.token.Token; import seng302.model.token.Token;
import seng302.model.token.TokenType; import seng302.model.token.TokenType;
import seng302.utilities.GeoUtility; import seng302.utilities.GeoUtility;
import seng302.utilities.RandomSpawn;
import seng302.utilities.XMLParser; import seng302.utilities.XMLParser;
import seng302.visualiser.fxObjects.assets_3D.BoatMeshType; import seng302.visualiser.fxObjects.assets_3D.BoatMeshType;
@@ -82,7 +84,7 @@ public class GameState implements Runnable {
public static final Integer HANDLING_BOOST_MULTIPLIER = 2; public static final Integer HANDLING_BOOST_MULTIPLIER = 2;
private static final Double BAD_RANDOM_SPEED_PENALTY = 0.3; private static final Double BAD_RANDOM_SPEED_PENALTY = 0.3;
public static final Long BUMPER_DISABLE_TIME = 5_000L; public static final Long BUMPER_DISABLE_TIME = 5_000L;
private static final Long TOKEN_SPAWN_TIME = 30_000L; private static final Long TOKEN_SPAWN_TIME = 15_000L;
private static Long previousUpdateTime; private static Long previousUpdateTime;
public static Double windDirection; public static Double windDirection;
@@ -99,13 +101,12 @@ public class GameState implements Runnable {
private static GameStages currentStage; private static GameStages currentStage;
private static MarkOrder markOrder; private static MarkOrder markOrder;
private static long startTime; private static long startTime;
private static Set<Mark> marks; private static List<Mark> marks;
private static List<Limit> courseLimit; private static List<Limit> courseLimit;
private static Integer maxPlayers = 8; private static Integer maxPlayers = 8;
private static List<Token> allTokens;
private static List<Token> tokensInPlay; private static List<Token> tokensInPlay;
private static RandomSpawn randomSpawn;
private static List<NewMessageListener> newMessageListeners; private static List<NewMessageListener> newMessageListeners;
@@ -126,14 +127,12 @@ public class GameState implements Runnable {
previousUpdateTime = System.currentTimeMillis(); previousUpdateTime = System.currentTimeMillis();
markOrder = new MarkOrder(); //This could be instantiated at some point with a select map? markOrder = new MarkOrder(); //This could be instantiated at some point with a select map?
newMessageListeners = new ArrayList<>(); newMessageListeners = new ArrayList<>();
allTokens = makeTokens(); marks = new MarkOrder().getAllMarks();
randomSpawn = new RandomSpawn(markOrder.getOrderedUniqueCompoundMarks());
resetStartTime(); resetStartTime();
new Thread(this, "GameState").start(); //Run the auto updates on the game state
marks = new MarkOrder().getAllMarks();
setCourseLimit("/server_config/race.xml"); setCourseLimit("/server_config/race.xml");
new Thread(this, "GameState").start(); //Run the auto updates on the game state
} }
private void setCourseLimit(String url) { private void setCourseLimit(String url) {
@@ -151,29 +150,10 @@ public class GameState implements Runnable {
courseLimit = XMLParser.parseRace(document).getCourseLimit(); courseLimit = XMLParser.parseRace(document).getCourseLimit();
} }
/**
* Make a pre defined set of tokensInPlay. //TODO wmu16 - Should read from some file for each
* race ideally
*
* @return A list of possible tokensInPlay for this race
*/
private ArrayList<Token> makeTokens() {
Token token1 = new Token(TokenType.BOOST, 57.66946, 11.83154);
Token token2 = new Token(TokenType.BOOST, 57.66877, 11.83382);
Token token3 = new Token(TokenType.BOOST, 57.66914, 11.83965);
Token token4 = new Token(TokenType.BOOST, 57.66684, 11.83214);
return new ArrayList<>(Arrays.asList(token1, token2, token3, token4));
}
public static String getHostIpAddress() { public static String getHostIpAddress() {
return hostIpAddress; return hostIpAddress;
} }
public static Set<Mark> getMarks() {
return Collections.unmodifiableSet(marks);
}
public static List<Player> getPlayers() { public static List<Player> getPlayers() {
return players; return players;
} }
@@ -378,16 +358,9 @@ public class GameState implements Runnable {
* Broadasts a new race status message to show this update * Broadasts a new race status message to show this update
*/ */
private void spawnNewToken() { private void spawnNewToken() {
Random random = new Random();
tokensInPlay.clear(); tokensInPlay.clear();
Token token = randomSpawn.getRandomTokenLocation();
//Get a random token location with random type
Token token = allTokens.get(random.nextInt(allTokens.size()));
token.assignRandomType();
// token.assignType(TokenType.RANDOM);
logger.debug("Spawned token of type " + token.getTokenType()); logger.debug("Spawned token of type " + token.getTokenType());
tokensInPlay.add(token); tokensInPlay.add(token);
} }
@@ -912,7 +885,7 @@ public class GameState implements Runnable {
} }
private static Mark checkMarkCollision(ServerYacht yacht) { private static Mark checkMarkCollision(ServerYacht yacht) {
Set<Mark> marksInRace = GameState.getMarks(); Set<Mark> marksInRace = new HashSet<>(marks);
for (Mark mark : marksInRace) { for (Mark mark : marksInRace) {
if (GeoUtility.getDistance(yacht.getLocation(), mark) if (GeoUtility.getDistance(yacht.getLocation(), mark)
<= MARK_COLLISION_DISTANCE) { <= MARK_COLLISION_DISTANCE) {
@@ -24,8 +24,9 @@ import java.util.*;
*/ */
public class MarkOrder { public class MarkOrder {
private List<CompoundMark> raceMarkOrder; private List<CompoundMark> raceMarkOrder;
private List<CompoundMark> orderedUniqueCompoundMarks;
private Logger logger = LoggerFactory.getLogger(MarkOrder.class); private Logger logger = LoggerFactory.getLogger(MarkOrder.class);
private Set<Mark> allMarks; private List<Mark> allMarks;
public MarkOrder(){ public MarkOrder(){
loadRaceProperties(); loadRaceProperties();
@@ -44,6 +45,10 @@ public class MarkOrder {
return Collections.unmodifiableList(raceMarkOrder); return Collections.unmodifiableList(raceMarkOrder);
} }
public List<CompoundMark> getOrderedUniqueCompoundMarks() {
return orderedUniqueCompoundMarks;
}
/** /**
* @param seqID The seqID of the current mark the boat is heading to * @param seqID The seqID of the current mark the boat is heading to
* @return A Boolean indicating if this coming mark is the last one (finish line) * @return A Boolean indicating if this coming mark is the last one (finish line)
@@ -75,8 +80,8 @@ public class MarkOrder {
return raceMarkOrder.get(currentSeqID + 1); return raceMarkOrder.get(currentSeqID + 1);
} }
public Set<Mark> getAllMarks(){ public List<Mark> getAllMarks() {
return Collections.unmodifiableSet(allMarks); return Collections.unmodifiableList(allMarks);
} }
/** /**
@@ -89,7 +94,7 @@ public class MarkOrder {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db; DocumentBuilder db;
Document doc; Document doc;
allMarks = new HashSet<>(); allMarks = new ArrayList<>();
try { try {
db = dbf.newDocumentBuilder(); db = dbf.newDocumentBuilder();
@@ -105,6 +110,7 @@ public class MarkOrder {
logger.debug("Loaded RaceXML for mark order"); logger.debug("Loaded RaceXML for mark order");
List<Corner> corners = data.getMarkSequence(); List<Corner> corners = data.getMarkSequence();
Map<Integer, CompoundMark> marks = data.getCompoundMarks(); Map<Integer, CompoundMark> marks = data.getCompoundMarks();
orderedUniqueCompoundMarks = new ArrayList<>(marks.values());
List<CompoundMark> course = new ArrayList<>(); List<CompoundMark> course = new ArrayList<>();
for (Corner corner : corners){ for (Corner corner : corners){
CompoundMark compoundMark = marks.get(corner.getCompoundMarkID()); CompoundMark compoundMark = marks.get(corner.getCompoundMarkID());
@@ -15,11 +15,24 @@ public class Token extends GeoPoint {
private TokenType tokenType; private TokenType tokenType;
private Random random = new Random(); private Random random = new Random();
//Constructor for creating a specific type client side
public Token(TokenType tokenType, double lat, double lng) { public Token(TokenType tokenType, double lat, double lng) {
super(lat, lng); super(lat, lng);
this.tokenType = tokenType; this.tokenType = tokenType;
} }
//Making random type server side
public Token(double lat, double lng) {
super(lat, lng);
assignRandomType();
}
//Making random type server side
public Token(GeoPoint geoPoint) {
super(geoPoint.getLat(), geoPoint.getLng());
assignRandomType();
}
public TokenType getTokenType() { public TokenType getTokenType() {
return tokenType; return tokenType;
} }
@@ -0,0 +1,64 @@
package seng302.utilities;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import seng302.model.GeoPoint;
import seng302.model.mark.CompoundMark;
import seng302.model.token.Token;
/**
* A class for generating and spawning tokens in random locations
* Created by wmu16 on 27/09/17.
*/
public class RandomSpawn {
private static final Integer DEGREES_IN_CIRCLE = 360;
private HashMap<GeoPoint, Double> spawnRadii;
private Random random;
/**
* @param markOrder this must be the ORDERED list of marks. Better yet UNIQUE to avoid over
* computation
*/
public RandomSpawn(List<CompoundMark> markOrder) {
this.spawnRadii = new HashMap<>();
random = new Random();
spawnRadii = generateSpawnRadii(markOrder);
}
private HashMap<GeoPoint, Double> generateSpawnRadii(List<CompoundMark> markOrder) {
System.out.println(markOrder);
HashMap<GeoPoint, Double> spawnRadii = new HashMap<>();
for (int i = 0; i < markOrder.size() - 1; i++) {
GeoPoint spawnCentre = GeoUtility.getDirtyMidPoint(
markOrder.get(i).getMidPoint(),
markOrder.get(i + 1).getMidPoint());
Double distance = GeoUtility.getDistance(spawnCentre, markOrder.get(i).getMidPoint());
spawnRadii.put(spawnCentre, distance);
}
return spawnRadii;
}
/**
* @return A random token type at a random location in a random radii of the set of possible
* radii
*/
public Token getRandomTokenLocation() {
Object[] keys = spawnRadii.keySet().toArray();
GeoPoint randomSpawnCentre = (GeoPoint) keys[random.nextInt(keys.length)];
Double spawnRadius = spawnRadii.get(randomSpawnCentre);
Double randomDistance = spawnRadius * random.nextDouble();
Double randomAngle = random.nextDouble() * DEGREES_IN_CIRCLE;
GeoPoint randomLocation = GeoUtility
.getGeoCoordinate(randomSpawnCentre, randomAngle, randomDistance);
return new Token(randomLocation);
}
}