package au.gov.amsa.geo.adhoc;
import java.io.File;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import au.gov.amsa.ais.ShipTypeDecoder;
import au.gov.amsa.gt.Shapefile;
import au.gov.amsa.navigation.ShipStaticData;
import au.gov.amsa.navigation.ShipStaticData.Info;
import au.gov.amsa.risky.format.BinaryFixes;
import au.gov.amsa.risky.format.Fix;
import au.gov.amsa.util.Files;
import rx.Observable;
import rx.functions.Func2;
public class CountCrossingsIntoRegionMain {
private static final Logger log = LoggerFactory.getLogger(CountCrossingsIntoRegionMain.class);
public static void main(String[] args) {
String shape = "/home/dxm/temp/amsa_atba_ningaloo_reef_pl.shp";
// String shape = "/home/dxm/temp/amb06_map_eez_pl.shp";
Shapefile region = Shapefile.from(new File(shape));
// test load
region.contains(0, 0);
Func2<Fix, Fix, Integer> ascendingTime = (a, b) -> ((Long) a.time()).compareTo(b.time());
Map<Integer, Info> ships = ShipStaticData.getMapFromResource("/ship-data.txt");
Pattern pattern = Pattern.compile(".*\\.track");
List<File> files = Files.find(new File("/media/an/binary-fixes-5-minute/2012"), pattern);
files.addAll(Files.find(new File("/media/an/binary-fixes-5-minute/2013"), pattern));
files.addAll(Files.find(new File("/media/an/binary-fixes-5-minute/2014"), pattern));
files.addAll(Files.find(new File("/media/an/binary-fixes-5-minute/2015"), pattern));
log.info("files=" + files.size());
int count = Observable.from(files)
// .doOnNext(System.out::println)
.concatMap(file -> detectCrossings(file, region))
// count out to in crossings
.toSortedList(ascendingTime).flatMap(o -> Observable.from(o))
// log
.doOnNext(fix -> {
Info info = ships.get(fix.mmsi());
if (info != null) {
String type;
if (info.shipType.isPresent())
type = ShipTypeDecoder.getShipType(info.shipType.get());
else
type = "UNKNOWN";
String t = DateTimeFormatter.ISO_DATE_TIME.format(ZonedDateTime
.ofInstant(Instant.ofEpochMilli(fix.time()), ZoneId.of("UTC")));
System.out.println(t + ", mmsi=" + fix.mmsi() + ", class="
+ fix.aisClass().name() + ", lengthMetres="
+ info.lengthMetres().orNull() + ", type=" + type + ", lat="
+ fix.lat() + ", lon=" + fix.lon());
}
}).count().toBlocking().single();
System.out.println("count=" + count);
}
private static Observable<Fix> detectCrossings(File file, Shapefile region) {
return BinaryFixes.from(file)
// log
// .lift(Logging.<Fix>
// logger().showCount().every(100000).log())
.filter(fix -> fix.mmsi() != 0)
// add in or out of region
.map(fix -> new FixAndRegion(fix, region.contains(fix.lat(), fix.lon())))
// detect changes in being in
// our out of region
.distinctUntilChanged(fix -> fix.inRegion)
// pair them up
.buffer(2)
// just get out of region to
// inside region
.filter(list -> list.size() == 2 && !list.get(0).inRegion && list.get(1).inRegion)
// get the fix inside the region
.map(list -> list.get(1).fix);
}
private static class FixAndRegion {
final Fix fix;
final boolean inRegion;
FixAndRegion(Fix fix, boolean inRegion) {
super();
this.fix = fix;
this.inRegion = inRegion;
}
}
}