package au.gov.amsa.navigation;
import java.util.concurrent.TimeUnit;
import com.google.common.base.Optional;
import au.gov.amsa.navigation.VesselPosition.NavigationalStatus;
import au.gov.amsa.risky.format.AisClass;
import au.gov.amsa.risky.format.Fix;
import au.gov.amsa.risky.format.HasFix;
import rx.functions.Func1;
public class VesselPositions {
private static final double KNOTS_TO_METRES_PER_SECOND = 1852.0 / TimeUnit.HOURS.toSeconds(1);
// TODO unit test
public static VesselPosition toVesselPosition(Fix fix, Optional<?> data) {
return VesselPosition.builder().id(new Mmsi(fix.mmsi())).lat(fix.lat()).lon(fix.lon())
.time(fix.time()).cls(fix.aisClass() == AisClass.A ? VesselClass.A : VesselClass.B)
.cogDegrees(toDouble(fix.courseOverGroundDegrees()))
.headingDegrees(toDouble(fix.headingDegrees()))
.speedMetresPerSecond(
multiply(fix.speedOverGroundKnots(), KNOTS_TO_METRES_PER_SECOND))
.navigationalStatus(fix.navigationalStatus().isPresent()
? NavigationalStatus.values()[fix.navigationalStatus().get().ordinal()]
: NavigationalStatus.NOT_DEFINED)
.positionAisNmea(Optional.<String> absent())
.shipStaticAisNmea(Optional.<String> absent())
// set data
.data(data)
// build
.build();
}
public static Func1<HasFix, VesselPosition> TO_VESSEL_POSITION = fix -> toVesselPosition(
fix.fix(), Optional.absent());
public static <T extends HasFix> Func1<T, VesselPosition> toVesselPosition(
final Func1<T, Optional<?>> dataExtractor) {
return fix -> toVesselPosition(fix.fix(), dataExtractor.call(fix));
}
private static Optional<Double> toDouble(Optional<Float> value) {
if (!value.isPresent())
return Optional.absent();
else
return Optional.of((double) value.get());
}
private static Optional<Double> multiply(Optional<Float> value, double factor) {
if (!value.isPresent())
return Optional.absent();
else
return Optional.of((double) value.get() * factor);
}
}