avoid code duplication in certificate importers

Change-Id: Ifc44bbabf03610294a95788b82640c925c2b606b
This commit is contained in:
Axel Uhl committed 2019-09-17 16:56:31 +02:00
1 parent d687bb590b
commit ef2a2ae0b1
4 files changed
+41 -36

No files matched your search

@@ -0,0 +1,16 @@
package com.sap.sailing.domain.orc.impl;
import com.sap.sailing.domain.orc.ORCCertificateImporter;
public abstract class AbstractORCCertificateImporter implements ORCCertificateImporter {
/**
* From a sail number which may contain spaces, also redundantly and repeatedly, as well
* as dashes, slashes or other special characters, and where upper and lower case may be mixed,
* constructs a canonicalized version such that the chances for producing a match when searching
* for a sail number is maximized, while still minimizing the chances for a false match.
*/
protected String getCanonicalizedSailNumber(String sailNumber) {
return sailNumber.replaceAll(" ", "").toUpperCase();
}
}
@@ -18,7 +18,6 @@ import org.json.simple.parser.ParseException;
import com.sap.sailing.domain.common.impl.MeterDistance;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.domain.common.orc.impl.ORCCertificateImpl;
import com.sap.sailing.domain.orc.ORCCertificateImporter;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
@@ -38,9 +37,8 @@ import com.sap.sse.common.impl.SecondsDurationImpl;
* @author Daniel Lisunkin (i505543)
*
*/
public class ORCCertificateImporterJSON implements ORCCertificateImporter {
private Map<String, Object> data;
public class ORCCertificateImporterJSON extends AbstractORCCertificateImporter {
private Map<String, JSONObject> data;
private static final String RUN = "Run";
private static final String BEAT = "Beat";
private static final String WINDWARD_LEEWARD = "WL";
@@ -53,7 +51,7 @@ public class ORCCertificateImporterJSON implements ORCCertificateImporter {
* {@code .json} file.
*/
public ORCCertificateImporterJSON(InputStream in) throws IOException, ParseException {
Map<String, Object> result = new HashMap<>();
Map<String, JSONObject> result = new HashMap<>();
String defaultEncoding = "UTF-8";
BOMInputStream bomInputStream = new BOMInputStream(in);
ByteOrderMark bom = bomInputStream.getBOM();
@@ -63,7 +61,7 @@ public class ORCCertificateImporterJSON implements ORCCertificateImporter {
JSONArray dataArray = (JSONArray) parsedJson.get("rms");
for (int i = 0; i < dataArray.size(); i++) {
JSONObject object = (JSONObject) dataArray.get(i);
result.put(((String) object.get("SailNo")).replaceAll(" ", "").toUpperCase(), object);
result.put(getCanonicalizedSailNumber((String) object.get("SailNo")), object);
}
data = result;
}
@@ -83,8 +81,8 @@ public class ORCCertificateImporterJSON implements ORCCertificateImporter {
Map<Speed, Map<Bearing, Speed>> velocityPredictionPerTrueWindSpeedAndAngle = new HashMap<>();
Map<Bearing, Map<Speed, Duration>> allowanceDurationsPerTrueWindAngleAndSpeed = new HashMap<>(); //per nautical mile
Map<String, Map<Speed, Duration>> predefinedAllowanceDurationsPerTrueWindSpeed = new HashMap<>(); //per nautical mile
String searchString = sailnumber.replaceAll(" ", "").toUpperCase();
JSONObject object = (JSONObject) data.get(searchString);
String searchString = getCanonicalizedSailNumber(sailnumber);
JSONObject object = data.get(searchString);
if (object == null) {
//TODO Throw Exception for sailnumber not found. InvalidArgumentException?
return null;
@@ -6,9 +6,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
@@ -22,7 +22,6 @@ import org.apache.commons.io.input.BOMInputStream;
import com.sap.sailing.domain.common.impl.MeterDistance;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.domain.common.orc.impl.ORCCertificateImpl;
import com.sap.sailing.domain.orc.ORCCertificateImporter;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
@@ -50,7 +49,7 @@ import com.sap.sse.common.impl.SecondsDurationImpl;
*
*/
public class ORCCertificateImporterRMS implements ORCCertificateImporter {
public class ORCCertificateImporterRMS extends AbstractORCCertificateImporter {
//Codes used in the RMS document as column names for different information
private static final String TWA_COURSES = "R";
private static final String CDL = "CDL";
@@ -95,30 +94,22 @@ public class ORCCertificateImporterRMS implements ORCCertificateImporter {
String line;
while ((line = br.readLine()) != null) {
final Map<String, String> parsedLine = parseLine(line);
certificateValuesBySailnumber.put(parsedLine.get(sailnumberColumnName).replaceAll(" ", "").toUpperCase(), parsedLine);
certificateValuesBySailnumber.put(getCanonicalizedSailNumber(parsedLine.get(sailnumberColumnName)), parsedLine);
}
}
public ORCCertificateImporterRMS(InputStream in) throws IOException {
this(getReaderForInputStream(in));
}
private static BufferedReader getReaderForInputStream(InputStream in) throws IOException, UnsupportedEncodingException {
String defaultEncoding = "UTF-8";
BOMInputStream bomInputStream = new BOMInputStream(in);
ByteOrderMark bom = bomInputStream.getBOM();
String charsetName = bom == null ? defaultEncoding : bom.getCharsetName();
InputStreamReader reader = new InputStreamReader(new BufferedInputStream(bomInputStream), charsetName);
BufferedReader br = new BufferedReader(reader);
columnNamesAndWidths = readColumnWidthsFromFirstLine(br.readLine());
Iterator<String> iterator = columnNamesAndWidths.keySet().iterator();
iterator.next(); // the first column contains the IDs of the certificates
final String sailnumberColumnName = iterator.next(); // the second column contains the sail numbers, which are easier to use for identification
certificateValuesBySailnumber = new HashMap<>();
String line;
while ((line = br.readLine()) != null) {
final Map<String, String> parsedLine = parseLine(line);
certificateValuesBySailnumber.put(parsedLine.get(sailnumberColumnName).replaceAll(" ", "").toUpperCase(), parsedLine);
}
br.close();
return br;
}
private Map<String, String> parseLine(final String line) {
@@ -145,7 +136,6 @@ public class ORCCertificateImporterRMS implements ORCCertificateImporter {
splitBySpaceMode = true;
}
start = end;
}
return result;
}
@@ -171,13 +161,13 @@ public class ORCCertificateImporterRMS implements ORCCertificateImporter {
}
public ORCCertificateValues getValuesForSailnumber(String sailnumber) {
String searchString = sailnumber.replaceAll(" ", "").toUpperCase();
String searchString = getCanonicalizedSailNumber(sailnumber);
return certificateValuesBySailnumber.containsKey(searchString) ? new ORCCertificateValues(searchString) : null;
}
@Override
public ORCCertificate getCertificate(String sailnumber) {
String searchString = sailnumber.replaceAll(" ", "").toUpperCase();
String searchString = getCanonicalizedSailNumber(sailnumber);
ORCCertificateValues certificateValues = getValuesForSailnumber(searchString);
final String boatclass = certificateValues.getValue(BOATCLASS);
final Distance length = new MeterDistance(Double.parseDouble(certificateValues.getValue(LENGTH)));
@@ -194,7 +184,6 @@ public class ORCCertificateImporterRMS implements ORCCertificateImporter {
final Map<Speed, Speed> longDistanceSpeedPredictionPerTrueWindSpeed = new HashMap<>();
final Map<Speed, Speed> circularRandomSpeedPredictionPerTrueWindSpeed = new HashMap<>();
final Map<Speed, Speed> nonSpinnakerSpeedPredictionPerTrueWindSpeed = new HashMap<>();
for (Speed tws : ORCCertificateImpl.ALLOWANCES_TRUE_WIND_SPEEDS) {
String windSpeed = Integer.toString((int) tws.getKnots());
String beatAngleKey = BEAT_ANGLE + windSpeed;
@@ -227,7 +216,6 @@ public class ORCCertificateImporterRMS implements ORCCertificateImporter {
}
velocityPredictionsPerTrueWindSpeedAndAngle.put(tws, velocityPredictionPerTrueWindAngle);
}
return new ORCCertificateImpl(searchString, boatclass, length, gph, cdl,
velocityPredictionsPerTrueWindSpeedAndAngle, beatAngles, beatVMGPredictionPerTrueWindSpeed,
beatAllowancePerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed,
@@ -239,7 +227,6 @@ public class ORCCertificateImporterRMS implements ORCCertificateImporter {
@Override
public Map<String, ORCCertificate> getCertificates(String[] sailnumbers) {
Map<String, ORCCertificate> result = new HashMap<>();
for (String sailnumber : sailnumbers) {
result.put(sailnumber, getCertificate(sailnumber));
}
@@ -532,11 +532,15 @@ public class ORCPerformanceCurveRankingMetric extends AbstractRankingMetric {
try {
timeForCompetitorImpliedWindCalculation = nowOrLegFinishTimeIfFinishedAtTimePoint(trackedLegOfCompetitor, timePoint, cache);
final ORCPerformanceCurve competitorPerformanceCurveForLeg = getPerformanceCurveForPartialCourse(competitor, timeForCompetitorImpliedWindCalculation, cache);
final TimePoint timeForLegLeaderImpliedWindCalculation = nowOrLegFinishTimeIfFinishedAtTimePoint(
getTrackedRace().getTrackedLeg(legLeader, trackedLegOfCompetitor.getLeg()), timePoint, cache);
final Speed legLeaderImpliedWindInOrAtEndOfLeg = getImpliedWind(legLeader, timeForLegLeaderImpliedWindCalculation, cache);
final Duration correctedTimeOfLegLeaderInCompetitorsPerformanceCurve = competitorPerformanceCurveForLeg.getAllowancePerCourse(legLeaderImpliedWindInOrAtEndOfLeg);
result = actualRaceDurationForCompetitor.minus(correctedTimeOfLegLeaderInCompetitorsPerformanceCurve);
if (competitorPerformanceCurveForLeg == null) {
result = null;
} else {
final TimePoint timeForLegLeaderImpliedWindCalculation = nowOrLegFinishTimeIfFinishedAtTimePoint(
getTrackedRace().getTrackedLeg(legLeader, trackedLegOfCompetitor.getLeg()), timePoint, cache);
final Speed legLeaderImpliedWindInOrAtEndOfLeg = getImpliedWind(legLeader, timeForLegLeaderImpliedWindCalculation, cache);
final Duration correctedTimeOfLegLeaderInCompetitorsPerformanceCurve = competitorPerformanceCurveForLeg.getAllowancePerCourse(legLeaderImpliedWindInOrAtEndOfLeg);
result = actualRaceDurationForCompetitor.minus(correctedTimeOfLegLeaderInCompetitorsPerformanceCurve);
}
} catch (FunctionEvaluationException | MaxIterationsExceededException e) {
logger.log(Level.WARNING, "Problem with performance curve calculation for competitor "+competitor+" or "+legLeader, e);
result = null;