@@ -0,0 +1,1461 @@
+package au.gov.amsa.navigation;%0A%0Aimport java.util.concurrent.TimeUnit;%0A%0Aimport au.gov.amsa.navigation.VesselPosition.NavigationalStatus;%0Aimport au.gov.amsa.risky.format.AisClass;%0Aimport au.gov.amsa.risky.format.Fix;%0A%0Aimport com.google.common.base.Optional;%0A%0Apublic class VesselPositions %7B%0A%0A%09private static final long KNOTS_TO_METRES_PER_SECOND = 1852 / TimeUnit.HOURS%0A%09%09%09.toSeconds(1);%0A%0A%09public static VesselPosition toVesselPosition(Fix fix) %7B%0A%09%09return VesselPosition%0A%09%09%09%09.builder()%0A%09%09%09%09.lat(fix.getLat())%0A%09%09%09%09.lon(fix.getLon())%0A%09%09%09%09.time(fix.getTime())%0A%09%09%09%09.cls(fix.getAisClass() == AisClass.A ? VesselClass.A%0A%09%09%09%09%09%09: VesselClass.B)%0A%09%09%09%09.cogDegrees(toDouble(fix.getCourseOverGroundDegrees()))%0A%09%09%09%09.headingDegrees(toDouble(fix.getHeadingDegrees()))%0A%09%09%09%09.speedMetresPerSecond(%0A%09%09%09%09%09%09times(fix.getSpeedOverGroundKnots(),%0A%09%09%09%09%09%09%09%09KNOTS_TO_METRES_PER_SECOND))%0A%09%09%09%09.navigationalStatus(%0A%09%09%09%09%09%09fix.getNavigationalStatus().isPresent() ? NavigationalStatus%0A%09%09%09%09%09%09%09%09.values()%5Bfix.getNavigationalStatus().get()%0A%09%09%09%09%09%09%09%09.ordinal()%5D : NavigationalStatus.UNKNOWN)%0A%09%09%09%09// build%0A%09%09%09%09.build();%0A%09%7D%0A%0A%09private static Optional%3CDouble%3E toDouble(Optional%3CFloat%3E value) %7B%0A%09%09if (!value.isPresent())%0A%09%09%09return Optional.absent();%0A%09%09else%0A%09%09%09return Optional.of((double) value.get());%0A%09%7D%0A%0A%09private static Optional%3CDouble%3E times(Optional%3CFloat%3E value, double factor) %7B%0A%09%09if (!value.isPresent())%0A%09%09%09return Optional.absent();%0A%09%09else%0A%09%09%09return Optional.of((double) value.get() * factor);%0A%09%7D%0A%0A%7D%0A

add conversion from Fix to VesselPosition