mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 06:18:44 +00:00
b5076bc976
Added a hack to bumper so that the collision distance is larger than the regular collision distance Wind walker now makes you go at you max speed rather than VMG speed #story[1293]
215 lines
7.4 KiB
Java
215 lines
7.4 KiB
Java
package seng302.model;
|
|
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.Map;
|
|
|
|
/**
|
|
* A static class for parsing and storing the polars. Will parse the whole polar table and also store the optimised
|
|
* upwind and downwind in separate tables here as well
|
|
* Created by wmu16 on 22/05/17.
|
|
*/
|
|
public final class PolarTable {
|
|
|
|
//A Polar table will consist of a wind speed key to a hashmap value of pairs of wind angles and boat speeds
|
|
private static HashMap<Double, HashMap<Double, Double>> polarTable;
|
|
private static HashMap<Double, HashMap<Double, Double>> upwindOptimal;
|
|
private static HashMap<Double, HashMap<Double, Double>> downwindOptimal;
|
|
private static Double optimalAngle;
|
|
|
|
private static int upTwaIndex;
|
|
private static int dnTwaIndex;
|
|
|
|
|
|
/**
|
|
* Iterates through each row of the polar table, in pairs, to extract the row into a hashmap of angle to boat speed.
|
|
* These angle boatspeed hashmaps are then added to an outer hashmap at the end of wind speed key to each row hashmap
|
|
* as a value
|
|
* @param polarFile polarFile to be parsed
|
|
*/
|
|
public static void parsePolarFile(InputStream polarFile) {
|
|
polarTable = new HashMap<>();
|
|
upwindOptimal = new HashMap<>();
|
|
downwindOptimal = new HashMap<>();
|
|
|
|
String line = null;
|
|
String check;
|
|
Boolean isHeaderLine = true;
|
|
|
|
try (BufferedReader br = new BufferedReader(new InputStreamReader(polarFile))) {
|
|
while ((check = br.readLine()) != null) {
|
|
line = check;
|
|
String[] thisLine = line.split(",");
|
|
|
|
//Initial line in file
|
|
if (isHeaderLine) {
|
|
deduceHeaders(thisLine);
|
|
isHeaderLine = false;
|
|
} else {
|
|
HashMap<Double, Double> thisPolar = new HashMap<>();
|
|
HashMap<Double, Double> thisUpWindPolar = new HashMap<>();
|
|
HashMap<Double, Double> thisDnWindPolar = new HashMap<>();
|
|
Double thisWindSpeed = Double.parseDouble(thisLine[0]);
|
|
|
|
// -3 <== -1 for length -1, and a further -2 as we iterate in pairs of 2 so finish before final 2
|
|
for (int i = 1; i < thisLine.length; i += 2) {
|
|
Double thisWindAngle = Double.parseDouble(thisLine[i]);
|
|
Double thisBoatSpeed = Double.parseDouble(thisLine[i + 1]);
|
|
thisPolar.put(thisWindAngle, thisBoatSpeed);
|
|
if (i == upTwaIndex) {
|
|
thisUpWindPolar.put(thisWindAngle, thisBoatSpeed);
|
|
} else if (i == dnTwaIndex) {
|
|
thisDnWindPolar.put(thisWindAngle, thisBoatSpeed);
|
|
}
|
|
}
|
|
|
|
polarTable.put(thisWindSpeed, thisPolar);
|
|
upwindOptimal.put(thisWindSpeed, thisUpWindPolar);
|
|
downwindOptimal.put(thisWindSpeed, thisDnWindPolar);
|
|
}
|
|
|
|
|
|
}
|
|
getMaxSpeedAngle(line);
|
|
|
|
} catch (IOException e) {
|
|
System.out.println("[PolarTable] IO exception");
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Passes the final line of the polar table and iterates over the speeds for each
|
|
* angle, velocity pair to find the angle that produces the highest velocity
|
|
*
|
|
* @param line The last line of the polar file
|
|
*/
|
|
private static void getMaxSpeedAngle(String line) {
|
|
String[] theLastLine = line.split(",");
|
|
Double maxWindVal = Double.parseDouble(theLastLine[0]);
|
|
Double optimalAngle = Double.parseDouble(theLastLine[1]);
|
|
Double maxSpeed = Double.parseDouble(theLastLine[2]);
|
|
for (Map.Entry<Double, Double> entry : polarTable.get(maxWindVal).entrySet()) {
|
|
if (entry.getValue() > maxSpeed) {
|
|
maxSpeed = entry.getValue();
|
|
optimalAngle = entry.getKey();
|
|
}
|
|
}
|
|
PolarTable.optimalAngle = optimalAngle;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Parses the header line of a polar file
|
|
* @param thisLine The line which is the header of a polar file
|
|
*/
|
|
private static void deduceHeaders(String[] thisLine) {
|
|
|
|
for (int i = 0; i < thisLine.length; i++) {
|
|
String thisItem = thisLine[i];
|
|
if (thisItem.toLowerCase().startsWith("uptwa")) {
|
|
upTwaIndex = i;
|
|
} else if (thisItem.toLowerCase().startsWith("dntwa")) {
|
|
dnTwaIndex = i;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
public static Double getOptimalAngle() {
|
|
return optimalAngle;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return The entire polar table
|
|
*/
|
|
public static HashMap<Double, HashMap<Double, Double>> getPolarTable() {
|
|
return polarTable;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return The polar table just containing the optimal upwind values
|
|
*/
|
|
public static HashMap<Double, HashMap<Double, Double>> getUpwindOptimal() {
|
|
return upwindOptimal;
|
|
}
|
|
|
|
|
|
/**
|
|
* @return The polar table just containing the optimal downwind values
|
|
*/
|
|
public static HashMap<Double, HashMap<Double, Double>> getDownwindOptimal() {
|
|
return downwindOptimal;
|
|
}
|
|
|
|
|
|
/**
|
|
* Will raise an exception if a polar table has just one row of data
|
|
* @param thisWindSpeed The current wind speed
|
|
* @return HashMap containing just the optimal upwind angle and resulting boat speed
|
|
*/
|
|
public static HashMap<Double, Double> getOptimalUpwindVMG(Double thisWindSpeed) {
|
|
|
|
Double polarWindSpeed = getClosestWindSpeedInPolar(thisWindSpeed);
|
|
return upwindOptimal.get(polarWindSpeed);
|
|
}
|
|
|
|
|
|
/**
|
|
* Will raise an exception if a polar table has just one row of data
|
|
* @param thisWindSpeed The current wind speed
|
|
* @return HashMap containing just the optimal downwind angle and resulting boat speed
|
|
*/
|
|
public static HashMap<Double, Double> getOptimalDownwindVMG(Double thisWindSpeed) {
|
|
|
|
Double polarWindSpeed = getClosestWindSpeedInPolar(thisWindSpeed);
|
|
return downwindOptimal.get(polarWindSpeed);
|
|
}
|
|
|
|
|
|
public static Double getBoatSpeed(Double thisWindSpeed, Double thisHeading) {
|
|
|
|
Double polarWindSpeed = getClosestWindSpeedInPolar(thisWindSpeed);
|
|
Double polarAngle = getClosestAngleInPolar(polarTable.get(polarWindSpeed), thisHeading);
|
|
|
|
return polarTable.get(polarWindSpeed).get(polarAngle);
|
|
}
|
|
|
|
|
|
public static Double getClosestWindSpeedInPolar(Double thisWindSpeed) {
|
|
Double smallestDif = Double.POSITIVE_INFINITY;
|
|
Double closestWind = 0d;
|
|
for (Double polarWindSpeed : polarTable.keySet()) {
|
|
Double difference = Math.abs(polarWindSpeed - thisWindSpeed);
|
|
if (difference < smallestDif) {
|
|
smallestDif = difference;
|
|
closestWind = polarWindSpeed;
|
|
}
|
|
}
|
|
return closestWind;
|
|
}
|
|
|
|
|
|
public static Double getClosestAngleInPolar(HashMap<Double, Double> thisWindSpeedPolar, Double thisHeading) {
|
|
Double smallestDif = Double.POSITIVE_INFINITY;
|
|
Double closestAngle = 0d;
|
|
|
|
for (Double polarAngle : thisWindSpeedPolar.keySet()) {
|
|
Double difference = Math.abs(polarAngle - thisHeading);
|
|
if (difference < smallestDif) {
|
|
smallestDif = difference;
|
|
closestAngle = polarAngle;
|
|
}
|
|
}
|
|
return closestAngle;
|
|
}
|
|
|
|
|
|
} |