mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-11-10 21:02:40 +00:00
use RefNo as ID for ORC certificates; distinguish valid/invalid in certificate search
This commit is contained in:
1 parent
b0ecf94880
commit
ffc00ddbf0
18 files changed
+322
-151
No files matched your search
+32
-7
@@ -5,10 +5,12 @@ import java.util.Map;
|
||||
|
||||
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.CountryCode;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
import com.sap.sse.common.WithID;
|
||||
import com.sap.sse.common.impl.DegreeBearingImpl;
|
||||
|
||||
@@ -24,10 +26,9 @@ import com.sap.sse.common.impl.DegreeBearingImpl;
|
||||
* {@link RankingMetric}.
|
||||
* <p>
|
||||
*
|
||||
* The {@link WithID} interface is to be implemented such that a {@link String} is produced as the ID that contains the
|
||||
* concatenation (without intermediate white space) of the {@code NatAuth}, the {@code CertNo} and the {@code BIN}
|
||||
* fields, as provided as single fields in the JSON representation, and as provided in the concatenated form in the
|
||||
* {@code NATCERTN.FILE_ID} column in the RMS format.
|
||||
* The {@link WithID} interface is to be implemented based on the {@link #getReferenceNumber()} which is unique across the
|
||||
* ORC world-wide certificate database. Note that the {@link #getBoatKey()} consisting of the {@link #getFileId()} and the
|
||||
* {@link #getIssuingCountry()} field values is a unique key for the boat to which the certificate belongs.
|
||||
* <p>
|
||||
*
|
||||
* The certificate contains time allowances (or, conversely, speed predictions) for a combination of true wind speeds
|
||||
@@ -64,14 +65,38 @@ public interface ORCCertificate extends WithID, Serializable {
|
||||
Bearing[] ALLOWANCES_TRUE_WIND_ANGLES = { new DegreeBearingImpl(52), new DegreeBearingImpl(60),
|
||||
new DegreeBearingImpl(75), new DegreeBearingImpl(90), new DegreeBearingImpl(110),
|
||||
new DegreeBearingImpl(120), new DegreeBearingImpl(135), new DegreeBearingImpl(150) };
|
||||
|
||||
/**
|
||||
* As the ID of an ORC certificate we use the concatenation (without intermediate white space) of the
|
||||
* {@code NatAuth}, the {@code CertNo} and the {@code BIN} fields, as provided as single fields in the JSON
|
||||
* representation
|
||||
* We use the {@link #getReferenceNumber() reference number ("RefNo")} as the ID of a certificate document.
|
||||
* It is unique for all of ORC's certificates issued world-wide.
|
||||
*/
|
||||
@Override
|
||||
String getId();
|
||||
|
||||
String getReferenceNumber();
|
||||
|
||||
/**
|
||||
* Technically, at ORC a certificate's boat is identified by a "file ID" as returned by this method, together
|
||||
* with the {@link #getIssuingCountry() issuing country} which together makes this a unique boat key. For each
|
||||
* such boat key there is at most one valid certificate at a time.
|
||||
*/
|
||||
String getFileId();
|
||||
|
||||
/**
|
||||
* The country whose authority issued this certificate. Together with the {@link #getFileId() file ID} this makes for a
|
||||
* unique key of the boat to which this certifiate belongs.
|
||||
*/
|
||||
CountryCode getIssuingCountry();
|
||||
|
||||
/**
|
||||
* A unique key of the boat to which this certificate belongs; it consists of the {@link #getFileId() file ID} and the
|
||||
* {@link #getIssuingCountry() issuing country}. For any such key the ORC database delivers at most one valid certificate
|
||||
* at any given time.
|
||||
*/
|
||||
default Pair<String, CountryCode> getBoatKey() {
|
||||
return new Pair<>(getFileId(), getIssuingCountry());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sailnumber of the {@link Competitor} which this certificate belongs to.
|
||||
*
|
||||
|
||||
+39
-15
@@ -6,6 +6,7 @@ import java.util.Map;
|
||||
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
|
||||
import com.sap.sailing.domain.common.orc.ORCCertificate;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.CountryCode;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
@@ -24,7 +25,7 @@ import com.sap.sse.common.Util;
|
||||
public class ORCCertificateImpl implements ORCCertificate {
|
||||
private static final long serialVersionUID = 8725162998514202782L;
|
||||
|
||||
private final String idConsistingOfNatAuthCertNoAndBIN;
|
||||
private final String referenceNumber;
|
||||
|
||||
public final static Distance NAUTICAL_MILE = new NauticalMileDistance(1);
|
||||
|
||||
@@ -35,7 +36,9 @@ public class ORCCertificateImpl implements ORCCertificate {
|
||||
private final Duration gph;
|
||||
private final Double cdl;
|
||||
private final TimePoint issueDate;
|
||||
|
||||
private final String fileId;
|
||||
private final CountryCode issuingCountry;
|
||||
|
||||
/**
|
||||
* The "core" of the certificate for performance curve scoring; the values in the map tell how fast the boat
|
||||
* described by this certificate is expected to sail for the true wind speed (TWS) provided by the key, and the true
|
||||
@@ -111,11 +114,13 @@ public class ORCCertificateImpl implements ORCCertificate {
|
||||
* {@link ORCCertificate#ALLOWANCES_TRUE_WIND_ANGLES}.
|
||||
*/
|
||||
public ORCCertificateImpl(Speed[] allowancesTrueWindSpeeds, Bearing[] allowancesTrueWindAngles,
|
||||
String idConsistingOfNatAuthCertNoAndBIN, String sailnumber, String boatName, String boatClassName,
|
||||
Distance length, Duration gph, Double cdl, TimePoint issueDate,
|
||||
String referenceNumber, String fileId, String sailnumber, String boatName,
|
||||
String boatClassName, Distance length, Duration gph, Double cdl,
|
||||
TimePoint issueDate, CountryCode issuingCountry,
|
||||
Map<Speed, Map<Bearing, Speed>> velocityPredictionsPerTrueWindSpeedAndAngle, Map<Speed, Bearing> beatAngles,
|
||||
Map<Speed, Speed> beatVMGPredictionPerTrueWindSpeed, Map<Speed, Duration> beatAllowancePerTrueWindSpeed,
|
||||
Map<Speed, Bearing> runAngles, Map<Speed, Speed> runVMGPredictionPerTrueWindSpeed,
|
||||
Map<Speed, Bearing> runAngles,
|
||||
Map<Speed, Speed> runVMGPredictionPerTrueWindSpeed,
|
||||
Map<Speed, Duration> runAllowancePerTrueWindSpeed,
|
||||
Map<Speed, Speed> windwardLeewardSpeedPredictionsPerTrueWindSpeed,
|
||||
Map<Speed, Speed> longDistanceSpeedPredictionsPerTrueWindSpeed,
|
||||
@@ -123,7 +128,9 @@ public class ORCCertificateImpl implements ORCCertificate {
|
||||
Map<Speed, Speed> nonSpinnakerSpeedPredictionsPerTrueWindSpeed) {
|
||||
this.allowancesTrueWindAngles = allowancesTrueWindAngles;
|
||||
this.allowancesTrueWindSpeeds = allowancesTrueWindSpeeds;
|
||||
this.idConsistingOfNatAuthCertNoAndBIN = idConsistingOfNatAuthCertNoAndBIN;
|
||||
this.referenceNumber = referenceNumber;
|
||||
this.fileId = fileId;
|
||||
this.issuingCountry = issuingCountry;
|
||||
this.sailNumber = sailnumber;
|
||||
this.boatName = boatName;
|
||||
this.boatClassName = boatClassName;
|
||||
@@ -150,21 +157,23 @@ public class ORCCertificateImpl implements ORCCertificate {
|
||||
* {@link ORCCertificate#ALLOWANCES_TRUE_WIND_ANGLES}, respectively, for the matrix of time allowances
|
||||
* or, conversely, the speed predictions.
|
||||
*/
|
||||
public ORCCertificateImpl(String idConsistingOfNatAuthCertNoAndBIN,
|
||||
String sailnumber, String boatName, String boatClassName,
|
||||
Distance length, Duration gph,
|
||||
Double cdl, TimePoint issueDate,
|
||||
Map<Speed, Map<Bearing, Speed>> velocityPredictionsPerTrueWindSpeedAndAngle,
|
||||
public ORCCertificateImpl(String referenceNumber,
|
||||
String fileId, String sailnumber, String boatName,
|
||||
String boatClassName, Distance length,
|
||||
Duration gph, Double cdl,
|
||||
TimePoint issueDate,
|
||||
CountryCode issuingCountry, Map<Speed, Map<Bearing, Speed>> velocityPredictionsPerTrueWindSpeedAndAngle,
|
||||
Map<Speed, Bearing> beatAngles, Map<Speed, Speed> beatVMGPredictionPerTrueWindSpeed,
|
||||
Map<Speed, Duration> beatAllowancePerTrueWindSpeed, Map<Speed, Bearing> runAngles,
|
||||
Map<Speed, Duration> beatAllowancePerTrueWindSpeed,
|
||||
Map<Speed, Bearing> runAngles,
|
||||
Map<Speed, Speed> runVMGPredictionPerTrueWindSpeed,
|
||||
Map<Speed, Duration> runAllowancePerTrueWindSpeed,
|
||||
Map<Speed, Speed> windwardLeewardSpeedPredictionsPerTrueWindSpeed,
|
||||
Map<Speed, Speed> longDistanceSpeedPredictionsPerTrueWindSpeed,
|
||||
Map<Speed, Speed> circularRandomSpeedPredictionsPerTrueWindSpeed,
|
||||
Map<Speed, Speed> nonSpinnakerSpeedPredictionsPerTrueWindSpeed) {
|
||||
this(ALLOWANCES_TRUE_WIND_SPEEDS, ALLOWANCES_TRUE_WIND_ANGLES, idConsistingOfNatAuthCertNoAndBIN, sailnumber,
|
||||
boatName, boatClassName, length, gph, cdl, issueDate, velocityPredictionsPerTrueWindSpeedAndAngle,
|
||||
this(ALLOWANCES_TRUE_WIND_SPEEDS, ALLOWANCES_TRUE_WIND_ANGLES, referenceNumber, fileId, sailnumber, boatName,
|
||||
boatClassName, length, gph, cdl, issueDate, issuingCountry, velocityPredictionsPerTrueWindSpeedAndAngle,
|
||||
beatAngles, beatVMGPredictionPerTrueWindSpeed, beatAllowancePerTrueWindSpeed, runAngles,
|
||||
runVMGPredictionPerTrueWindSpeed, runAllowancePerTrueWindSpeed,
|
||||
windwardLeewardSpeedPredictionsPerTrueWindSpeed, longDistanceSpeedPredictionsPerTrueWindSpeed,
|
||||
@@ -173,7 +182,22 @@ public class ORCCertificateImpl implements ORCCertificate {
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return idConsistingOfNatAuthCertNoAndBIN;
|
||||
return getReferenceNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReferenceNumber() {
|
||||
return referenceNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileId() {
|
||||
return fileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CountryCode getIssuingCountry() {
|
||||
return issuingCountry;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+2
-2
@@ -35,8 +35,8 @@ public abstract class AbstractORCCertificateImporterTest {
|
||||
protected void testSimpleOnlineFileRead(String rmsOrJsonFormat) throws IOException, ParseException, InterruptedException {
|
||||
Collection<ORCCertificate> certificates = customIgnoreRule.getAvailableCerts();
|
||||
final ORCCertificate cert = certificates.stream().findFirst().get();
|
||||
String countryCode = cert.getId().substring(0, 3);
|
||||
String url = String.format("https://data.orc.org/public/WPub.dll?action=DownBoatRMS&CountryId=%s&ext=%s", countryCode, rmsOrJsonFormat);
|
||||
String countryCode = cert.getIssuingCountry().getThreeLetterIOCCode();
|
||||
String url = String.format("https://data.orc.org/public/WPub.dll?action=DownRMS&CountryId=%s&ext=%s", countryCode, rmsOrJsonFormat);
|
||||
ORCCertificatesCollection importer = ORCCertificatesImporter.INSTANCE.read(new URL(url).openStream());
|
||||
ORCCertificate someValidCert = null, referenceCert = null;
|
||||
for (ORCCertificate orcCertificate : certificates) {
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ public class FailIfNoValidOrcCertificateRule implements TestRule {
|
||||
certificateExists = false;
|
||||
for (CountryCode cc : CountryCodeFactory.INSTANCE.getAll()) {
|
||||
try {
|
||||
Iterable<CertificateHandle> certificateHandles = db.search(cc, year, null, null, null, null);
|
||||
Iterable<CertificateHandle> certificateHandles = db.search(cc, year, null, null, null, null, /* includeInvalid */ false);
|
||||
Iterable<ORCCertificate> orcCertificates = db.getCertificates(certificateHandles);
|
||||
orcCertificates.forEach(availableCerts::add);
|
||||
if (orcCertificates.iterator().hasNext()) {
|
||||
|
||||
+1
-1
@@ -128,7 +128,7 @@ public class ORCPerformanceCurveRankingTest extends OnlineTracTracBasedTest {
|
||||
final Boat boat = getTrackedRace().getRace().getBoatOfCompetitor(competitor);
|
||||
ORCCertificate certificate;
|
||||
if (boat.getSailID().equals("Air is blue")) {
|
||||
certificate = certificates.getCertificateById("ITA52521I5252");
|
||||
certificate = certificates.getCertificateById("ITA00052727");
|
||||
} else {
|
||||
certificate = certificates.getCertificateById(boat.getSailID());
|
||||
if (certificate == null) {
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ public class TestORCCertificateImporterJSON extends AbstractORCCertificateImport
|
||||
|
||||
@Test
|
||||
public void testSimpleLocalJSONFileRead() throws IOException, ParseException {
|
||||
testSimpleLocalFileRead("GER2019.json", "GER166844GER7323");
|
||||
testSimpleLocalFileRead("GER2019.json", "GER20041179");
|
||||
}
|
||||
|
||||
@FailIfNoValidOrcCertificates
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ public class TestORCCertificateImporterRMS extends AbstractORCCertificateImporte
|
||||
|
||||
@Test
|
||||
public void testSimpleLocalRMSFileRead() throws IOException, ParseException {
|
||||
testSimpleLocalFileRead("GER2019.rms", "GER166844GER7323");
|
||||
testSimpleLocalFileRead("GER2019.rms", "GER20041179");
|
||||
}
|
||||
|
||||
@FailIfNoValidOrcCertificates
|
||||
|
||||
+34
-34
@@ -103,31 +103,31 @@ public class TestORCPerformanceCurve {
|
||||
|
||||
@Test
|
||||
public void testLagrangeInterpolation60() throws FunctionEvaluationException {
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER20040783");
|
||||
testAllowancePerLeg(certificate, 60.0, 498.4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLagrangeInterpolation62_5() throws FunctionEvaluationException {
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER20040783");
|
||||
testAllowancePerLeg(certificate, 62.5, 492.2, 425.0, 403.6, 393.1, 386.7, 382.6, 371.4);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLagrangeInterpolation98_3() throws FunctionEvaluationException {
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER20040783");
|
||||
testAllowancePerLeg(certificate, 98.3, 483.6, 418.7, 394.8, 377.9, 360.2, 345.0, 321.7);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLagrangeInterpolation120() throws FunctionEvaluationException {
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER20040783");
|
||||
testAllowancePerLeg(certificate, 120.0, 506);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLagrangeInterpolation138_7() throws FunctionEvaluationException {
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificate = importerLocal.getCertificateById("GER20040783");
|
||||
testAllowancePerLeg(certificate, 138.7, 588.1, 468.4, 413.8, 382.6, 355.1, 326.4, 275.4);
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public class TestORCPerformanceCurve {
|
||||
|
||||
@Test
|
||||
public void testSimpleConstructedCourse() throws FunctionEvaluationException {
|
||||
ORCCertificate certificate = (ORCCertificate) importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificate = (ORCCertificate) importerLocal.getCertificateById("GER20040783");
|
||||
List<ORCPerformanceCurveLeg> legs = new ArrayList<>();
|
||||
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(1.0), new DegreeBearingImpl(0)));
|
||||
legs.add(new ORCPerformanceCurveLegImpl(new NauticalMileDistance(1.0), new DegreeBearingImpl(30)));
|
||||
@@ -165,7 +165,7 @@ public class TestORCPerformanceCurve {
|
||||
@Test
|
||||
public void testPerformanceCurveInversion() throws MaxIterationsExceededException, FunctionEvaluationException {
|
||||
Double accuracy = 0.1;
|
||||
ORCCertificate certificate = (ORCCertificate) importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificate = (ORCCertificate) importerLocal.getCertificateById("GER20040783");
|
||||
ORCPerformanceCurveImpl performanceCurve = (ORCPerformanceCurveImpl) new ORCPerformanceCurveImpl(certificate, alturaCourse);
|
||||
testBackwardForward(accuracy, performanceCurve, 11.5);
|
||||
testBackwardForward(accuracy, performanceCurve, 17.23);
|
||||
@@ -194,12 +194,12 @@ public class TestORCPerformanceCurve {
|
||||
@Test
|
||||
public void testImpliedWind() throws MaxIterationsExceededException, FunctionEvaluationException {
|
||||
double accuracy = 0.0001;
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER166844GER7323");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER140618GER5609");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER140755GER5555");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER141411GER6300");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER141432GER5564");
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER20040783");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER20041179");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER30010194");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER20040647");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER30010167");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER20040632");
|
||||
ORCPerformanceCurve performanceCurveMoana = new ORCPerformanceCurveImpl(certificateMoana, alturaCourse);
|
||||
ORCPerformanceCurve performanceCurveMilan = new ORCPerformanceCurveImpl(certificateMilan, alturaCourse);
|
||||
ORCPerformanceCurve performanceCurveTutima = new ORCPerformanceCurveImpl(certificateTutima, alturaCourse);
|
||||
@@ -231,12 +231,12 @@ public class TestORCPerformanceCurve {
|
||||
@Test
|
||||
public void testAllowances() throws FunctionEvaluationException {
|
||||
double accuracy = 0.00001;
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER166844GER7323");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER140618GER5609");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER140755GER5555");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER141411GER6300");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER141432GER5564");
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER20040783");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER20041179");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER30010194");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER20040647");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER30010167");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER20040632");
|
||||
ORCPerformanceCurve performanceCurveMoana = new ORCPerformanceCurveImpl(certificateMoana, alturaCourse);
|
||||
ORCPerformanceCurve performanceCurveMilan = new ORCPerformanceCurveImpl(certificateMilan, alturaCourse);
|
||||
ORCPerformanceCurve performanceCurveTutima = new ORCPerformanceCurveImpl(certificateTutima, alturaCourse);
|
||||
@@ -268,7 +268,7 @@ public class TestORCPerformanceCurve {
|
||||
final double highAccuracy = 0.01;
|
||||
final double allowanceAccuracy = 0.1;
|
||||
final Distance ONE_NAUTICAL_MILE = new NauticalMileDistance(1.0);
|
||||
final ORCCertificate certificateWithSpecificBins = importerWithSpecificBins.getCertificateById("GRA00073GR317");
|
||||
final ORCCertificate certificateWithSpecificBins = importerWithSpecificBins.getCertificateById("N/A");
|
||||
for (final Bearing twa : certificateWithSpecificBins.getTrueWindAngles()) {
|
||||
final ORCPerformanceCurveCourse singleLegOneMileCourseWithTwa = createSingleLegCourseWithTwa(twa);
|
||||
final ORCPerformanceCurve performanceCurveSpecificBins = new ORCPerformanceCurveImpl(certificateWithSpecificBins, singleLegOneMileCourseWithTwa);
|
||||
@@ -299,13 +299,13 @@ public class TestORCPerformanceCurve {
|
||||
ORCPerformanceCurveCourse complexCourse = new ORCPerformanceCurveCourseImpl(list);
|
||||
|
||||
final double accuracy = 0.0001;
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER166844GER7323");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER140618GER5609");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER140755GER5555");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER141411GER6300");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER141432GER5564");
|
||||
ORCCertificate certificateWithSpecificBins=importerWithSpecificBins.getCertificateById("GRA00073GR317");
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER20040783");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER20041179");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER30010194");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER20040647");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER30010167");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER20040632");
|
||||
ORCCertificate certificateWithSpecificBins=importerWithSpecificBins.getCertificateById("N/A");
|
||||
ORCPerformanceCurve performanceCurveMoana = new ORCPerformanceCurveImpl(certificateMoana, complexCourse);
|
||||
ORCPerformanceCurve performanceCurveMilan = new ORCPerformanceCurveImpl(certificateMilan, complexCourse);
|
||||
ORCPerformanceCurve performanceCurveTutima = new ORCPerformanceCurveImpl(certificateTutima, complexCourse);
|
||||
@@ -334,13 +334,13 @@ public class TestORCPerformanceCurve {
|
||||
ORCPerformanceCurveCourse complexCourse = new ORCPerformanceCurveCourseImpl(list);
|
||||
|
||||
double accuracy = 0.00001;
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER140772GER5549");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER166844GER7323");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER140618GER5609");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER140755GER5555");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER141411GER6300");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER141432GER5564");
|
||||
ORCCertificate certificateWithSpecificBins=importerWithSpecificBins.getCertificateById("GRA00073GR317");
|
||||
ORCCertificate certificateMoana = importerLocal.getCertificateById("GER20040783");
|
||||
ORCCertificate certificateMilan = importerLocal.getCertificateById("GER20041179");
|
||||
ORCCertificate certificateTutima = importerLocal.getCertificateById("GER30010194");
|
||||
ORCCertificate certificateBank = importerLocal.getCertificateById("GER20040647");
|
||||
ORCCertificate certificateHaspa = importerLocal.getCertificateById("GER30010167");
|
||||
ORCCertificate certificateHalbtrocken = importerLocal.getCertificateById("GER20040632");
|
||||
ORCCertificate certificateWithSpecificBins=importerWithSpecificBins.getCertificateById("N/A");
|
||||
ORCPerformanceCurve performanceCurveMoana = new ORCPerformanceCurveImpl(certificateMoana, complexCourse);
|
||||
ORCPerformanceCurve performanceCurveMilan = new ORCPerformanceCurveImpl(certificateMilan, complexCourse);
|
||||
ORCPerformanceCurve performanceCurveTutima = new ORCPerformanceCurveImpl(certificateTutima, complexCourse);
|
||||
|
||||
+6
-4
@@ -2,6 +2,7 @@ package com.sap.sailing.domain.orc;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -92,7 +93,7 @@ public class TestORCPublicCertificateDatabase {
|
||||
final String referenceNumber = "FRA00013881";
|
||||
final Iterable<CertificateHandle> result = db.search(/* country */ null, /* yearOfIssuance */ null,
|
||||
/* referenceNumber */ referenceNumber, /* yachtName */ null, /* sailNumber */ null,
|
||||
/* boatClassName */ null);
|
||||
/* boatClassName */ null, /* includeInvalid */ true);
|
||||
assertEquals(1, Util.size(result));
|
||||
assertSoulmate(referenceNumber, result.iterator().next());
|
||||
}
|
||||
@@ -102,7 +103,7 @@ public class TestORCPublicCertificateDatabase {
|
||||
final String referenceNumber = "FRA00013881";
|
||||
final Iterable<CertificateHandle> result = db.search(/* country */ null, /* yearOfIssuance */ 2019,
|
||||
/* referenceNumber */ null, /* yachtName */ "Soulmate", /* sailNumber */ "DEN- 13",
|
||||
/* boatClassName */ null);
|
||||
/* boatClassName */ null, /* includeInvalid */ true);
|
||||
assertEquals(1, Util.size(result));
|
||||
assertSoulmate(referenceNumber, result.iterator().next());
|
||||
}
|
||||
@@ -112,7 +113,7 @@ public class TestORCPublicCertificateDatabase {
|
||||
final String referenceNumber = "FRA00013881";
|
||||
final Iterable<CertificateHandle> result = db.search(/* country */ null, /* yearOfIssuance */ null,
|
||||
/* referenceNumber */ null, /* yachtName */ "Soulmate", /* sailNumber */ null,
|
||||
/* boatClassName */ null);
|
||||
/* boatClassName */ null, /* includeInvalid */ true);
|
||||
assertTrue(Util.size(result)>1);
|
||||
boolean found = false;
|
||||
for (final CertificateHandle handle : result) {
|
||||
@@ -140,13 +141,14 @@ public class TestORCPublicCertificateDatabase {
|
||||
cert.getSailNumber(), /*
|
||||
* boat class name; could be set to cert.getBoatClassName() but there are
|
||||
* deviations in ORC DBs and query API, so leaving null:
|
||||
*/ null);
|
||||
*/ null, /* includeInvalid */ false);
|
||||
Optional<CertificateHandle> certificateHandle = Optional.ofNullable(certHandles.iterator().hasNext() ? certHandles.iterator().next() : null);
|
||||
assertTrue("No certificate found for handle "+certificateHandle+
|
||||
" extracted from certificates "+certificates, certificateHandle.isPresent());
|
||||
final String referenceNumber = certificateHandle.get().getReferenceNumber();
|
||||
final CertificateHandle handle = db.getCertificateHandle(referenceNumber);
|
||||
final ORCCertificate result = db.getCertificate(referenceNumber);
|
||||
assertNotNull("Unable to load certificate for reference number "+referenceNumber+" from handle "+certificateHandle);
|
||||
assertEquals(handle.getGPH(), result.getGPH().asSeconds(), 0.00001);
|
||||
// Use some tolerance as we found differences as much as 5s between the dxtDate in the handle coming from the XML search result
|
||||
// and the IssueDate field in the JSON. Both suggest to report millisecond accuracy, but dxtDate always seems to have the
|
||||
|
||||
+15
-6
@@ -17,8 +17,14 @@ import com.sap.sse.common.Util;
|
||||
/**
|
||||
* An interface to {@code data.orc.org}, mostly the search functionality at
|
||||
* {@code https://data.orc.org/public/WPub.dll?action=SrchCert&xslp=scert.php}. It can search for certificates by a
|
||||
* number of criteria, among them the issuing country, sail number, ORC reference number, or boat name.
|
||||
* <p>
|
||||
* number of criteria, among them the issuing country, sail number, ORC reference number, or boat name. Those search
|
||||
* results are represented as {@link CertificateHandle} objects. Such handles can also be obtained for certificates that
|
||||
* are not currently valid. See the {@code includeInvalid} parameter of the
|
||||
* {@link #search(CountryCode, Integer, String, String, String, String, boolean)} method. However, handles for
|
||||
* {@link CertificateHandle#isValid() invalid} certificates cannot be resolved into {@link ORCCertificate} objects
|
||||
* through {@link #getCertificates(Iterable)} or {@link #getCertificates(CertificateHandle...)} because the database
|
||||
* returns full certificates only if they are valid.
|
||||
* <p>
|
||||
*
|
||||
* As the web site emits XML documents as search results, those can be parsed and turned into handles to certificates.
|
||||
* An example output (excerpt):
|
||||
@@ -80,8 +86,8 @@ import com.sap.sse.common.Util;
|
||||
</DATA>
|
||||
* </pre>
|
||||
*
|
||||
* This also shows that some query results do not provide a valid link to a downloadable copy of the certificate. Those are
|
||||
* automatically removed from the results here.
|
||||
* This also shows that some query results do not provide a valid link to a downloadable copy of the certificate. Those
|
||||
* are automatically removed from the results here.
|
||||
*
|
||||
* @author Axel Uhl (D043530)
|
||||
*
|
||||
@@ -97,6 +103,7 @@ public interface ORCPublicCertificateDatabase {
|
||||
*/
|
||||
public interface CertificateHandle {
|
||||
CountryCode getIssuingCountry();
|
||||
String getFileId();
|
||||
Double getGPH();
|
||||
String getSSSID();
|
||||
UUID getDatInGID();
|
||||
@@ -111,6 +118,7 @@ public interface ORCPublicCertificateDatabase {
|
||||
Integer getCertType();
|
||||
Boolean isOd();
|
||||
Boolean isProvisional();
|
||||
Boolean isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,11 +126,12 @@ public interface ORCPublicCertificateDatabase {
|
||||
* results based on that criterion. You can use "%" as wildcards in the {@code yachtName}, {@code sailNumber} and
|
||||
* {@code boatClassName} parameters.
|
||||
* <p>
|
||||
* @param includeInvalid TODO
|
||||
*
|
||||
* @return an always valid, never {@code null} object which may be {@link Util#isEmpty() empty}.
|
||||
*/
|
||||
Iterable<CertificateHandle> search(CountryCode country, Integer yearOfIssuance, String referenceNumber,
|
||||
String yachtName, String sailNumber, String boatClassName) throws Exception;
|
||||
String yachtName, String sailNumber, String boatClassName, boolean includeInvalid) throws Exception;
|
||||
|
||||
default Iterable<ORCCertificate> getCertificates(Iterable<CertificateHandle> handles) throws Exception {
|
||||
return Util.map(handles, handle->{
|
||||
@@ -139,7 +148,7 @@ public interface ORCPublicCertificateDatabase {
|
||||
}
|
||||
|
||||
default CertificateHandle getCertificateHandle(String referenceNumber) throws Exception {
|
||||
return search(null, null, referenceNumber, null, null, null).iterator().next();
|
||||
return search(null, null, referenceNumber, null, null, null, /* includeInvalid */ true).iterator().next();
|
||||
}
|
||||
|
||||
ORCCertificate getCertificate(String referenceNumber) throws Exception;
|
||||
|
||||
+17
-10
@@ -21,6 +21,7 @@ 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.sse.common.Bearing;
|
||||
import com.sap.sse.common.CountryCodeFactory;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
@@ -52,16 +53,15 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec
|
||||
private static final String YACHT_NAME = "YachtName";
|
||||
private static final String LOA = "LOA";
|
||||
private static final String SAIL_NO = "SailNo";
|
||||
private static final String CERT_NO = "CertNo";
|
||||
private static final String BIN = "BIN";
|
||||
private static final String NAT_AUTH = "NatAuth";
|
||||
private static final String REFERENCE_NUMBER = "RefNo";
|
||||
private static final String RUN = "Run";
|
||||
private static final String BEAT = "Beat";
|
||||
private static final String WINDWARD_LEEWARD = "WL";
|
||||
private static final String LONG_DISTANCE = "OC";
|
||||
private static final String CIRCULAR_RANDOM = "CR";
|
||||
private static final String NON_SPINNAKER = "NS";
|
||||
private static final String EMPTY_CERT_NO = " ";
|
||||
private static final String WIND_SPEEDS = "WindSpeeds";
|
||||
|
||||
/**
|
||||
@@ -99,6 +99,9 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec
|
||||
*/
|
||||
@Override
|
||||
public ORCCertificate getCertificateById(String certificateId) {
|
||||
String refNo = null;
|
||||
String natAuth = null;
|
||||
String fileId = null;
|
||||
String boatName = null;
|
||||
String boatclass = null;
|
||||
Distance length = null;
|
||||
@@ -121,6 +124,15 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec
|
||||
String sailNumber = null;
|
||||
for (Entry<Object, Object> entry : object.entrySet()) {
|
||||
switch ((String) entry.getKey()) {
|
||||
case REFERENCE_NUMBER:
|
||||
refNo = entry.getValue() == null ? null : entry.getValue().toString();
|
||||
break;
|
||||
case NAT_AUTH:
|
||||
natAuth = entry.getValue() == null ? null : entry.getValue().toString();
|
||||
break;
|
||||
case BIN:
|
||||
fileId = entry.getValue() == null ? null : entry.getValue().toString();
|
||||
break;
|
||||
case SAIL_NO:
|
||||
sailNumber = entry.getValue() == null ? null : entry.getValue().toString();
|
||||
break;
|
||||
@@ -256,7 +268,8 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec
|
||||
Arrays.equals(ORCCertificate.ALLOWANCES_TRUE_WIND_ANGLES, dynamicAllowancesTrueWindAngles)
|
||||
? ORCCertificate.ALLOWANCES_TRUE_WIND_ANGLES
|
||||
: dynamicAllowancesTrueWindAngles,
|
||||
getId(object), sailNumber, boatName, boatclass, length, gph, cdl, issueDate,
|
||||
refNo, fileId, sailNumber, boatName, boatclass, length, gph, cdl,
|
||||
issueDate, CountryCodeFactory.INSTANCE.getFromThreeLetterIOCName(natAuth),
|
||||
velocityPredictionPerTrueWindSpeedAndAngle, beatAngles, beatVMGPredictionPerTrueWindSpeed,
|
||||
beatAllowancePerTrueWindSpeed, gybeAngles, runVMGPredictionPerTrueWindSpeed,
|
||||
runAllowancePerTrueWindSpeed, windwardLeewardSpeedPredictionPerTrueWindSpeed,
|
||||
@@ -267,13 +280,7 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec
|
||||
}
|
||||
|
||||
private String getId(JSONObject certificateAsJson) {
|
||||
return getIdFromFields(certificateAsJson.get(NAT_AUTH).toString(),
|
||||
certificateAsJson.get(CERT_NO) == null ? EMPTY_CERT_NO : certificateAsJson.get(CERT_NO).toString(),
|
||||
certificateAsJson.get(BIN).toString());
|
||||
}
|
||||
|
||||
private String getIdFromFields(final String natAuth, final String certNo, final String bin) {
|
||||
return natAuth + certNo + bin;
|
||||
return certificateAsJson.get(REFERENCE_NUMBER).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+25
-5
@@ -14,10 +14,13 @@ 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.sse.common.Bearing;
|
||||
import com.sap.sse.common.CountryCode;
|
||||
import com.sap.sse.common.CountryCodeFactory;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
import com.sap.sse.common.TimePoint;
|
||||
import com.sap.sse.common.Util.Triple;
|
||||
import com.sap.sse.common.impl.DegreeBearingImpl;
|
||||
import com.sap.sse.common.impl.MillisecondsTimePoint;
|
||||
import com.sap.sse.common.impl.SecondsDurationImpl;
|
||||
@@ -52,6 +55,7 @@ public class ORCCertificatesCollectionRMS extends AbstractORCCertificatesCollect
|
||||
private static final String SAILNUMBER = "SAILNUMB";
|
||||
private static final String BOATCLASS = "TYPE";
|
||||
static final String ISSUEDATE = "DD_MM_yyYY";
|
||||
static final String LOA = "LOA";
|
||||
private static final String ISSUETIME = "HH:MM:SS";
|
||||
private static final String RUN_ALLOWANCE = "D";
|
||||
private static final String RUN_ANGLE = "DA";
|
||||
@@ -61,7 +65,12 @@ public class ORCCertificatesCollectionRMS extends AbstractORCCertificatesCollect
|
||||
private static final String LONG_DISTANCE = "OC";
|
||||
private static final String CIRCULAR_RANDOM = "CR";
|
||||
private static final String NON_SPINNAKER = "NSP";
|
||||
private static final String NATCERTN_FILE_ID = "NATCERTN.FILE_ID";
|
||||
private static final String ISSUING_NATIONAL_AUTHORITY = "NAT";
|
||||
private static final String CERTIFICATE_NUMBER = "CERTN";
|
||||
private static final String NATCERTN = ISSUING_NATIONAL_AUTHORITY+CERTIFICATE_NUMBER;
|
||||
private static final String FILE_ID = "FILE_ID";
|
||||
private static final String NATCERTN_FILE_ID = NATCERTN+"."+FILE_ID;
|
||||
static final String REFERENCE_NUMBER = "ReferenceNo";
|
||||
private static final DateFormat timestampFormat = new SimpleDateFormat("dd MM yyyy HH:mm:ssZ");
|
||||
|
||||
/**
|
||||
@@ -108,6 +117,7 @@ public class ORCCertificatesCollectionRMS extends AbstractORCCertificatesCollect
|
||||
if (certificateValues == null) {
|
||||
result = null;
|
||||
} else {
|
||||
final String refNo = certificateValues.getValue(REFERENCE_NUMBER);
|
||||
final String sailNumber = certificateValues.getValue(SAILNUMBER);
|
||||
final String boatclass = certificateValues.getValue(BOATCLASS);
|
||||
final String boatName = certificateValues.getValue(BOATNAME);
|
||||
@@ -165,15 +175,25 @@ public class ORCCertificatesCollectionRMS extends AbstractORCCertificatesCollect
|
||||
}
|
||||
velocityPredictionsPerTrueWindSpeedAndAngle.put(tws, velocityPredictionPerTrueWindAngle);
|
||||
}
|
||||
result = new ORCCertificateImpl(certificateValues.getValue(NATCERTN_FILE_ID), sailNumber, boatName, boatclass,
|
||||
length, gph, cdl, issueDate, velocityPredictionsPerTrueWindSpeedAndAngle, beatAngles, beatVMGPredictionPerTrueWindSpeed,
|
||||
beatAllowancePerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed,
|
||||
final Triple<CountryCode, String, String> natCertNoFileId = getIssuingNationalityCertificateNumberAndFileId(certificateValues.getValue(NATCERTN_FILE_ID));
|
||||
result = new ORCCertificateImpl(refNo, natCertNoFileId.getC(), sailNumber, boatName, boatclass, length, gph,
|
||||
cdl, issueDate, natCertNoFileId.getA(), velocityPredictionsPerTrueWindSpeedAndAngle, beatAngles,
|
||||
beatVMGPredictionPerTrueWindSpeed, beatAllowancePerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed,
|
||||
runAllowancePerTrueWindSpeed, windwardLeewardSpeedPredictionPerTrueWindSpeed,
|
||||
longDistanceSpeedPredictionPerTrueWindSpeed, circularRandomSpeedPredictionPerTrueWindSpeed, nonSpinnakerSpeedPredictionPerTrueWindSpeed);
|
||||
longDistanceSpeedPredictionPerTrueWindSpeed, circularRandomSpeedPredictionPerTrueWindSpeed,
|
||||
nonSpinnakerSpeedPredictionPerTrueWindSpeed);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Triple<CountryCode, String, String> getIssuingNationalityCertificateNumberAndFileId(String natCertFileId) {
|
||||
final CountryCode nationalityIOCCode = CountryCodeFactory.INSTANCE
|
||||
.getFromThreeLetterIOCName(natCertFileId.substring(0, ISSUING_NATIONAL_AUTHORITY.length()));
|
||||
final String certNo = natCertFileId.substring(ISSUING_NATIONAL_AUTHORITY.length(), ISSUING_NATIONAL_AUTHORITY.length()+CERTIFICATE_NUMBER.length()).trim();
|
||||
final String fileId = natCertFileId.substring(NATCERTN.length()+".".length()).trim();
|
||||
return new Triple<>(nationalityIOCCode, certNo, fileId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<String> getCertificateIds() {
|
||||
return Collections.unmodifiableCollection(certificateValuesByCertificateId.keySet());
|
||||
|
||||
+75
-37
@@ -5,7 +5,6 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -13,16 +12,27 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.sap.sailing.domain.common.orc.ORCCertificate;
|
||||
import com.sap.sse.common.Util.Pair;
|
||||
|
||||
/**
|
||||
* Represents a file in format {@code .rms} which is a simple ASCII file format, column-based, with fixed-width columns,
|
||||
* defined by a header line that defines the names and for the first columns up to the column labeled
|
||||
* {@link #NAME_OF_LAST_LEFT_ALIGNED_COLUMN_HEADER} also the width of the columns. The header uses column names that do
|
||||
* not contain spaces, separated by one or more spaces. For the columns up to and including the column
|
||||
* {@link #NAME_OF_LAST_LEFT_ALIGNED_COLUMN_HEADER} the column names are formatted left-aligned. For subsequent columns
|
||||
* which contain all numeric values without spaces the column names may also be centered. For those columns parsing can
|
||||
* simply split by space characters.
|
||||
* <p>
|
||||
* Represents a file in format {@code .rms} which is a strange ASCII file format, column-based, with fixed-width columns,
|
||||
* "defined" by a header line that gives the names and for the first columns up to the column labeled
|
||||
* {@link #NAME_OF_COLUMN_HEADER_WHERE_THINGS_GET_WEIRD} also the width of the columns. Starting with the column following
|
||||
* {@link #NAME_OF_COLUMN_HEADER_WHERE_THINGS_GET_WEIRD}, field names may be "centered" over their character columns; for example,
|
||||
* the "LOA" field is represented as " LOA " with the last space marking the separating space to the next column,
|
||||
* and the values are placed somewhere within those first six "payload" columns; they may appear centered, left-aligned
|
||||
* or right-aligned, and there doesn't seem to be a recognizable pattern to it.<p>
|
||||
*
|
||||
* To make matters worse, some columns do not contain values at all. In this case, no alternation between space and non-space
|
||||
* characters can be used to determine field boundaries. At least, after the {@link #NAME_OF_COLUMN_HEADER_WHERE_THINGS_GET_WEIRD} no
|
||||
* columns can contain space characters unless they are entirely empty. And in all cases do those column values after
|
||||
* {@link #NAME_OF_COLUMN_HEADER_WHERE_THINGS_GET_WEIRD} have a non-space character in at least one of the columns used by the corresponding
|
||||
* field name in the header, unless the field value is left blank.<p>
|
||||
*
|
||||
* Therefore, a good strategy seems to look for non-space characters in the columns used for the field name in the header.
|
||||
* If none are found, the field is assumed to be left empty. Otherwise, from the first non-blank character found in the columns
|
||||
* used by the field name in the header, all characters to the left and to the right that are no space are added to the
|
||||
* field value.<p>
|
||||
*
|
||||
* The result of successfully parsing a {@code .rms} file is a map keyed by the sailnumber, with values being
|
||||
* equal-sized maps from the column names to the {@link String} values. Additionally, the column names corresponding to
|
||||
@@ -35,19 +45,18 @@ import com.sap.sailing.domain.common.orc.ORCCertificate;
|
||||
*/
|
||||
|
||||
public class ORCCertificatesRmsImporter extends AbstractORCCertificatesImporter {
|
||||
private static final String NAME_OF_LAST_LEFT_ALIGNED_COLUMN_HEADER = ORCCertificatesCollectionRMS.ISSUEDATE;
|
||||
private static final String NAME_OF_COLUMN_HEADER_WHERE_THINGS_GET_WEIRD = ORCCertificatesCollectionRMS.ISSUEDATE;
|
||||
|
||||
public ORCCertificatesCollectionRMS read(Reader reader) throws IOException {
|
||||
final BufferedReader br = new BufferedReader(reader);
|
||||
final LinkedHashMap<String, Integer> columnNamesAndWidths = readColumnWidthsFromFirstLine(br.readLine());
|
||||
final Iterator<String> i = columnNamesAndWidths.keySet().iterator();
|
||||
final String certificateIdColumnName = i.next();
|
||||
final String header = br.readLine();
|
||||
final LinkedHashMap<String, Pair<Integer, Integer>> columnNamesAndFieldNameStartInHeader = readColumnHeaderFieldNameStartColumnsAndLengthFromFirstLine(header);
|
||||
final Map<String, Map<String, String>> certificateValuesByCertificateId = new HashMap<>();
|
||||
String line;
|
||||
while ((line = br.readLine()) != null) {
|
||||
if (!line.trim().isEmpty()) {
|
||||
final Map<String, String> parsedLine = parseLine(line, columnNamesAndWidths);
|
||||
certificateValuesByCertificateId.put(parsedLine.get(certificateIdColumnName), parsedLine);
|
||||
final Map<String, String> parsedLine = parseLine(line, columnNamesAndFieldNameStartInHeader);
|
||||
certificateValuesByCertificateId.put(parsedLine.get(ORCCertificatesCollectionRMS.REFERENCE_NUMBER), parsedLine);
|
||||
}
|
||||
}
|
||||
return new ORCCertificatesCollectionRMS(certificateValuesByCertificateId);
|
||||
@@ -57,41 +66,70 @@ public class ORCCertificatesRmsImporter extends AbstractORCCertificatesImporter
|
||||
return read(getReaderForInputStream(in));
|
||||
}
|
||||
|
||||
private Map<String, String> parseLine(final String line, LinkedHashMap<String, Integer> columnNamesAndWidths) {
|
||||
assert columnNamesAndWidths != null;
|
||||
private Map<String, String> parseLine(final String line, LinkedHashMap<String, Pair<Integer, Integer>> columnNamesAndFieldNameStartAndLengthInHeader) {
|
||||
assert columnNamesAndFieldNameStartAndLengthInHeader != null;
|
||||
final Map<String, String> result = new LinkedHashMap<>();
|
||||
int start=0;
|
||||
boolean splitBySpaceMode = false; // start using column names; switch to splitting by spaces when NAME_OF_LAST_LEFT_ALIGNED_COLUMN_HEADER has been found
|
||||
for (final Entry<String, Integer> columnNameAndWidth : columnNamesAndWidths.entrySet()) {
|
||||
boolean leftAligned = true;
|
||||
for (final Entry<String, Pair<Integer, Integer>> columnNameAndFieldNameStartInHeader : columnNamesAndFieldNameStartAndLengthInHeader.entrySet()) {
|
||||
final int start = columnNameAndFieldNameStartInHeader.getValue().getA();
|
||||
final int end;
|
||||
if (splitBySpaceMode) {
|
||||
boolean foundSpace = false;
|
||||
int i;
|
||||
for (i=start; i<line.length() && (!foundSpace || line.charAt(i) == ' '); i++) {
|
||||
if (!foundSpace) {
|
||||
foundSpace = line.charAt(i) == ' ';
|
||||
}
|
||||
}
|
||||
end = i;
|
||||
final String value;
|
||||
if (leftAligned) {
|
||||
end = start+columnNameAndFieldNameStartInHeader.getValue().getB();
|
||||
value = line.substring(start, end).trim();
|
||||
} else {
|
||||
end = start+columnNameAndWidth.getValue();
|
||||
end = start+columnNameAndFieldNameStartInHeader.getKey().length();
|
||||
value = expandFromNonSpaceCharacterInRange(line, start, end);
|
||||
}
|
||||
result.put(columnNameAndWidth.getKey(), line.substring(start, end).trim());
|
||||
if (columnNameAndWidth.getKey().equals(NAME_OF_LAST_LEFT_ALIGNED_COLUMN_HEADER)) {
|
||||
splitBySpaceMode = true;
|
||||
result.put(columnNameAndFieldNameStartInHeader.getKey(), value);
|
||||
if (columnNameAndFieldNameStartInHeader.getKey().equals(NAME_OF_COLUMN_HEADER_WHERE_THINGS_GET_WEIRD)) {
|
||||
leftAligned = false;
|
||||
}
|
||||
start = end;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private LinkedHashMap<String, Integer> readColumnWidthsFromFirstLine(final String readLine) {
|
||||
final LinkedHashMap<String, Integer> result = new LinkedHashMap<>();
|
||||
/**
|
||||
* If only space characters are found in {@code line} starting at index {@code start} and ending before index {@code end},
|
||||
* the result is {@code null}. Otherwise, starting at any non-space character in the range, expansion to the left and right is
|
||||
* performed, collecting all contiguous non-space characters.
|
||||
*/
|
||||
private String expandFromNonSpaceCharacterInRange(String line, int start, int end) {
|
||||
final String result;
|
||||
if (start >= line.length()) {
|
||||
result = null;
|
||||
} else {
|
||||
int left = start;
|
||||
// search for first non-whitespace from start looking right:
|
||||
while (left<line.length() && left < end && left < line.length() && Character.isWhitespace(line.charAt(left))) {
|
||||
left++;
|
||||
}
|
||||
if (left >= end) {
|
||||
result = null;
|
||||
} else {
|
||||
int right = left+1;
|
||||
// expand left:
|
||||
while (left > 0 && Character.isWhitespace(line.charAt(left-1))) {
|
||||
left--;
|
||||
}
|
||||
// expand right:
|
||||
while (right < line.length() && !Character.isWhitespace(line.charAt(right))) {
|
||||
right++;
|
||||
}
|
||||
result = line.substring(left, right);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private LinkedHashMap<String, Pair<Integer, Integer>> readColumnHeaderFieldNameStartColumnsAndLengthFromFirstLine(final String readLine) {
|
||||
final LinkedHashMap<String, Pair<Integer, Integer>> result = new LinkedHashMap<>();
|
||||
final Pattern p = Pattern.compile("([^ ]+ *)");
|
||||
final Matcher m = p.matcher(readLine);
|
||||
int start = 0;
|
||||
while (m.find(start)) {
|
||||
result.put(m.group(1).trim(), m.group(1).length());
|
||||
final String fieldNameTrimmed = m.group(1).trim();
|
||||
result.put(fieldNameTrimmed, new Pair<>(m.start(1), m.group(1).length()));
|
||||
start += m.group(1).length();
|
||||
}
|
||||
return result;
|
||||
|
||||
+42
-11
@@ -77,6 +77,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
private static final String ROOT_ELEMENT = "ROOT";
|
||||
private static final String DATA_ELEMENT = "DATA";
|
||||
private static final String ROW_ELEMENT = "ROW";
|
||||
private static final String DXT_SUFFIX = ".dxt";
|
||||
|
||||
private static final DateTimeFormatter[] DATE_FORMATTERS =
|
||||
new DateTimeFormatter[] {
|
||||
@@ -100,6 +101,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
*/
|
||||
private static class CertificateHandleImpl implements CertificateHandle {
|
||||
private final CountryCode issuingCountry;
|
||||
private final String fileId;
|
||||
private final String sssid;
|
||||
private final Double gph;
|
||||
private final UUID datInGID;
|
||||
@@ -114,12 +116,15 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
private final Integer certType;
|
||||
private final Boolean isOneDesign;
|
||||
private final Boolean isProvisional;
|
||||
private final Boolean isValid;
|
||||
|
||||
public CertificateHandleImpl(CountryCode issuingCountry, Double gph, String sssid, UUID datInGID,
|
||||
String referenceNumber, String yachtName, String sailNumber, String boatClassName, String designer,
|
||||
String builder, Integer yearBuilt, TimePoint issueDate, Integer certType, Boolean oneDesign, Boolean isProvisional) {
|
||||
public CertificateHandleImpl(CountryCode issuingCountry, String fileId, Double gph, String sssid,
|
||||
UUID datInGID, String referenceNumber, String yachtName, String sailNumber, String boatClassName,
|
||||
String designer, String builder, Integer yearBuilt, TimePoint issueDate, Integer certType,
|
||||
Boolean oneDesign, Boolean isProvisional, Boolean isValid) {
|
||||
super();
|
||||
this.issuingCountry = issuingCountry;
|
||||
this.fileId = fileId;
|
||||
this.gph = gph;
|
||||
this.sssid = sssid;
|
||||
this.datInGID = datInGID;
|
||||
@@ -134,6 +139,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
this.certType = certType;
|
||||
this.isOneDesign = oneDesign;
|
||||
this.isProvisional = isProvisional;
|
||||
this.isValid = isValid;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,6 +172,11 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
return issuingCountry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileId() {
|
||||
return fileId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Double getGPH() {
|
||||
return gph;
|
||||
@@ -235,6 +246,11 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
public Boolean isOd() {
|
||||
return isOneDesign;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isValid() {
|
||||
return isValid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -242,13 +258,14 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
+ ", datInGID=" + datInGID + ", referenceNumber=" + referenceNumber + ", yachtName=" + yachtName
|
||||
+ ", sailNumber=" + sailNumber + ", boatClassName=" + boatClassName + ", designer=" + designer
|
||||
+ ", builder=" + builder + ", yearBuilt=" + yearBuilt + ", issueDate=" + issueDate + ", certType="
|
||||
+ certType + ", isOneDesign=" + isOneDesign + ", isProvisional=" + isProvisional + "]";
|
||||
+ certType + ", isOneDesign=" + isOneDesign + ", isProvisional=" + isProvisional +
|
||||
", isValid=" + isValid + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<CertificateHandle> search(CountryCode issuingCountry, Integer yearOfIssuance, String referenceNumber,
|
||||
String yachtName, String sailNumber, String boatClassName) throws Exception {
|
||||
String yachtName, String sailNumber, String boatClassName, boolean includeInvalid) throws Exception {
|
||||
final Set<ORCPublicCertificateDatabase.CertificateHandle> result = new HashSet<>();
|
||||
final HttpClient client = new SystemDefaultHttpClient();
|
||||
final List<NameValuePair> params = new ArrayList<>();
|
||||
@@ -285,8 +302,11 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
for (int rowNodeIndex=0; rowNodeIndex<rowNodes.getLength(); rowNodeIndex++) {
|
||||
final Node rowNode = rowNodes.item(rowNodeIndex);
|
||||
if (rowNode.getNodeName().equals(ROW_ELEMENT)) {
|
||||
// TODO only include results that have <CanSelect>True</CanSelect> CERTIFICATE_IS_ACTIVE
|
||||
result.add(parseHandle(rowNode));
|
||||
final CertificateHandle certificateHandle = parseHandle(rowNode);
|
||||
// certificates can only be obtained if they are currently valid, so ignore expired ones
|
||||
if (includeInvalid || certificateHandle.isValid()) {
|
||||
result.add(certificateHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -302,6 +322,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
private CertificateHandle parseHandle(Node rowNode) throws DOMException, ParseException {
|
||||
assert rowNode.getNodeName().equals(ROW_ELEMENT);
|
||||
CountryCode issuingCountry = null;
|
||||
String fileId = null;
|
||||
String sssid = null;
|
||||
Double gph = null;
|
||||
UUID datInGID = null;
|
||||
@@ -316,6 +337,7 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
TimePoint issueDate = null;
|
||||
Boolean isOneDesign = null;
|
||||
Boolean isProvisional = null;
|
||||
Boolean isValid = null;
|
||||
for (int i=0; i<rowNode.getChildNodes().getLength(); i++) {
|
||||
final Node child = rowNode.getChildNodes().item(i);
|
||||
switch (child.getNodeName()) {
|
||||
@@ -352,6 +374,12 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
case "dxtDate":
|
||||
issueDate = new MillisecondsTimePoint(parseDate(child.getTextContent())); // assume UTC
|
||||
break;
|
||||
case "dxtName":
|
||||
final String fileIdWithOptionalDxtSuffix = child.getTextContent();
|
||||
fileId = fileIdWithOptionalDxtSuffix.toLowerCase().endsWith(DXT_SUFFIX) ?
|
||||
fileIdWithOptionalDxtSuffix.substring(0, fileIdWithOptionalDxtSuffix.length()-DXT_SUFFIX.length()) :
|
||||
fileIdWithOptionalDxtSuffix;
|
||||
break;
|
||||
case "CertType":
|
||||
certType = Integer.valueOf(child.getTextContent().trim());
|
||||
break;
|
||||
@@ -364,10 +392,13 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
case "Provisional":
|
||||
isProvisional = Boolean.valueOf(child.getTextContent());
|
||||
break;
|
||||
case "CanSelect":
|
||||
isValid = Boolean.valueOf(child.getTextContent());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new CertificateHandleImpl(issuingCountry, gph, sssid, datInGID, referenceNumber, yachtName,
|
||||
sailNumber, boatClassName, designer, builder, yearBuilt, issueDate, certType, isOneDesign, isProvisional);
|
||||
return new CertificateHandleImpl(issuingCountry, fileId, gph, sssid, datInGID, referenceNumber,
|
||||
yachtName, sailNumber, boatClassName, designer, builder, yearBuilt, issueDate, certType, isOneDesign, isProvisional, isValid);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -525,13 +556,13 @@ public class ORCPublicCertificateDatabaseImpl implements ORCPublicCertificateDat
|
||||
*/
|
||||
private Iterable<CertificateHandle> fuzzySearchVaryingBoatClassName(final String yachtName, final String sailNumber, final BoatClass boatClass) throws Exception {
|
||||
String successfulBoatClassName = boatClass==null?null:boatClass.getName();
|
||||
Iterable<CertificateHandle> certificateHandles = search(/* issuingCountry */ null, /* yearOfIssuance */ null, /* referenceNumber */ null, yachtName, sailNumber, successfulBoatClassName);
|
||||
Iterable<CertificateHandle> certificateHandles = search(/* issuingCountry */ null, /* yearOfIssuance */ null, /* referenceNumber */ null, yachtName, sailNumber, successfulBoatClassName, /* includeInvalid */ false);
|
||||
if (!containsHandleForCurrentYear(certificateHandles) && successfulBoatClassName != null) {
|
||||
if (yachtName != null || sailNumber != null) {
|
||||
logger.fine(()->"Nothing found; removing boat class name restriction "+boatClass.getName());
|
||||
// try without boat class restriction
|
||||
successfulBoatClassName = null;
|
||||
certificateHandles = search(/* issuingCountry */ null, /* yearOfIssuance */ null, /* referenceNumber */ null, yachtName, sailNumber, successfulBoatClassName);
|
||||
certificateHandles = search(/* issuingCountry */ null, /* yearOfIssuance */ null, /* referenceNumber */ null, yachtName, sailNumber, successfulBoatClassName, /* includeInvalid */ false);
|
||||
} else {
|
||||
logger.fine(()->"No current certificates found for boat class "+boatClass.getName()+
|
||||
" but yacht name and sail number are not specified either; giving up.");
|
||||
|
||||
+12
-7
@@ -12,6 +12,7 @@ import com.google.gwt.user.client.rpc.SerializationStreamWriter;
|
||||
import com.sap.sailing.domain.common.orc.ORCCertificate;
|
||||
import com.sap.sailing.domain.common.orc.impl.ORCCertificateImpl;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.CountryCode;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
@@ -27,7 +28,9 @@ public class ORCCertificateImpl_CustomFieldSerializer extends CustomFieldSeriali
|
||||
|
||||
public static void serialize(SerializationStreamWriter streamWriter, ORCCertificateImpl instance)
|
||||
throws SerializationException {
|
||||
streamWriter.writeString(instance.getId());
|
||||
streamWriter.writeString(instance.getReferenceNumber());
|
||||
streamWriter.writeString(instance.getFileId());
|
||||
streamWriter.writeObject(instance.getIssuingCountry());
|
||||
streamWriter.writeString(instance.getSailNumber());
|
||||
streamWriter.writeString(instance.getBoatName());
|
||||
streamWriter.writeString(instance.getBoatClassName());
|
||||
@@ -65,7 +68,9 @@ public class ORCCertificateImpl_CustomFieldSerializer extends CustomFieldSeriali
|
||||
|
||||
public static ORCCertificateImpl instantiate(SerializationStreamReader streamReader)
|
||||
throws SerializationException {
|
||||
final String idConsistingOfNatAuthCertNoAndBIN = streamReader.readString();
|
||||
final String referenceNumber = streamReader.readString();
|
||||
final String fileId = streamReader.readString();
|
||||
final CountryCode issuingCountry = (CountryCode) streamReader.readObject();
|
||||
final String sailnumber = streamReader.readString();
|
||||
final String boatName = streamReader.readString();
|
||||
final String boatclass = streamReader.readString();
|
||||
@@ -101,12 +106,12 @@ public class ORCCertificateImpl_CustomFieldSerializer extends CustomFieldSeriali
|
||||
@SuppressWarnings("unchecked")
|
||||
final List<Speed> readTWSs = (List<Speed>) streamReader.readObject();
|
||||
final Speed[] trueWindSpeeds = readTWSs == null ? ORCCertificate.ALLOWANCES_TRUE_WIND_SPEEDS : readTWSs.toArray(new Speed[readTWSs.size()]);
|
||||
return new ORCCertificateImpl(trueWindSpeeds,trueWindAngles,idConsistingOfNatAuthCertNoAndBIN, sailnumber, boatName, boatclass, length, gph,
|
||||
cdl, issueDate, velocityPredictionsPerTrueWindSpeedAndAngle, beatAngles,
|
||||
beatVMGPredictionPerTrueWindSpeed, beatAllowancePerTrueWindSpeed, runAngles,
|
||||
return new ORCCertificateImpl(trueWindSpeeds,trueWindAngles,referenceNumber, fileId, sailnumber, boatName, boatclass, length,
|
||||
gph, cdl, issueDate, issuingCountry,
|
||||
velocityPredictionsPerTrueWindSpeedAndAngle, beatAngles, beatVMGPredictionPerTrueWindSpeed,
|
||||
beatAllowancePerTrueWindSpeed, runAngles,
|
||||
runVMGPredictionPerTrueWindSpeed, runAllowancePerTrueWindSpeed,
|
||||
windwardLeewardSpeedPredictionsPerTrueWindSpeed, longDistanceSpeedPredictionsPerTrueWindSpeed,
|
||||
circularRandomSpeedPredictionsPerTrueWindSpeed, nonSpinnakerSpeedPredictionsPerTrueWindSpeed);
|
||||
windwardLeewardSpeedPredictionsPerTrueWindSpeed, longDistanceSpeedPredictionsPerTrueWindSpeed, circularRandomSpeedPredictionsPerTrueWindSpeed, nonSpinnakerSpeedPredictionsPerTrueWindSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -9981,7 +9981,7 @@ public class SailingServiceImpl extends ResultCachingProxiedRemoteServiceServlet
|
||||
String referenceNumber, String yachtName, String sailNumber, String boatClassName) throws Exception {
|
||||
final ORCPublicCertificateDatabase db = ORCPublicCertificateDatabase.INSTANCE;
|
||||
final Set<ORCCertificate> result = new HashSet<>();
|
||||
final Iterable<CertificateHandle> searchResult = db.search(country, yearOfIssuance, referenceNumber, yachtName, sailNumber, boatClassName);
|
||||
final Iterable<CertificateHandle> searchResult = db.search(country, yearOfIssuance, referenceNumber, yachtName, sailNumber, boatClassName, /* includeInvalid */ false);
|
||||
Util.addAll(
|
||||
db.getCertificates(searchResult),
|
||||
result);
|
||||
|
||||
+13
-7
@@ -17,6 +17,8 @@ import com.sap.sailing.server.gateway.deserialization.JsonDeserializationExcepti
|
||||
import com.sap.sailing.server.gateway.deserialization.JsonDeserializer;
|
||||
import com.sap.sailing.server.gateway.serialization.racelog.impl.ORCCertificateJsonSerializer;
|
||||
import com.sap.sse.common.Bearing;
|
||||
import com.sap.sse.common.CountryCode;
|
||||
import com.sap.sse.common.CountryCodeFactory;
|
||||
import com.sap.sse.common.Distance;
|
||||
import com.sap.sse.common.Duration;
|
||||
import com.sap.sse.common.Speed;
|
||||
@@ -29,6 +31,9 @@ public class ORCCertificateJsonDeserializer implements JsonDeserializer<ORCCerti
|
||||
|
||||
@Override
|
||||
public ORCCertificate deserialize(JSONObject json) throws JsonDeserializationException {
|
||||
String fileId = (String) json.get(ORCCertificateJsonSerializer.ORC_CERTIFICATE_FILE_ID);
|
||||
CountryCode issuingCountry = CountryCodeFactory.INSTANCE.getFromThreeLetterIOCName(
|
||||
((String) json.get(ORCCertificateJsonSerializer.ORC_CERTIFICATE_ISSUING_COUNTRY_IOC)));
|
||||
String sailnumber = (String) json.get(ORCCertificateJsonSerializer.ORC_CERTIFICATE_SAILNUMBER);
|
||||
String boatName = (String) json.get(ORCCertificateJsonSerializer.ORC_CERTIFICATE_BOATNAME);
|
||||
String boatclass = (String) json.get(ORCCertificateJsonSerializer.ORC_CERTIFICATE_BOATCLASS);
|
||||
@@ -103,13 +108,14 @@ public class ORCCertificateJsonDeserializer implements JsonDeserializer<ORCCerti
|
||||
velocityPredictionsPerTrueWindSpeedAndAngle.put(tws,
|
||||
velocityPredictionAtCurrentTrueWindSpeedPerTrueWindAngle);
|
||||
}
|
||||
final String idConsistingOfNatAuthCertNoAndBIN = json.get(ORCCertificateJsonSerializer.ORC_CERTIFICATE_ID).toString();
|
||||
final ORCCertificate certificate = new ORCCertificateImpl(trueWindSpeeds,trueWindAngles,idConsistingOfNatAuthCertNoAndBIN, sailnumber,
|
||||
boatName, boatclass, length, gph, cdl, issueDate, velocityPredictionsPerTrueWindSpeedAndAngle,
|
||||
beatAngles, beatVMGPredictionPerTrueWindSpeed, beatAllowancePerTrueWindSpeed, runAngles,
|
||||
runVMGPredictionPerTrueWindSpeed, runAllowancePerTrueWindSpeed,
|
||||
windwardLeewardSpeedPredictionPerTrueWindSpeed, longDistanceSpeedPredictionPerTrueWindSpeed,
|
||||
circularRandomSpeedPredictionPerTrueWindSpeed, nonSpinnakerSpeedPredictionPerTrueWindSpeed);
|
||||
final String referenceNumber = json.get(ORCCertificateJsonSerializer.ORC_CERTIFICATE_ID).toString();
|
||||
final ORCCertificate certificate = new ORCCertificateImpl(trueWindSpeeds, trueWindAngles, referenceNumber,
|
||||
fileId, sailnumber, boatName, boatclass, length, gph, cdl, issueDate, issuingCountry,
|
||||
velocityPredictionsPerTrueWindSpeedAndAngle, beatAngles, beatVMGPredictionPerTrueWindSpeed,
|
||||
beatAllowancePerTrueWindSpeed, runAngles, runVMGPredictionPerTrueWindSpeed,
|
||||
runAllowancePerTrueWindSpeed, windwardLeewardSpeedPredictionPerTrueWindSpeed,
|
||||
longDistanceSpeedPredictionPerTrueWindSpeed, circularRandomSpeedPredictionPerTrueWindSpeed,
|
||||
nonSpinnakerSpeedPredictionPerTrueWindSpeed);
|
||||
return certificate;
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -23,6 +23,8 @@ public class ORCCertificateJsonSerializer implements JsonSerializer<ORCCertifica
|
||||
public static final String ORC_CERTIFICATE_CIRCULAR_RANDOM_SPEED_PREDICTIONS = "circularRandomSpeedPredictions";
|
||||
public static final String ORC_CERTIFICATE_NON_SPINNAKER_SPEED_PREDICTIONS = "nonSpinnakerSpeedPredictions";
|
||||
public static final String ORC_CERTIFICATE_TWA_SPEED_PREDICTIONS = "twaSpeedPredictions";
|
||||
public static final String ORC_CERTIFICATE_FILE_ID = "fileId";
|
||||
public static final String ORC_CERTIFICATE_ISSUING_COUNTRY_IOC = "issuingCountryIOC";
|
||||
public static final String ORC_CERTIFICATE_SAILNUMBER = "sailNumber";
|
||||
public static final String ORC_CERTIFICATE_BOATNAME = "boatName";
|
||||
public static final String ORC_CERTIFICATE_BOATCLASS = "boatClass";
|
||||
@@ -55,7 +57,9 @@ public class ORCCertificateJsonSerializer implements JsonSerializer<ORCCertifica
|
||||
@Override
|
||||
public JSONObject serialize(ORCCertificate certificate) {
|
||||
JSONObject result = new JSONObject();
|
||||
result.put(ORC_CERTIFICATE_ID, certificate.getId());
|
||||
result.put(ORC_CERTIFICATE_ID, certificate.getReferenceNumber());
|
||||
result.put(ORC_CERTIFICATE_ISSUING_COUNTRY_IOC, certificate.getIssuingCountry().getThreeLetterIOCCode());
|
||||
result.put(ORC_CERTIFICATE_FILE_ID, certificate.getFileId());
|
||||
result.put(ORC_CERTIFICATE_SAILNUMBER, certificate.getSailNumber());
|
||||
result.put(ORC_CERTIFICATE_BOATNAME, certificate.getBoatName());
|
||||
result.put(ORC_CERTIFICATE_BOATCLASS, certificate.getBoatClassName());
|
||||
|
||||
Reference in new issue
Block a user