improved ORC certificate display in AdminConsole

This commit is contained in:
Axel Uhl committed 2020-03-12 21:30:50 +01:00
1 parent 45b5669b0d
commit 3228ee4841
18 files changed
+217 -37

No files matched your search

@@ -5,6 +5,7 @@ import com.sap.sailing.domain.common.impl.NauticalMileDistance;
import com.sap.sse.common.Distance;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Speed;
import com.sap.sse.common.impl.SecondsDurationImpl;
public abstract class AbstractDistance implements Distance {
@@ -41,6 +42,11 @@ public abstract class AbstractDistance implements Distance {
return inSeconds(duration.asSeconds());
}
@Override
public Duration atSpeed(Speed speed) {
return new SecondsDurationImpl(getMeters() / speed.getMetersPerSecond());
}
@Override
public double getNauticalMiles() {
return getMeters() / Mile.METERS_PER_NAUTICAL_MILE;
@@ -4,6 +4,7 @@ import java.io.Serializable;
import java.util.Map;
import com.sap.sailing.domain.common.impl.KnotSpeedImpl;
import com.sap.sailing.domain.common.impl.NauticalMileDistance;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.CountryCode;
import com.sap.sse.common.Distance;
@@ -64,6 +65,8 @@ 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) };
Distance NAUTICAL_MILE = new NauticalMileDistance(1);
/**
* We use the {@link #getReferenceNumber() reference number ("RefNo")} as the ID of a certificate document.
@@ -3,7 +3,6 @@ package com.sap.sailing.domain.common.orc.impl;
import java.util.Collections;
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;
@@ -27,8 +26,6 @@ public class ORCCertificateImpl implements ORCCertificate {
private final String referenceNumber;
public final static Distance NAUTICAL_MILE = new NauticalMileDistance(1);
private final String sailNumber;
private final String boatName;
private final String boatClassName;
@@ -14,7 +14,6 @@ import org.json.simple.parser.ParseException;
import org.junit.Rule;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.domain.common.orc.impl.ORCCertificateImpl;
import com.sap.sse.common.Util;
@@ -50,7 +49,7 @@ public abstract class AbstractORCCertificateImporterTest {
" was found when importing the country document from "+url, someValidCert);
assertNotNull(referenceCert);
assertEquals(referenceCert.getGPHInSecondsToTheMile(), someValidCert.getGPHInSecondsToTheMile(), 0.0000001);
assertTrue(referenceCert.getWindwardLeewardSpeedPrediction().get(ORCCertificate.ALLOWANCES_TRUE_WIND_SPEEDS[0]).getDuration(ORCCertificateImpl.NAUTICAL_MILE).asSeconds() > 10);
assertTrue(referenceCert.getLongDistanceSpeedPredictions().get(ORCCertificate.ALLOWANCES_TRUE_WIND_SPEEDS[0]).getDuration(ORCCertificateImpl.NAUTICAL_MILE).asSeconds() > 10);
assertTrue(referenceCert.getWindwardLeewardSpeedPrediction().get(ORCCertificate.ALLOWANCES_TRUE_WIND_SPEEDS[0]).getDuration(ORCCertificate.NAUTICAL_MILE).asSeconds() > 10);
assertTrue(referenceCert.getLongDistanceSpeedPredictions().get(ORCCertificate.ALLOWANCES_TRUE_WIND_SPEEDS[0]).getDuration(ORCCertificate.NAUTICAL_MILE).asSeconds() > 10);
}
}
@@ -27,7 +27,6 @@ import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveCourse;
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLeg;
import com.sap.sailing.domain.common.orc.ORCPerformanceCurveLegTypes;
import com.sap.sailing.domain.common.orc.impl.ORCCertificateImpl;
import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveCourseImpl;
import com.sap.sailing.domain.common.orc.impl.ORCPerformanceCurveLegImpl;
import com.sap.sailing.domain.orc.impl.ORCCertificatesJsonImporter;
@@ -133,7 +132,7 @@ public class TestORCPerformanceCurve {
private void testAllowancePerLeg(ORCCertificate certificate, double twa, double... expectedAllowancesPerTrueWindSpeed) throws FunctionEvaluationException {
Double accuracy = 0.1;
final ORCPerformanceCurveCourse course = new ORCPerformanceCurveCourseImpl(Arrays.asList(new ORCPerformanceCurveLegImpl(ORCCertificateImpl.NAUTICAL_MILE, new DegreeBearingImpl(twa))));
final ORCPerformanceCurveCourse course = new ORCPerformanceCurveCourseImpl(Arrays.asList(new ORCPerformanceCurveLegImpl(ORCCertificate.NAUTICAL_MILE, new DegreeBearingImpl(twa))));
final ORCPerformanceCurve performanceCurve = new ORCPerformanceCurveImpl(certificate, course);
for (int i=0; i<expectedAllowancesPerTrueWindSpeed.length; i++) {
assertEquals(expectedAllowancesPerTrueWindSpeed[i], performanceCurve.getAllowancePerCourse(ORCCertificate.ALLOWANCES_TRUE_WIND_SPEEDS[i]).asSeconds(), accuracy);
@@ -230,7 +230,7 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec
trueWindSpeedMap.values().forEach(tws -> velocityPredictionPerTrueWindSpeedAndAngle.put(tws, new HashMap<>()));
for (final Bearing keyTWA : allowanceDurationsPerTrueWindAngleAndSpeed.keySet()) {
for (final Speed keyTWS : allowanceDurationsPerTrueWindAngleAndSpeed.get(keyTWA).keySet()) {
velocityPredictionPerTrueWindSpeedAndAngle.get(keyTWS).put(keyTWA, ORCCertificateImpl.NAUTICAL_MILE
velocityPredictionPerTrueWindSpeedAndAngle.get(keyTWS).put(keyTWA, ORCCertificate.NAUTICAL_MILE
.inTime(allowanceDurationsPerTrueWindAngleAndSpeed.get(keyTWA).get(keyTWS)));
}
}
@@ -243,19 +243,19 @@ public class ORCCertificatesCollectionJSON extends AbstractORCCertificatesCollec
final Map<Speed, Speed> circularRandomSpeedPredictionPerTrueWindSpeed = new HashMap<>();
final Map<Speed, Speed> nonSpinnakerSpeedPredictionPerTrueWindSpeed = new HashMap<>();
for (final Speed tws : velocityPredictionPerTrueWindSpeedAndAngle.keySet()) {
beatVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE
beatVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE
.inTime(predefinedAllowanceDurationsPerTrueWindSpeed.get(BEAT).get(tws)));
beatAllowancePerTrueWindSpeed.put(tws, predefinedAllowanceDurationsPerTrueWindSpeed.get(BEAT).get(tws));
runVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE
runVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE
.inTime(predefinedAllowanceDurationsPerTrueWindSpeed.get(RUN).get(tws)));
runAllowancePerTrueWindSpeed.put(tws, predefinedAllowanceDurationsPerTrueWindSpeed.get(RUN).get(tws));
windwardLeewardSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE
windwardLeewardSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE
.inTime(predefinedAllowanceDurationsPerTrueWindSpeed.get(WINDWARD_LEEWARD).get(tws)));
longDistanceSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE
longDistanceSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE
.inTime(predefinedAllowanceDurationsPerTrueWindSpeed.get(LONG_DISTANCE).get(tws)));
circularRandomSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE
circularRandomSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE
.inTime(predefinedAllowanceDurationsPerTrueWindSpeed.get(CIRCULAR_RANDOM).get(tws)));
nonSpinnakerSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE
nonSpinnakerSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE
.inTime(predefinedAllowanceDurationsPerTrueWindSpeed.get(NON_SPINNAKER).get(tws)));
}
final Bearing[] dynamicAllowancesTrueWindAngles = trueWindAngleMap.values().toArray(new Bearing[trueWindAngleMap.values().size()]);
@@ -155,22 +155,22 @@ public class ORCCertificatesCollectionRMS extends AbstractORCCertificatesCollect
String nonSpinnakerKey = NON_SPINNAKER + windSpeed;
beatAngles.put(tws, new DegreeBearingImpl(Double.parseDouble(certificateValues.getValue(beatAngleKey))));
beatAllowancePerTrueWindSpeed.put(tws, new SecondsDurationImpl(Double.parseDouble(certificateValues.getValue(beatAllowanceKey))));
beatVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE.inTime(beatAllowancePerTrueWindSpeed.get(tws)));
beatVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE.inTime(beatAllowancePerTrueWindSpeed.get(tws)));
runAngles.put(tws, new DegreeBearingImpl(Double.parseDouble(certificateValues.getValue(runAngleKey))));
runAllowancePerTrueWindSpeed.put(tws, new SecondsDurationImpl(Double.parseDouble(certificateValues.getValue(runAllowanceKey))));
runVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE.inTime(runAllowancePerTrueWindSpeed.get(tws)));
windwardLeewardSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE.inTime(
runVMGPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE.inTime(runAllowancePerTrueWindSpeed.get(tws)));
windwardLeewardSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE.inTime(
new SecondsDurationImpl(Double.parseDouble(certificateValues.getValue(windwardLeewardKey)))));
longDistanceSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE.inTime(
longDistanceSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE.inTime(
new SecondsDurationImpl(Double.parseDouble(certificateValues.getValue(longDistanceKey)))));
circularRandomSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE.inTime(
circularRandomSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE.inTime(
new SecondsDurationImpl(Double.parseDouble(certificateValues.getValue(circularRandomKey)))));
nonSpinnakerSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificateImpl.NAUTICAL_MILE.inTime(
nonSpinnakerSpeedPredictionPerTrueWindSpeed.put(tws, ORCCertificate.NAUTICAL_MILE.inTime(
new SecondsDurationImpl(Double.parseDouble(certificateValues.getValue(nonSpinnakerKey)))));
Map<Bearing, Speed> velocityPredictionPerTrueWindAngle = new HashMap<>();
for (Bearing twa : ORCCertificate.ALLOWANCES_TRUE_WIND_ANGLES ) {
String twaCoursesKey = TWA_COURSES + Integer.toString((int) twa.getDegrees()) + windSpeed;
velocityPredictionPerTrueWindAngle.put(twa, ORCCertificateImpl.NAUTICAL_MILE.inTime(
velocityPredictionPerTrueWindAngle.put(twa, ORCCertificate.NAUTICAL_MILE.inTime(
new SecondsDurationImpl(Double.parseDouble(certificateValues.getValue(twaCoursesKey)))));
}
velocityPredictionsPerTrueWindSpeedAndAngle.put(tws, velocityPredictionPerTrueWindAngle);
@@ -375,7 +375,7 @@ public class ORCPerformanceCurveImpl implements Serializable, ORCPerformanceCurv
result.append(e.getKey());
result.append(':');
final Speed averageSpeed = getCourse().getTotalLength().inTime(e.getValue());
result.append(averageSpeed.getDuration(ORCCertificateImpl.NAUTICAL_MILE).asSeconds());
result.append(averageSpeed.getDuration(ORCCertificate.NAUTICAL_MILE).asSeconds());
result.append("s/NM, ");
result.append(e.getValue().asSeconds());
result.append("s total; ");
@@ -26,7 +26,7 @@ public class ORCCertificateImpl_CustomFieldSerializer extends CustomFieldSeriali
serialize(streamWriter, instance);
}
public static void serialize(SerializationStreamWriter streamWriter, ORCCertificateImpl instance)
public static void serialize(SerializationStreamWriter streamWriter, ORCCertificate instance)
throws SerializationException {
streamWriter.writeString(instance.getReferenceNumber());
streamWriter.writeString(instance.getFileId());
@@ -120,7 +120,7 @@ public class ORCCertificateImpl_CustomFieldSerializer extends CustomFieldSeriali
deserialize(streamReader, instance);
}
public static void deserialize(SerializationStreamReader streamReader, ORCCertificateImpl instance) {
public static void deserialize(SerializationStreamReader streamReader, ORCCertificate instance) {
// Done by instantiateInstance
}
@@ -15,8 +15,8 @@ import com.google.gwt.user.cellview.client.AbstractCellTable;
import com.google.gwt.user.cellview.client.Column;
import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler;
import com.google.gwt.user.cellview.client.TextColumn;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.gwt.ui.client.SailingServiceAsync;
import com.sap.sailing.gwt.ui.client.StringMessages;
@@ -27,6 +27,7 @@ import com.sap.sse.gwt.client.ErrorReporter;
import com.sap.sse.gwt.client.celltable.EntityIdentityComparator;
import com.sap.sse.gwt.client.celltable.ImagesBarColumn;
import com.sap.sse.gwt.client.celltable.RefreshableSelectionModel;
import com.sap.sse.gwt.client.dialog.DataEntryDialog;
import com.sap.sse.gwt.client.panels.LabeledAbstractFilterablePanel;
import com.sap.sse.security.ui.client.UserService;
@@ -174,10 +175,19 @@ public class CertificatesTableWrapper<S extends RefreshableSelectionModel<ORCCer
table.ensureDebugId("BoatsWithVertificateTable");
}
protected void showCertificate(ORCCertificate certificate) {
// TODO embed <a href=\"http://data.orc.org/public/WPub.dll/CC/"+certificate.getReferenceNumber()+"\"> to link to the certificate PDF
Window.confirm("Certificate: "+certificate);
// TODO Implement CertificatesTableWrapper.showCertificate(...)
protected void showCertificate(final ORCCertificate certificate) {
new DataEntryDialog<Void>(getStringMessages().orcCertificate(), /* message */ null,
getStringMessages().ok(), getStringMessages().cancel(), /* validator */ null, /* animation */ false, /* callback */ null) {
@Override
protected Widget getAdditionalWidget() {
return new ORCCertificateDisplayPanel(certificate, getStringMessages());
}
@Override
protected Void getResult() {
return null;
}
}.show();
}
public void setCertificates(Collection<ORCCertificate> result) {
@@ -0,0 +1,104 @@
package com.sap.sailing.gwt.ui.adminconsole;
import java.util.Map;
import java.util.function.Function;
import com.google.gwt.dom.client.Style;
import com.google.gwt.safehtml.shared.SafeHtmlBuilder;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.CaptionPanel;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.sap.sailing.domain.common.orc.ORCCertificate;
import com.sap.sailing.gwt.ui.client.StringMessages;
import com.sap.sse.common.Bearing;
import com.sap.sse.common.CountryCode;
import com.sap.sse.common.Duration;
import com.sap.sse.common.Speed;
import com.sap.sse.common.Util;
public class ORCCertificateDisplayPanel extends DockPanel {
public ORCCertificateDisplayPanel(ORCCertificate certificate, StringMessages stringMessages) {
final VerticalPanel panel = new VerticalPanel();
add(panel, DockPanel.CENTER);
// header
final CaptionPanel headerCaptionPanel = new CaptionPanel();
final Grid headerData = new Grid(10, 2);
headerCaptionPanel.add(headerData);
panel.add(headerCaptionPanel);
int row=0;
headerData.setWidget(row, 0, new Label(stringMessages.certificateIssuingDate()));
headerData.setWidget(row++, 1, new Label(certificate.getIssueDate().toString()));
headerData.setWidget(row, 0, new Label(stringMessages.issuingCountry()));
final CountryCode issuingCountry = certificate.getIssuingCountry();
headerData.setWidget(row++, 1,
new Label(issuingCountry==null ? stringMessages.empty() : (issuingCountry.getThreeLetterIOCCode() + " (" + issuingCountry.getName() + ")")));
headerData.setWidget(row, 0, new Label(stringMessages.orcFileId()));
headerData.setWidget(row++, 1, new Label(certificate.getFileId()));
headerData.setWidget(row, 0, new Label(stringMessages.orcCertificateReferenceNumber()));
headerData.setWidget(row++, 1, new Label(certificate.getReferenceNumber()));
headerData.setWidget(row, 0, new Label(stringMessages.boat()));
headerData.setWidget(row++, 1, new Label(certificate.getBoatName()));
headerData.setWidget(row, 0, new Label(stringMessages.sailID()));
headerData.setWidget(row++, 1, new Label(certificate.getSailNumber()));
headerData.setWidget(row, 0, new Label(stringMessages.boatClass()));
headerData.setWidget(row++, 1, new Label(certificate.getBoatClassName()));
headerData.setWidget(row, 0, new Label(stringMessages.gph()));
headerData.setWidget(row++, 1, new Label(Util.padPositiveValue(certificate.getGPHInSecondsToTheMile(), 1, 1, /* round */ true)));
headerData.setWidget(row, 0, new Label(stringMessages.cdl()));
headerData.setWidget(row++, 1, new Label(Util.padPositiveValue(certificate.getCDL(), 1, 3, /* round */ true)));
headerData.setWidget(row, 0, new Label(stringMessages.lengthOverAllInMeters()));
headerData.setWidget(row++, 1, new Label(Util.padPositiveValue(certificate.getLengthOverAll().getMeters(), 1, 3, /* round */ true)));
// time allowances
final CaptionPanel timeAllowancesCaptionPanel = new CaptionPanel(stringMessages.timeAllowances());
panel.add(timeAllowancesCaptionPanel);
// the number of rows is one for the wind velocity header, plus the number of TWA values, plus beat VMG,
// plus run VMG, plus four allowances for the selected courses, plus beat angles, plus gybe angles
final Grid timeAllowancesData = new Grid(1+certificate.getTrueWindAngles().length+1+1+4+1+1, 1+certificate.getTrueWindSpeeds().length);
timeAllowancesCaptionPanel.add(timeAllowancesData);
row=0;
fillLine(certificate, stringMessages.windSpeed(), row++, timeAllowancesData, tws->Util.padPositiveValue(tws.getKnots(), 1, 1, /* round */ true)+stringMessages.knotsUnit());
final Map<Speed, Duration> beatAllowances = certificate.getBeatAllowances();
fillLine(certificate, stringMessages.beatVMG(), row++, timeAllowancesData, tws->Util.padPositiveValue(beatAllowances.get(tws).asSeconds(), 1, 1, /* round */ true));
for (final Bearing twa : certificate.getTrueWindAngles()) {
final Map<Speed, Map<Bearing, Speed>> allowances = certificate
.getVelocityPredictionPerTrueWindSpeedAndAngle();
fillLine(certificate, Util.padPositiveValue(twa.getDegrees(), 1, 1, /* round */ true), row++,
timeAllowancesData, tws -> getVelocityPredictionAsSecondsToTheNauticalMileRoundedToOneTenth(allowances.get(tws).get(twa)));
}
final Map<Speed, Duration> runAllowances = certificate.getRunAllowances();
fillLine(certificate, stringMessages.runVMG(), row++, timeAllowancesData, tws->Util.padPositiveValue(runAllowances.get(tws).asSeconds(), 1, 1, /* round */ true));
// selected courses:
final Map<Speed, Speed> windwardLeewardSpeedPrediction = certificate.getWindwardLeewardSpeedPrediction();
fillLine(certificate, "Windward/Leeward", row++, timeAllowancesData, tws->getVelocityPredictionAsSecondsToTheNauticalMileRoundedToOneTenth(windwardLeewardSpeedPrediction.get(tws)));
final Map<Speed, Speed> circularRandomSpeedPrediction = certificate.getCircularRandomSpeedPredictions();
fillLine(certificate, "Circular Random", row++, timeAllowancesData, tws->getVelocityPredictionAsSecondsToTheNauticalMileRoundedToOneTenth(circularRandomSpeedPrediction.get(tws)));
final Map<Speed, Speed> coastalLongDistanceSpeedPrediction = certificate.getLongDistanceSpeedPredictions();
fillLine(certificate, "Coastal / Long Distance", row++, timeAllowancesData, tws->getVelocityPredictionAsSecondsToTheNauticalMileRoundedToOneTenth(coastalLongDistanceSpeedPrediction.get(tws)));
final Map<Speed, Speed> nonSpinnakerSpeedPrediction = certificate.getNonSpinnakerSpeedPredictions();
fillLine(certificate, "Non Spinnaker", row++, timeAllowancesData, tws->getVelocityPredictionAsSecondsToTheNauticalMileRoundedToOneTenth(nonSpinnakerSpeedPrediction.get(tws)));
final Map<Speed, Bearing> beatAngles = certificate.getBeatAngles();
fillLine(certificate, stringMessages.beatAngles(), row++, timeAllowancesData, tws->Util.padPositiveValue(beatAngles.get(tws).getDegrees(), 1, 1, /* round */ true));
final Map<Speed, Bearing> runAngles = certificate.getRunAngles();
fillLine(certificate, stringMessages.runAngles(), row++, timeAllowancesData, tws->Util.padPositiveValue(runAngles.get(tws).getDegrees(), 1, 1, /* round */ true));
final Anchor linkToCertificate = new Anchor(new SafeHtmlBuilder().appendEscaped(stringMessages.linkToOrcCertificate()).toSafeHtml(),
"https://data.orc.org/public/WPub.dll/CC/"+certificate.getReferenceNumber(), /* target */ "_blank");
panel.add(linkToCertificate);
}
private String getVelocityPredictionAsSecondsToTheNauticalMileRoundedToOneTenth(Speed velocityPrediction) {
return Util.padPositiveValue(ORCCertificate.NAUTICAL_MILE.atSpeed(velocityPrediction).asSeconds(), 1, 1, /* round */ true);
}
private void fillLine(ORCCertificate certificate, String lineLabel, int row, final Grid grid, Function<Speed, String> twsToValueLabel) {
int column=0;
grid.setWidget(row, column++, new Label(lineLabel));
for (final Speed trueWindSpeed : certificate.getTrueWindSpeeds()) {
final Label valueLabel = new Label(twsToValueLabel.apply(trueWindSpeed));
valueLabel.setHorizontalAlignment(ALIGN_RIGHT);
grid.setWidget(row, column++, valueLabel);
}
}
}
@@ -2362,4 +2362,16 @@ public interface StringMessages extends com.sap.sse.gwt.client.StringMessages,
String spareMarksAndTheirOptionalDefaultMarkRoles();
String impliedWind();
String impliedWindTooltip();
String orcCertificate();
String linkToOrcCertificate();
String orcFileId();
String orcCertificateReferenceNumber();
String cdl();
String gph();
String lengthOverAllInMeters();
String timeAllowances();
String beatVMG();
String runVMG();
String beatAngles();
String runAngles();
}
@@ -2365,4 +2365,16 @@ setPosition=Set position
spareMarksAndTheirOptionalDefaultMarkRoles=Spare marks and their optional default mark roles
impliedWind=Implied Wind
impliedWindTooltip=The implied wind is the hypothetical true wind speed at which the competitor would have completed the part of the course it has sailed so far in the time elapsed so far, according to its polar sheet / velocity predictions.
additionalInformation=Additional information
additionalInformation=Additional information
orcCertificate=ORC Certificate
linkToOrcCertificate=PDF version of certificate
orcFileId=File ID
orcCertificateReferenceNumber=Reference number
cdl=Class Division Length (CDL)
gph=General-Purpose Handicap (GPH)
lengthOverAllInMeters=Length over all (LOA) in meters
timeAllowances=Time allowances
beatVMG=Beat VMG
runVMG=Run VMG
beatAngles=Beat angles
runAngles=Run angles
@@ -2380,4 +2380,16 @@ setPosition=Position setzen
spareMarksAndTheirOptionalDefaultMarkRoles=Ersatzbahnmarken und ihre optionalen Standard-Rollen
impliedWind=Implizierter Wind
impliedWindTooltip=Der implizierte Wind ist die hypothetische Geschwindigkeit des wahren Windes, mit dem der Teilnehmer den bisher absolvierten Teil des Kurses in der bisher benötigten Zeit laut seinem Polardiagramm gesegelt sein würde.
additionalInformation=Weiterführende Information
additionalInformation=Weiterführende Information
orcCertificate=ORC-Zertifikat
linkToOrcCertificate=PDF-Version des Zertifikats
orcFileId=Datei-Kennung
orcCertificateReferenceNumber=Referenz-Nummer
cdl=Klassen-Unterteilungslänge (CDL)
gph=Allgemeiner Handicap-Wert (GPH)
lengthOverAllInMeters=Länge über alles (LüA) in Metern
timeAllowances=Zeitgutschriften
beatVMG=VMG an der Kreuz
runVMG=VMG vor dem Wind
beatAngles=Kreuzwinkel
runAngles=Vorwindwinkel
@@ -17,10 +17,17 @@
</div>
</div>
<div class="yield_content">
<div class="contentWrapper">
<div class="mainContent">
<h2 class="releaseHeadline">Release Notes - Administration Console</h2>
<div class="innerContent">
<div class="contentWrapper">
<div class="mainContent">
<h2 class="releaseHeadline">Release Notes - Administration Console</h2>
<div class="innerContent">
<h2 class="articleSubheadline">March 2020</h2>
<ul class="bulletList">
<li>The visualization for ORC certificates has been much improved. It now shows all the
time allowances relevant for Performance Curve Scoring (PCS) and offers a link to the
official PDF version of the respective certificate, based on its reference number.
</li>
</ul>
<h2 class="articleSubheadline">February 2020</h2>
<ul class="bulletList">
<li>The "Local Server" tab now refreshes automatically when it comes into view.</li>
@@ -21,6 +21,11 @@ public class NumberPaddingTest {
assertEquals("10.1", padPositiveValue(10.1, 0, 1, /* round */ false));
}
@Test
public void testValueGreaterThanTenWithOneDigitLeftOfDecimalRequested() {
assertEquals("10.1", padPositiveValue(10.1, 1, 1, /* round */ false));
}
@Test
public void testTruncation() {
assertEquals("10.1", padPositiveValue(10.179, 0, 1, /* round */ false));
@@ -39,6 +39,11 @@ public interface Distance extends Comparable<Distance>, Serializable {
return 0;
}
@Override
public Duration atSpeed(Speed speed) {
return Duration.NULL;
}
@Override
public double getKilometers() {
return 0;
@@ -123,6 +128,11 @@ public interface Distance extends Comparable<Distance>, Serializable {
Speed inTime(Duration duration);
/**
* Computes the duration it takes to travel this distance at the given {@code speed}.
*/
Duration atSpeed(Speed speed);
Distance add(Distance d);
/**
@@ -846,7 +846,11 @@ public class Util {
* the integer part of the {@code value}'s magnitude.
*
* @param digitsLeftOfDecimal
* a non-negative number; if zero,
* a non-negative number; if zero, no "0" will be used left of the decimal point if the value is less than 1.
* Padding occurs only if the number of digits requested is greater than the number of digits the value has
* left of the decimal point. If the number of digits requested left of the decimal point is less than what
* the number has, no cropping takes place and the result will have more digits left of the decimal point
* than requested.
* @param digitsRightOfDecimal
* a non-negative number; if zero, no decimal point will appear at all
* @param round