From f413879b0519bf0772c0a4abaa1304f7b4e0410a Mon Sep 17 00:00:00 2001 From: scrudden Date: Tue, 25 Feb 2020 19:51:02 +0000 Subject: [PATCH 01/17] Integrating with services changes gtfs-rt. --- transitclock/pom.xml | 4 +-- .../GtfsRtVehiclePositionsReaderBase.java | 28 +++++++++++++++++++ .../transitclock/statistics/Statistics.java | 6 ++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/transitclock/pom.xml b/transitclock/pom.xml index 37914354c..06d009920 100755 --- a/transitclock/pom.xml +++ b/transitclock/pom.xml @@ -139,9 +139,9 @@ - com.google.transit + io.mobilitydata.transit gtfs-realtime-bindings - 0.0.4 + 0.0.6-SNAPSHOT diff --git a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java index cf86de367..6c8f7ed7c 100644 --- a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java +++ b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java @@ -35,7 +35,10 @@ import com.google.transit.realtime.GtfsRealtime.FeedEntity; import com.google.transit.realtime.GtfsRealtime.FeedMessage; import com.google.transit.realtime.GtfsRealtime.Position; +import com.google.transit.realtime.GtfsRealtime.Shape; import com.google.transit.realtime.GtfsRealtime.TripDescriptor; +import com.google.transit.realtime.GtfsRealtime.TripProperties; +import com.google.transit.realtime.GtfsRealtime.TripUpdate; import com.google.transit.realtime.GtfsRealtime.VehicleDescriptor; import com.google.transit.realtime.GtfsRealtime.VehiclePosition; @@ -125,6 +128,30 @@ private void processMessage(FeedMessage message) { int counter = 0; for (FeedEntity entity : message.getEntityList()) { // If no vehicles in the entity then nothing to process + + if(entity.hasTripUpdate()) + { + TripUpdate tripUpdate = entity.getTripUpdate(); + if(tripUpdate.hasTripProperties()) + { + TripProperties tripProperties = tripUpdate.getTripProperties(); + if(tripProperties.hasShapeId()) + { + tripProperties.getShapeId(); + + if(entity.hasShape()) + { + Shape shape = entity.getShape(); + shape.getShapeId(); + if(tripProperties.getShapeId().equals(shape.getShapeId())) + { + logger.debug("Have found shape update to process.",tripUpdate.toString()); + } + } + } + } + } + if (!entity.hasVehicle()) continue; @@ -263,6 +290,7 @@ public void process() { // it never seemed to complete, even for just a single call to // parseFrom(). Therefore loading in entire file at once. FeedMessage feed = FeedMessage.parseFrom(codedStream); + logger.info("Parsing GTFS-realtime file into a FeedMessage took " + "{} msec", timer.elapsedMsec()); diff --git a/transitclock/src/main/java/org/transitclock/statistics/Statistics.java b/transitclock/src/main/java/org/transitclock/statistics/Statistics.java index f3eb94e31..6d02b418f 100644 --- a/transitclock/src/main/java/org/transitclock/statistics/Statistics.java +++ b/transitclock/src/main/java/org/transitclock/statistics/Statistics.java @@ -351,9 +351,9 @@ public static double getSampleStandardDeviation(double[] values, double mean) { * Just for testing */ public static void main(String args[]) { - Integer a[] = {56449, 45916, 33983, 1237582, 32739}; - Statistics.filteredMean(Arrays.asList(a), 0.7); - + Integer a[] = {12, 41, 24, 5,10}; + int filteredmean = Statistics.filteredMean(Arrays.asList(a), 0); + System.out.println("Filtered mean=" + filteredmean + " mean="+mean(Arrays.asList(a))); Integer array[] = {2,4, 3};//, 4, 4, 4, 5, 5, 7, 9}; List values = Arrays.asList(array); From 4d1177d63bed012234c3b19b578649abd8f078a9 Mon Sep 17 00:00:00 2001 From: scrudden Date: Tue, 25 Feb 2020 20:19:44 +0000 Subject: [PATCH 02/17] Start on model for detours. --- .../core/diversion/model/detour.java | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java new file mode 100644 index 000000000..40a0387e6 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java @@ -0,0 +1,110 @@ +package org.transitclock.core.diversion.model; + +import java.util.List; + +import org.transitclock.db.structs.Location; +import org.transitclock.db.structs.Route; +import org.transitclock.db.structs.Trip; + +/** + * @author Sean Óg Crudden + * This is the starting point of modeling a detour. + */ +public class detour { + + private Route routeId; + + private Trip tripId; + + private int startStopSeq; + + private int distanceStartAlongSegment; + + private int returnStopSeq; + + private int distanceEndAlongSegment; + + private List detourPath; + + private List stopLocations; + + public detour(Route routeId, Trip tripId, int startStopSeq, int distanceStartAlongSegment, int returnStopSeq, + int distanceEndAlongSegment, List detourPath, List stopLocations) { + super(); + this.routeId = routeId; + this.tripId = tripId; + this.startStopSeq = startStopSeq; + this.distanceStartAlongSegment = distanceStartAlongSegment; + this.returnStopSeq = returnStopSeq; + this.distanceEndAlongSegment = distanceEndAlongSegment; + this.detourPath = detourPath; + this.stopLocations = stopLocations; + } + + public Route getRouteId() { + return routeId; + } + + public void setRouteId(Route routeId) { + this.routeId = routeId; + } + + public Trip getTripId() { + return tripId; + } + + public void setTripId(Trip tripId) { + this.tripId = tripId; + } + + public int getStartStopSeq() { + return startStopSeq; + } + + public void setStartStopSeq(int startStopSeq) { + this.startStopSeq = startStopSeq; + } + + public int getDistanceStartAlongSegment() { + return distanceStartAlongSegment; + } + + public void setDistanceStartAlongSegment(int distanceStartAlongSegment) { + this.distanceStartAlongSegment = distanceStartAlongSegment; + } + + public int getReturnStopSeq() { + return returnStopSeq; + } + + public void setReturnStopSeq(int returnStopSeq) { + this.returnStopSeq = returnStopSeq; + } + + public int getDistanceEndAlongSegment() { + return distanceEndAlongSegment; + } + + public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { + this.distanceEndAlongSegment = distanceEndAlongSegment; + } + + public List getDetourPath() { + return detourPath; + } + + public void setDetourPath(List detourPath) { + this.detourPath = detourPath; + } + + public List getStopLocations() { + return stopLocations; + } + + public void setStopLocations(List stopLocations) { + this.stopLocations = stopLocations; + } + + + +} From 69a3026d176d300aef2d9fd333db585b21ba9555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sean=20=C3=93g=20Crudden?= Date: Thu, 27 Feb 2020 18:02:55 +0000 Subject: [PATCH 03/17] WIP on GTFS-NewShapes piece of GTFS-rt Service Changes v3. --- .../core/diversion/cache/DiversionCache.java | 8 + .../diversion/cache/DiversionCacheImpl.java | 56 +++++ .../cache/DiversionsCacheFactory.java | 23 ++ .../core/diversion/cache/DiversionsKey.java | 14 ++ .../core/diversion/cache/DiversionsList.java | 57 +++++ .../core/diversion/model/Diversion.java | 223 ++++++++++++++++ .../core/diversion/model/detour.java | 110 -------- .../db/hibernate/AnnotatedClassesList.java | 2 + .../transitclock/db/structs/Diversion.java | 238 ++++++++++++++++++ .../GtfsRtVehiclePositionsReaderBase.java | 22 +- .../transitclock/ipc/data/IpcDiversions.java | 5 + .../ipc/interfaces/DiversionsInterface.java | 10 + .../ipc/servers/DiversionsServer.java | 26 ++ transitclock/src/main/resources/ehcache.xml | 16 +- .../transitclock/api/data/ApiDiversion.java | 5 + .../transitclock/api/data/ApiDiversions.java | 5 + .../api/rootResources/DiversionApi.java | 48 ++++ 17 files changed, 755 insertions(+), 113 deletions(-) create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCache.java create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCacheImpl.java create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsCacheFactory.java create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java delete mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java create mode 100644 transitclock/src/main/java/org/transitclock/db/structs/Diversion.java create mode 100644 transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java create mode 100644 transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java create mode 100644 transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java create mode 100644 transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java create mode 100644 transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java create mode 100644 transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCache.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCache.java new file mode 100644 index 000000000..29c8c30ea --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCache.java @@ -0,0 +1,8 @@ +package org.transitclock.core.diversion.cache; + +import org.transitclock.core.diversion.model.Diversion; + +public interface DiversionCache { + DiversionsList getDiversions(DiversionsKey key); + void putDiversion(Diversion diversion); +} diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCacheImpl.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCacheImpl.java new file mode 100644 index 000000000..5f9242f19 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionCacheImpl.java @@ -0,0 +1,56 @@ +package org.transitclock.core.diversion.cache; + +import java.util.List; + +import org.ehcache.Cache; +import org.ehcache.CacheManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.transitclock.core.dataCache.ehcache.CacheManagerFactory; +import org.transitclock.core.diversion.model.Diversion; + +public class DiversionCacheImpl implements DiversionCache { + + final private static String cacheName = "diversionsCache"; + private static final Logger logger = LoggerFactory.getLogger(DiversionCacheImpl.class); + + private Cache cache = null; + + @Override + public DiversionsList getDiversions(DiversionsKey key) { + + return cache.get(key); + } + + public DiversionCacheImpl() { + CacheManager cm = CacheManagerFactory.getInstance(); + + cache = cm.getCache(cacheName, DiversionsKey.class, DiversionsList.class); + } + + @Override + public void putDiversion(Diversion diversion) { + DiversionsList result = cache.get(new DiversionsKey(diversion)); + if(result==null) + result = new DiversionsList(); + + if(!inList(result.getDiversions(),diversion)) + { + result.addDiversion(diversion); + + cache.put(new DiversionsKey(diversion), result); + } + } + private boolean inList(List list, Diversion diversion) + { + for(Diversion item:list) + { + if(item.equals(diversion)) + { + return true; + } + } + return false; + } + +} diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsCacheFactory.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsCacheFactory.java new file mode 100644 index 000000000..f417ae8e6 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsCacheFactory.java @@ -0,0 +1,23 @@ +package org.transitclock.core.diversion.cache; + +import org.transitclock.config.StringConfigValue; +import org.transitclock.utils.ClassInstantiator; + +public class DiversionsCacheFactory { + private static StringConfigValue className = + new StringConfigValue("transitclock.core.cache.diversionsCache", + "org.transitclock.core.diversion.cache.DiversionCacheImpl", + "Specifies the class used to cache diversions."); + + private static DiversionCache singleton = null; + + public static DiversionCache getInstance() { + + if (singleton == null) { + singleton = ClassInstantiator.instantiate(className.getValue(), + DiversionCache.class); + } + + return singleton; + } +} diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java new file mode 100644 index 000000000..4228b51d1 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java @@ -0,0 +1,14 @@ +package org.transitclock.core.diversion.cache; + +import org.transitclock.core.diversion.model.Diversion; + +public class DiversionsKey { + String tripId; + String routeId; + + public DiversionsKey(Diversion diversion) { + this.tripId=diversion.getTripId(); + this.routeId=diversion.getTripId(); + } + +} diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java new file mode 100644 index 000000000..b7c9e62e9 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java @@ -0,0 +1,57 @@ +package org.transitclock.core.diversion.cache; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +import org.transitclock.core.diversion.model.Diversion; + +public class DiversionsList implements Serializable { + + /** + * + */ + private static final long serialVersionUID = -6633598451497950140L; + + List diversions=null; + + public List getDiversions() { + return diversions; + } + + public void setEvents(List diversions) { + this.diversions = diversions; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((diversions == null) ? 0 : diversions.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DiversionsList other = (DiversionsList) obj; + if (diversions == null) { + if (other.diversions != null) + return false; + } else if (!diversions.equals(other.diversions)) + return false; + return true; + } + void addDiversion(Diversion diversion) + { + if(this.diversions==null) + diversions=new ArrayList(); + else + diversions.add(diversion); + } +} diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java new file mode 100644 index 000000000..e63986aa1 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java @@ -0,0 +1,223 @@ +package org.transitclock.core.diversion.model; + +import java.util.Date; +import java.util.List; + +import org.transitclock.db.structs.Location; +import org.transitclock.db.structs.Route; +import org.transitclock.db.structs.Trip; + +/** + * @author Sean Óg Crudden + * This is the starting point of modeling a detour. + */ +public class Diversion { + + private String routeId; + + private String tripId; + + private String shapeId; + + private int startStopSeq; + + private int distanceStartAlongSegment; + + private int returnStopSeq; + + private int distanceEndAlongSegment; + + private List detourPath; + + private List stopLocations; + + private Date startTime; + + private Date endTime; + + public Diversion() { + super(); + // TODO Auto-generated constructor stub + } + + public Diversion(String routeId, String tripId,String shapeId, int startStopSeq, int distanceStartAlongSegment, int returnStopSeq, + int distanceEndAlongSegment, List detourPath, List stopLocations, Date startTime, Date endTime) { + super(); + this.routeId = routeId; + this.tripId = tripId; + this.shapeId = shapeId; + this.startStopSeq = startStopSeq; + this.distanceStartAlongSegment = distanceStartAlongSegment; + this.returnStopSeq = returnStopSeq; + this.distanceEndAlongSegment = distanceEndAlongSegment; + this.detourPath = detourPath; + this.stopLocations = stopLocations; + this.startTime=startTime; + this.endTime=endTime; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + public String getRouteId() { + return routeId; + } + + public void setRouteId(String routeId) { + this.routeId = routeId; + } + + public String getTripId() { + return tripId; + } + + public void setTripId(String tripId) { + this.tripId = tripId; + } + + public int getStartStopSeq() { + return startStopSeq; + } + + public void setStartStopSeq(int startStopSeq) { + this.startStopSeq = startStopSeq; + } + + public int getDistanceStartAlongSegment() { + return distanceStartAlongSegment; + } + + public void setDistanceStartAlongSegment(int distanceStartAlongSegment) { + this.distanceStartAlongSegment = distanceStartAlongSegment; + } + + public int getReturnStopSeq() { + return returnStopSeq; + } + + public void setReturnStopSeq(int returnStopSeq) { + this.returnStopSeq = returnStopSeq; + } + + public int getDistanceEndAlongSegment() { + return distanceEndAlongSegment; + } + + public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { + this.distanceEndAlongSegment = distanceEndAlongSegment; + } + + public List getDetourPath() { + return detourPath; + } + + public void setDetourPath(List detourPath) { + this.detourPath = detourPath; + } + + public List getStopLocations() { + return stopLocations; + } + + public void setStopLocations(List stopLocations) { + this.stopLocations = stopLocations; + } + + public String getShapeId() { + return shapeId; + } + + public void setShapeId(String shapeId) { + this.shapeId = shapeId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((detourPath == null) ? 0 : detourPath.hashCode()); + result = prime * result + distanceEndAlongSegment; + result = prime * result + distanceStartAlongSegment; + result = prime * result + ((endTime == null) ? 0 : endTime.hashCode()); + result = prime * result + returnStopSeq; + result = prime * result + ((routeId == null) ? 0 : routeId.hashCode()); + result = prime * result + ((shapeId == null) ? 0 : shapeId.hashCode()); + result = prime * result + startStopSeq; + result = prime * result + ((startTime == null) ? 0 : startTime.hashCode()); + result = prime * result + ((stopLocations == null) ? 0 : stopLocations.hashCode()); + result = prime * result + ((tripId == null) ? 0 : tripId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Diversion other = (Diversion) obj; + if (detourPath == null) { + if (other.detourPath != null) + return false; + } else if (!detourPath.equals(other.detourPath)) + return false; + if (distanceEndAlongSegment != other.distanceEndAlongSegment) + return false; + if (distanceStartAlongSegment != other.distanceStartAlongSegment) + return false; + if (endTime == null) { + if (other.endTime != null) + return false; + } else if (!endTime.equals(other.endTime)) + return false; + if (returnStopSeq != other.returnStopSeq) + return false; + if (routeId == null) { + if (other.routeId != null) + return false; + } else if (!routeId.equals(other.routeId)) + return false; + if (shapeId == null) { + if (other.shapeId != null) + return false; + } else if (!shapeId.equals(other.shapeId)) + return false; + if (startStopSeq != other.startStopSeq) + return false; + if (startTime == null) { + if (other.startTime != null) + return false; + } else if (!startTime.equals(other.startTime)) + return false; + if (stopLocations == null) { + if (other.stopLocations != null) + return false; + } else if (!stopLocations.equals(other.stopLocations)) + return false; + if (tripId == null) { + if (other.tripId != null) + return false; + } else if (!tripId.equals(other.tripId)) + return false; + return true; + } + + + + +} diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java deleted file mode 100644 index 40a0387e6..000000000 --- a/transitclock/src/main/java/org/transitclock/core/diversion/model/detour.java +++ /dev/null @@ -1,110 +0,0 @@ -package org.transitclock.core.diversion.model; - -import java.util.List; - -import org.transitclock.db.structs.Location; -import org.transitclock.db.structs.Route; -import org.transitclock.db.structs.Trip; - -/** - * @author Sean Óg Crudden - * This is the starting point of modeling a detour. - */ -public class detour { - - private Route routeId; - - private Trip tripId; - - private int startStopSeq; - - private int distanceStartAlongSegment; - - private int returnStopSeq; - - private int distanceEndAlongSegment; - - private List detourPath; - - private List stopLocations; - - public detour(Route routeId, Trip tripId, int startStopSeq, int distanceStartAlongSegment, int returnStopSeq, - int distanceEndAlongSegment, List detourPath, List stopLocations) { - super(); - this.routeId = routeId; - this.tripId = tripId; - this.startStopSeq = startStopSeq; - this.distanceStartAlongSegment = distanceStartAlongSegment; - this.returnStopSeq = returnStopSeq; - this.distanceEndAlongSegment = distanceEndAlongSegment; - this.detourPath = detourPath; - this.stopLocations = stopLocations; - } - - public Route getRouteId() { - return routeId; - } - - public void setRouteId(Route routeId) { - this.routeId = routeId; - } - - public Trip getTripId() { - return tripId; - } - - public void setTripId(Trip tripId) { - this.tripId = tripId; - } - - public int getStartStopSeq() { - return startStopSeq; - } - - public void setStartStopSeq(int startStopSeq) { - this.startStopSeq = startStopSeq; - } - - public int getDistanceStartAlongSegment() { - return distanceStartAlongSegment; - } - - public void setDistanceStartAlongSegment(int distanceStartAlongSegment) { - this.distanceStartAlongSegment = distanceStartAlongSegment; - } - - public int getReturnStopSeq() { - return returnStopSeq; - } - - public void setReturnStopSeq(int returnStopSeq) { - this.returnStopSeq = returnStopSeq; - } - - public int getDistanceEndAlongSegment() { - return distanceEndAlongSegment; - } - - public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { - this.distanceEndAlongSegment = distanceEndAlongSegment; - } - - public List getDetourPath() { - return detourPath; - } - - public void setDetourPath(List detourPath) { - this.detourPath = detourPath; - } - - public List getStopLocations() { - return stopLocations; - } - - public void setStopLocations(List stopLocations) { - this.stopLocations = stopLocations; - } - - - -} diff --git a/transitclock/src/main/java/org/transitclock/db/hibernate/AnnotatedClassesList.java b/transitclock/src/main/java/org/transitclock/db/hibernate/AnnotatedClassesList.java index 691ff8ff1..7e9e7dd35 100644 --- a/transitclock/src/main/java/org/transitclock/db/hibernate/AnnotatedClassesList.java +++ b/transitclock/src/main/java/org/transitclock/db/hibernate/AnnotatedClassesList.java @@ -27,6 +27,7 @@ import org.transitclock.db.structs.ConfigRevision; import org.transitclock.db.structs.DbTest; import org.transitclock.db.structs.Departure; +import org.transitclock.db.structs.Diversion; import org.transitclock.db.structs.FareAttribute; import org.transitclock.db.structs.FareRule; import org.transitclock.db.structs.Frequency; @@ -107,6 +108,7 @@ public class AnnotatedClassesList { VehicleState.class, HoldingTime.class, Headway.class, + Diversion.class, // For website ApiKey.class, WebAgency.class, diff --git a/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java b/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java new file mode 100644 index 000000000..055bf931d --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java @@ -0,0 +1,238 @@ +package org.transitclock.db.structs; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import javax.persistence.Column; +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OrderColumn; +import javax.persistence.Table; + +import org.hibernate.annotations.DynamicUpdate; + +@Entity @DynamicUpdate +@Table(name="Diversions") +public class Diversion implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 1926444520257485356L; + + @Column + private String routeId; + + @Column + private String tripId; + + @Id + private String shapeId; + + @Column + private Date startTime; + + @Column + private Date endTime; + + @Column + private int startStopSeq; + + @Column + private int distanceStartAlongSegment; + + @Column + private int returnStopSeq; + + @Column + private int distanceEndAlongSegment; + + @ElementCollection + @OrderColumn + private List detourPath; + + @ElementCollection + @OrderColumn + private List stopLocations; + + public Diversion(String routeId, String tripId, String shapeId, Date startTime, Date endTime, int startStopSeq, + int distanceStartAlongSegment, int returnStopSeq, int distanceEndAlongSegment, List detourPath, + List stopLocations) { + super(); + this.routeId = routeId; + this.tripId = tripId; + this.shapeId = shapeId; + this.startTime = startTime; + this.endTime = endTime; + this.startStopSeq = startStopSeq; + this.distanceStartAlongSegment = distanceStartAlongSegment; + this.returnStopSeq = returnStopSeq; + this.distanceEndAlongSegment = distanceEndAlongSegment; + this.detourPath = detourPath; + this.stopLocations = stopLocations; + } + + public String getRouteId() { + return routeId; + } + + public void setRouteId(String routeId) { + this.routeId = routeId; + } + + public String getTripId() { + return tripId; + } + + public void setTripId(String tripId) { + this.tripId = tripId; + } + + public String getShapeId() { + return shapeId; + } + + public void setShapeId(String shapeId) { + this.shapeId = shapeId; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + public int getStartStopSeq() { + return startStopSeq; + } + + public void setStartStopSeq(int startStopSeq) { + this.startStopSeq = startStopSeq; + } + + public int getDistanceStartAlongSegment() { + return distanceStartAlongSegment; + } + + public void setDistanceStartAlongSegment(int distanceStartAlongSegment) { + this.distanceStartAlongSegment = distanceStartAlongSegment; + } + + public int getReturnStopSeq() { + return returnStopSeq; + } + + public void setReturnStopSeq(int returnStopSeq) { + this.returnStopSeq = returnStopSeq; + } + + public int getDistanceEndAlongSegment() { + return distanceEndAlongSegment; + } + + public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { + this.distanceEndAlongSegment = distanceEndAlongSegment; + } + + public List getDetourPath() { + return detourPath; + } + + public void setDetourPath(List detourPath) { + this.detourPath = detourPath; + } + + public List getStopLocations() { + return stopLocations; + } + + public void setStopLocations(List stopLocations) { + this.stopLocations = stopLocations; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((detourPath == null) ? 0 : detourPath.hashCode()); + result = prime * result + distanceEndAlongSegment; + result = prime * result + distanceStartAlongSegment; + result = prime * result + ((endTime == null) ? 0 : endTime.hashCode()); + result = prime * result + returnStopSeq; + result = prime * result + ((routeId == null) ? 0 : routeId.hashCode()); + result = prime * result + ((shapeId == null) ? 0 : shapeId.hashCode()); + result = prime * result + startStopSeq; + result = prime * result + ((startTime == null) ? 0 : startTime.hashCode()); + result = prime * result + ((stopLocations == null) ? 0 : stopLocations.hashCode()); + result = prime * result + ((tripId == null) ? 0 : tripId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Diversion other = (Diversion) obj; + if (detourPath == null) { + if (other.detourPath != null) + return false; + } else if (!detourPath.equals(other.detourPath)) + return false; + if (distanceEndAlongSegment != other.distanceEndAlongSegment) + return false; + if (distanceStartAlongSegment != other.distanceStartAlongSegment) + return false; + if (endTime == null) { + if (other.endTime != null) + return false; + } else if (!endTime.equals(other.endTime)) + return false; + if (returnStopSeq != other.returnStopSeq) + return false; + if (routeId == null) { + if (other.routeId != null) + return false; + } else if (!routeId.equals(other.routeId)) + return false; + if (shapeId == null) { + if (other.shapeId != null) + return false; + } else if (!shapeId.equals(other.shapeId)) + return false; + if (startStopSeq != other.startStopSeq) + return false; + if (startTime == null) { + if (other.startTime != null) + return false; + } else if (!startTime.equals(other.startTime)) + return false; + if (stopLocations == null) { + if (other.stopLocations != null) + return false; + } else if (!stopLocations.equals(other.stopLocations)) + return false; + if (tripId == null) { + if (other.tripId != null) + return false; + } else if (!tripId.equals(other.tripId)) + return false; + return true; + } + + +} diff --git a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java index 6c8f7ed7c..653df5d3b 100644 --- a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java +++ b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java @@ -25,8 +25,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.transitclock.core.diversion.cache.DiversionsCacheFactory; +import org.transitclock.core.diversion.model.Diversion; import org.transitclock.db.structs.AvlReport; import org.transitclock.db.structs.AvlReport.AssignmentType; +import org.transitclock.db.structs.Location; import org.transitclock.utils.IntervalTimer; import org.transitclock.utils.MathUtils; import org.transitclock.utils.Time; @@ -36,6 +39,7 @@ import com.google.transit.realtime.GtfsRealtime.FeedMessage; import com.google.transit.realtime.GtfsRealtime.Position; import com.google.transit.realtime.GtfsRealtime.Shape; +import com.google.transit.realtime.GtfsRealtime.ShapePoint; import com.google.transit.realtime.GtfsRealtime.TripDescriptor; import com.google.transit.realtime.GtfsRealtime.TripProperties; import com.google.transit.realtime.GtfsRealtime.TripUpdate; @@ -143,8 +147,22 @@ private void processMessage(FeedMessage message) { { Shape shape = entity.getShape(); shape.getShapeId(); - if(tripProperties.getShapeId().equals(shape.getShapeId())) - { + + if(tripProperties.getShapeId().equals(shape.getShapeId())) + { + Diversion detour=new Diversion(); + detour.setTripId(tripUpdate.getTrip().getTripId()); + detour.setRouteId(tripUpdate.getTrip().getRouteId()); + + for(ShapePoint shapePoint : shape.getShapePointList()) + { + Location location=new Location(shapePoint.getShapePtLat(), shapePoint.getShapePtLon()); + detour.getStopLocations().add(location); + } + + if(DiversionsCacheFactory.getInstance()!=null) + DiversionsCacheFactory.getInstance().putDiversion(detour); + logger.debug("Have found shape update to process.",tripUpdate.toString()); } } diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java new file mode 100644 index 000000000..b67d60920 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java @@ -0,0 +1,5 @@ +package org.transitclock.ipc.data; + +public class IpcDiversions { + +} diff --git a/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java b/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java new file mode 100644 index 000000000..577422750 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java @@ -0,0 +1,10 @@ +package org.transitclock.ipc.interfaces; + +import java.rmi.Remote; + +import org.transitclock.ipc.data.IpcDiversions; + +public interface DiversionsInterface extends Remote { + IpcDiversions getDiversionsForTrip(String tripId); + IpcDiversions getDiversionsForRoute(String routeId); +} diff --git a/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java new file mode 100644 index 000000000..da129cfeb --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java @@ -0,0 +1,26 @@ +package org.transitclock.ipc.servers; + +import org.transitclock.ipc.data.IpcDiversions; +import org.transitclock.ipc.interfaces.DiversionsInterface; +import org.transitclock.ipc.rmi.AbstractServer; + +public class DiversionsServer extends AbstractServer implements DiversionsInterface { + + protected DiversionsServer(String agencyId, String objectName) { + super(agencyId, objectName); + // TODO Auto-generated constructor stub + } + + @Override + public IpcDiversions getDiversionsForTrip(String tripId) { + // TODO Auto-generated method stub + return null; + } + + @Override + public IpcDiversions getDiversionsForRoute(String routeId) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/transitclock/src/main/resources/ehcache.xml b/transitclock/src/main/resources/ehcache.xml index e8ca78cab..e930c648a 100644 --- a/transitclock/src/main/resources/ehcache.xml +++ b/transitclock/src/main/resources/ehcache.xml @@ -5,7 +5,21 @@ xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.1.xsd"> - + + + org.transitclock.core.diversion.model.Diversion.DiversionsKey + org.transitclock.core.diversion.cache.DiversionsList + + 1 + + + 2000 + 100 + 200 + + + org.transitclock.core.dataCache.StopPathCacheKey diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java new file mode 100644 index 000000000..c9d0e1fcb --- /dev/null +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java @@ -0,0 +1,5 @@ +package org.transitclock.api.data; + +public class ApiDiversion { + +} diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java new file mode 100644 index 000000000..a0c0c5281 --- /dev/null +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java @@ -0,0 +1,5 @@ +package org.transitclock.api.data; + +public class ApiDiversions { + +} diff --git a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java new file mode 100644 index 000000000..e1553dbd3 --- /dev/null +++ b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java @@ -0,0 +1,48 @@ +package org.transitclock.api.rootResources; + +import javax.ws.rs.BeanParam; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.transitclock.api.data.ApiCacheDetails; +import org.transitclock.api.data.ApiDiversion; +import org.transitclock.api.data.ApiDiversions; +import org.transitclock.api.utils.StandardParameters; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; + +@Path("/key/{key}/agency/{agency}") +public class DiversionApi { + @Path("/command/getDiversionsByRoute") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Operation(summary="Get list of active diversions for a route.", + description="This is to give the means of manually setting a vehicle unpredictable and unassigned so it will be reassigned quickly.", + tags= {"command","vehicle"}) + public Response getDiversionsByRouteId(@BeanParam StandardParameters stdParameters, + @Parameter(description="routeId to get diversions for.",required=true) @PathParam("routeId") String routeId) + { + stdParameters.validate(); + + return stdParameters.createResponse(new ApiDiversions()); + } + @Path("/command/getDiversionsByTrip") + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + @Operation(summary="Get a list of active diversions for a trip", + description="This is to give the means of manually setting a vehicle unpredictable and unassigned so it will be reassigned quickly.", + tags= {"command","vehicle"}) + public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameters, + @Parameter(description="tripId to get diversions for.",required=true) @PathParam("tripId") String tripId) + { + stdParameters.validate(); + + + return stdParameters.createResponse(new ApiDiversions()); + } +} From 5ea59d78acda1f60b805de2daf43889ea1d57231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sean=20=C3=93g=20Crudden?= Date: Fri, 28 Feb 2020 19:25:44 +0000 Subject: [PATCH 04/17] More scaffolding for diversions. --- .../transitclock/ipc/data/IpcDiversion.java | 147 ++++++++++++++++++ .../transitclock/ipc/data/IpcDiversions.java | 18 ++- .../transitclock/api/data/ApiDiversion.java | 142 +++++++++++++++++ .../transitclock/api/data/ApiDiversions.java | 30 ++++ 4 files changed, 336 insertions(+), 1 deletion(-) create mode 100644 transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java new file mode 100644 index 000000000..0b3731738 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java @@ -0,0 +1,147 @@ +package org.transitclock.ipc.data; + +import java.io.Serializable; +import java.util.Date; +import java.util.List; + +import org.transitclock.db.structs.Location; + +public class IpcDiversion implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 2548744289428304091L; + + private String routeId; + + private String tripId; + + private String shapeId; + + private int startStopSeq; + + private int distanceStartAlongSegment; + + private int returnStopSeq; + + private int distanceEndAlongSegment; + + private List detourPath; + + private List stopLocations; + + private Date startTime; + + private Date endTime; + + public IpcDiversion() { + super(); + // TODO Auto-generated constructor stub + } + + public IpcDiversion(String routeId, String tripId, String shapeId, int startStopSeq, int distanceStartAlongSegment, + int returnStopSeq, int distanceEndAlongSegment, List detourPath, List stopLocations, + Date startTime, Date endTime) { + super(); + this.routeId = routeId; + this.tripId = tripId; + this.shapeId = shapeId; + this.startStopSeq = startStopSeq; + this.distanceStartAlongSegment = distanceStartAlongSegment; + this.returnStopSeq = returnStopSeq; + this.distanceEndAlongSegment = distanceEndAlongSegment; + this.detourPath = detourPath; + this.stopLocations = stopLocations; + this.startTime = startTime; + this.endTime = endTime; + } + + public String getRouteId() { + return routeId; + } + + public void setRouteId(String routeId) { + this.routeId = routeId; + } + + public String getTripId() { + return tripId; + } + + public void setTripId(String tripId) { + this.tripId = tripId; + } + + public String getShapeId() { + return shapeId; + } + + public void setShapeId(String shapeId) { + this.shapeId = shapeId; + } + + public int getStartStopSeq() { + return startStopSeq; + } + + public void setStartStopSeq(int startStopSeq) { + this.startStopSeq = startStopSeq; + } + + public int getDistanceStartAlongSegment() { + return distanceStartAlongSegment; + } + + public void setDistanceStartAlongSegment(int distanceStartAlongSegment) { + this.distanceStartAlongSegment = distanceStartAlongSegment; + } + + public int getReturnStopSeq() { + return returnStopSeq; + } + + public void setReturnStopSeq(int returnStopSeq) { + this.returnStopSeq = returnStopSeq; + } + + public int getDistanceEndAlongSegment() { + return distanceEndAlongSegment; + } + + public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { + this.distanceEndAlongSegment = distanceEndAlongSegment; + } + + public List getDetourPath() { + return detourPath; + } + + public void setDetourPath(List detourPath) { + this.detourPath = detourPath; + } + + public List getStopLocations() { + return stopLocations; + } + + public void setStopLocations(List stopLocations) { + this.stopLocations = stopLocations; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + +} diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java index b67d60920..8be99ccc6 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java @@ -1,5 +1,21 @@ package org.transitclock.ipc.data; -public class IpcDiversions { +import java.io.Serializable; +import java.util.List; +public class IpcDiversions implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 7884832425433350816L; + + private final List diversions; + + public IpcDiversions(List diversions) { + super(); + this.diversions = diversions; + } + public List getDiversions() { + return diversions; + } } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java index c9d0e1fcb..f6b4e1e4b 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java @@ -1,5 +1,147 @@ package org.transitclock.api.data; +import java.util.Date; +import java.util.List; + +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +import org.transitclock.db.structs.Location; +import org.transitclock.ipc.data.IpcDiversion; +@XmlRootElement(name = "diversion") public class ApiDiversion { + @XmlAttribute + private String routeId; + @XmlAttribute + private String tripId; + @XmlAttribute + private String shapeId; + @XmlAttribute + private int startStopSeq; + @XmlAttribute + private int distanceStartAlongSegment; + @XmlAttribute + private int returnStopSeq; + @XmlAttribute + private int distanceEndAlongSegment; + @XmlAttribute + private List detourPath; + @XmlAttribute + private List stopLocations; + @XmlAttribute + private Date startTime; + @XmlAttribute + private Date endTime; + + /** + * Need a no-arg constructor for Jersey. Otherwise get really obtuse + * "MessageBodyWriter not found for media type=application/json" exception. + */ + public ApiDiversion() { + + } + + public ApiDiversion(IpcDiversion diversion) + { + this.startStopSeq=diversion.getStartStopSeq(); + this.returnStopSeq=diversion.getReturnStopSeq(); + this.routeId=diversion.getRouteId(); + this.shapeId=diversion.getShapeId(); + this.tripId=diversion.getTripId(); + this.distanceStartAlongSegment=diversion.getDistanceStartAlongSegment(); + this.distanceStartAlongSegment=diversion.getDistanceStartAlongSegment(); + this.detourPath=diversion.getDetourPath(); + this.stopLocations=diversion.getStopLocations(); + this.startTime=diversion.getStartTime(); + this.endTime=diversion.getEndTime(); + } + + public String getRouteId() { + return routeId; + } + + public void setRouteId(String routeId) { + this.routeId = routeId; + } + + public String getTripId() { + return tripId; + } + + public void setTripId(String tripId) { + this.tripId = tripId; + } + + public String getShapeId() { + return shapeId; + } + + public void setShapeId(String shapeId) { + this.shapeId = shapeId; + } + + public int getStartStopSeq() { + return startStopSeq; + } + + public void setStartStopSeq(int startStopSeq) { + this.startStopSeq = startStopSeq; + } + + public int getDistanceStartAlongSegment() { + return distanceStartAlongSegment; + } + + public void setDistanceStartAlongSegment(int distanceStartAlongSegment) { + this.distanceStartAlongSegment = distanceStartAlongSegment; + } + + public int getReturnStopSeq() { + return returnStopSeq; + } + + public void setReturnStopSeq(int returnStopSeq) { + this.returnStopSeq = returnStopSeq; + } + + public int getDistanceEndAlongSegment() { + return distanceEndAlongSegment; + } + + public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { + this.distanceEndAlongSegment = distanceEndAlongSegment; + } + + public List getDetourPath() { + return detourPath; + } + + public void setDetourPath(List detourPath) { + this.detourPath = detourPath; + } + + public List getStopLocations() { + return stopLocations; + } + + public void setStopLocations(List stopLocations) { + this.stopLocations = stopLocations; + } + + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public Date getEndTime() { + return endTime; + } + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java index a0c0c5281..bbd0639d7 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java @@ -1,5 +1,35 @@ package org.transitclock.api.data; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import org.transitclock.ipc.data.IpcDiversion; + +@XmlRootElement(name = "diversions") public class ApiDiversions { + + public ApiDiversions() { + + } + + public ApiDiversions(List ipcDiversions) { + diversions=new ArrayList(); + for(IpcDiversion ipcDiversion:ipcDiversions) + { + diversions.add(new ApiDiversion(ipcDiversion)); + } + } + @XmlElement + private List diversions; + public List getDiversions() { + return diversions; + } + public void setDiversions(List diversions) { + this.diversions = diversions; + } + } From 6563efa3ce06a16aef3981dadf2ca506a2b1c8f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sean=20=C3=93g=20Crudden?= Date: Mon, 2 Mar 2020 18:32:11 +0000 Subject: [PATCH 05/17] More scaffolding for diversions. Introduces new Spatial match, DiversionMatch. --- .../ArrivalDepartureGeneratorDefaultImpl.java | 44 +++++----- .../org/transitclock/core/AvlProcessor.java | 14 ++-- .../org/transitclock/core/DiversionMatch.java | 43 ++++++++++ .../java/org/transitclock/core/Indices.java | 2 +- .../core/PredictionGeneratorDefaultImpl.java | 2 +- .../core/RealTimeSchedAdhProcessor.java | 2 +- .../{SpatialMatch.java => RouteMatch.java} | 83 ++++++++----------- .../org/transitclock/core/SpatialMatcher.java | 64 +++++++------- .../org/transitclock/core/TemporalMatch.java | 4 +- .../transitclock/core/TemporalMatcher.java | 26 +++--- .../org/transitclock/core/TravelTimes.java | 14 ++-- .../org/transitclock/core/VehicleState.java | 4 +- .../core/autoAssigner/AutoBlockAssigner.java | 38 ++++----- .../scheduled/TripDataHistoryCacheExpiry.java | 29 +++++++ ...toricalAveragePredictionGeneratorImpl.java | 4 +- .../org/transitclock/db/structs/Block.java | 4 +- .../org/transitclock/ipc/data/IpcVehicle.java | 4 +- .../ipc/data/IpcVehicleComplete.java | 4 +- .../ipc/data/IpcVehicleGtfsRealtime.java | 4 +- 19 files changed, 225 insertions(+), 164 deletions(-) create mode 100644 transitclock/src/main/java/org/transitclock/core/DiversionMatch.java rename transitclock/src/main/java/org/transitclock/core/{SpatialMatch.java => RouteMatch.java} (94%) create mode 100644 transitclock/src/main/java/org/transitclock/core/dataCache/ehcache/scheduled/TripDataHistoryCacheExpiry.java diff --git a/transitclock/src/main/java/org/transitclock/core/ArrivalDepartureGeneratorDefaultImpl.java b/transitclock/src/main/java/org/transitclock/core/ArrivalDepartureGeneratorDefaultImpl.java index 80b7e6c53..cecb4797e 100755 --- a/transitclock/src/main/java/org/transitclock/core/ArrivalDepartureGeneratorDefaultImpl.java +++ b/transitclock/src/main/java/org/transitclock/core/ArrivalDepartureGeneratorDefaultImpl.java @@ -171,8 +171,8 @@ private static int getMaxStopsBetweenMatches() { * @param avlReport * @return */ - private boolean tooManyStopsTraversed(SpatialMatch oldMatch, - SpatialMatch newMatch, AvlReport previousAvlReport, + private boolean tooManyStopsTraversed(RouteMatch oldMatch, + RouteMatch newMatch, AvlReport previousAvlReport, AvlReport avlReport) { // If there is no old match then we are fine if (oldMatch == null) @@ -224,8 +224,8 @@ private boolean tooManyStopsTraversed(SpatialMatch oldMatch, * The new match for the vehicle. * @return */ - private boolean shouldProcessArrivedOrDepartedStops(SpatialMatch oldMatch, - SpatialMatch newMatch) { + private boolean shouldProcessArrivedOrDepartedStops(RouteMatch oldMatch, + RouteMatch newMatch) { // If there is no old match at all then we likely finally got a // AVL report after vehicle had left terminal. Still want to // determine arrival/departure times for the first stops of the @@ -239,7 +239,7 @@ private boolean shouldProcessArrivedOrDepartedStops(SpatialMatch oldMatch, // truly know what is going on it is best to not generate // arrivals/departures for between the matches. int stopsTraversed = - SpatialMatch.numberStopsBetweenMatches(oldMatch, newMatch); + RouteMatch.numberStopsBetweenMatches(oldMatch, newMatch); if (stopsTraversed > getMaxStopsBetweenMatches()) { logger.error("Attempting to traverse {} stops between oldMatch " + "and newMatch, which is more thanThere are more than " + @@ -611,7 +611,7 @@ private void estimateArrivalsDeparturesWithoutPreviousMatch( } // Couple of convenience variables - SpatialMatch newMatch = vehicleState.getMatch(); + RouteMatch newMatch = vehicleState.getMatch(); String vehicleId = vehicleState.getVehicleId(); if (newMatch.getTripIndex() == 0 && @@ -624,7 +624,7 @@ private void estimateArrivalsDeparturesWithoutPreviousMatch( int stopPathIndex = 0; // Determine departure time for first stop of trip - SpatialMatch beginningOfTrip = new SpatialMatch(0, block, + RouteMatch beginningOfTrip = new RouteMatch(0, block, tripIndex, 0, 0, 0.0, 0.0); long travelTimeFromFirstStopToMatch = TravelTimes.getInstance() .expectedTravelTimeBetweenMatches(vehicleId, avlReportTime, @@ -799,7 +799,7 @@ private long handleVehicleDepartingStop(VehicleState vehicleState) { // If vehicle wasn't departing a stop then simply return the // previous AVL time as the beginTime. - SpatialMatch oldMatch = vehicleState.getPreviousMatch(); + RouteMatch oldMatch = vehicleState.getPreviousMatch(); VehicleAtStopInfo oldVehicleAtStopInfo = oldMatch.getAtStop(); AvlReport previousAvlReport = vehicleState.getPreviousAvlReportFromSuccessfulMatch(); @@ -813,13 +813,13 @@ private long handleVehicleDepartingStop(VehicleState vehicleState) { // Use match right at the departed stop. This way we are including the // time it takes to get from the actual stop to the new match. - SpatialMatch matchJustAfterStop = + RouteMatch matchJustAfterStop = oldMatch.getMatchAdjustedToBeginningOfPath(); // Determine departure info for the old stop by using the current // AVL report and subtracting the expected travel time to get from // there to the new match. - SpatialMatch newMatch = vehicleState.getMatch(); + RouteMatch newMatch = vehicleState.getMatch(); int travelTimeToNewMatchMsec = TravelTimes.getInstance() .expectedTravelTimeBetweenMatches(vehicleId, previousAvlReport.getDate(), matchJustAfterStop, @@ -846,7 +846,7 @@ private long handleVehicleDepartingStop(VehicleState vehicleState) { } else { // The oldMatch is before the stop so add the travel time from the // oldMatch to the stop to the previous AVL report time. - SpatialMatch matchJustBeforeStop = + RouteMatch matchJustBeforeStop = oldMatch.getMatchAdjustedToEndOfPath(); int travelTimeFromOldMatchToStopMsec = TravelTimes.getInstance() .expectedTravelTimeBetweenMatches(vehicleId, @@ -935,7 +935,7 @@ private long handleVehicleArrivingAtStop(VehicleState vehicleState, // If vehicle hasn't arrived at a stop then simply return the // AVL time as the endTime. - SpatialMatch newMatch = vehicleState.getMatch(); + RouteMatch newMatch = vehicleState.getMatch(); VehicleAtStopInfo newVehicleAtStopInfo = newMatch.getAtStop(); AvlReport avlReport = vehicleState.getAvlReport(); if (newVehicleAtStopInfo == null) @@ -949,14 +949,14 @@ private long handleVehicleArrivingAtStop(VehicleState vehicleState, // Use match right at the stop. This way we are including the // time it takes to get from the new match to the actual // stop and not just to some distance before the stop. - SpatialMatch matchJustBeforeStop = + RouteMatch matchJustBeforeStop = newMatch.getMatchAdjustedToEndOfPath(); // Determine arrival info for the new stop based on the // old AVL report. This will give us the proper time if // the vehicle already arrived before the current AVL // report - SpatialMatch oldMatch = vehicleState.getPreviousMatch(); + RouteMatch oldMatch = vehicleState.getPreviousMatch(); int travelTimeFromOldMatchMsec = TravelTimes.getInstance() .expectedTravelTimeBetweenMatches(vehicleId, avlReport.getDate(), oldMatch, matchJustBeforeStop); @@ -985,7 +985,7 @@ private long handleVehicleArrivingAtStop(VehicleState vehicleState, // The new match is after the stop so subtract the travel time // from the stop to the match from the AVL time to get the // arrivalTimeBasedOnNewMatch. - SpatialMatch matchJustAfterStop = + RouteMatch matchJustAfterStop = newMatch.getMatchAdjustedToBeginningOfPath(); int travelTimeFromStoptoNewMatchMsec = TravelTimes.getInstance() @@ -1077,8 +1077,8 @@ private long handleVehicleArrivingAtStop(VehicleState vehicleState, * @param newMatch * @return Number of zero travel or stop times */ - private int numberOfZeroTravelOrStopTimes(SpatialMatch oldMatch, - SpatialMatch newMatch) { + private int numberOfZeroTravelOrStopTimes(RouteMatch oldMatch, + RouteMatch newMatch) { int counter = 0; Indices indices = oldMatch.getIndices(); Indices newIndices = newMatch.getIndices(); @@ -1123,8 +1123,8 @@ private void handleIntermediateStops(VehicleState vehicleState, // Convenience variables String vehicleId = vehicleState.getVehicleId(); - SpatialMatch oldMatch = vehicleState.getPreviousMatch(); - SpatialMatch newMatch = vehicleState.getMatch(); + RouteMatch oldMatch = vehicleState.getPreviousMatch(); + RouteMatch newMatch = vehicleState.getMatch(); Date previousAvlDate = vehicleState .getPreviousAvlReportFromSuccessfulMatch().getDate(); Date avlDate = vehicleState.getAvlReport().getDate(); @@ -1173,7 +1173,7 @@ private void handleIntermediateStops(VehicleState vehicleState, newVehicleAtStopInfo.clone() : newMatch.getIndices(); // Determine time to first stop - SpatialMatch matchAtNextStop = oldMatch.getMatchAtJustBeforeNextStop(); + RouteMatch matchAtNextStop = oldMatch.getMatchAtJustBeforeNextStop(); long travelTimeToFirstStop = TravelTimes.getInstance() .expectedTravelTimeBetweenMatches(vehicleId, avlDate, oldMatch, matchAtNextStop); @@ -1250,7 +1250,7 @@ public void generate(VehicleState vehicleState) { // Return empty arrivalDepartures list return; } - SpatialMatch newMatch = vehicleState.getMatch(); + RouteMatch newMatch = vehicleState.getMatch(); if (newMatch == null) { logger.error("Vehicle was not matched when trying to process " + "arrival/departure times. {}", vehicleState); @@ -1264,7 +1264,7 @@ public void generate(VehicleState vehicleState) { // stop of the block due to not getting assignment right away or some // kind of AVL issue. For this situation still want to estimate the // arrival/departure times for the previous stops. - SpatialMatch oldMatch = vehicleState.getPreviousMatch(); + RouteMatch oldMatch = vehicleState.getPreviousMatch(); if (oldMatch == null) { logger.debug("For vehicleId={} there was no previous match " + "so seeing if can generate arrivals/departures for " + diff --git a/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java b/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java index 31b2a5a2b..59dea4f18 100644 --- a/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java +++ b/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java @@ -442,7 +442,7 @@ public void matchNewFixForPredictableVehicle(VehicleState vehicleState) { + "report. The old spatial match is {}", vehicleState); // Find possible spatial matches - List spatialMatches = SpatialMatcher + List spatialMatches = SpatialMatcher .getSpatialMatches(vehicleState); logger.debug("For vehicleId={} found the following {} spatial " + "matches: {}", vehicleState.getVehicleId(), @@ -521,7 +521,7 @@ public void matchNewFixForPredictableVehicle(VehicleState vehicleState) { * @param match * @return True if the match can be used when matching vehicle to a route */ - private static boolean matchOkForRouteMatching(SpatialMatch match) { + private static boolean matchOkForRouteMatching(RouteMatch match) { return match.awayFromTerminals(getTerminalDistanceForRouteMatching()); } @@ -684,7 +684,7 @@ private boolean matchVehicleToRouteAssignment(String routeId, } } - List allPotentialSpatialMatchesForRoute = new ArrayList(); + List allPotentialSpatialMatchesForRoute = new ArrayList(); // Go through each block and determine best spatial matches for (Block block : allBlocksForRoute) { @@ -718,12 +718,12 @@ private boolean matchVehicleToRouteAssignment(String routeId, block.getId(), potentialTrips); // Get the potential spatial matches - List spatialMatchesForBlock = SpatialMatcher + List spatialMatchesForBlock = SpatialMatcher .getSpatialMatches(vehicleState.getAvlReport(), block, potentialTrips, MatchingType.AUTO_ASSIGNING_MATCHING); // Add appropriate spatial matches to list - for (SpatialMatch spatialMatch : spatialMatchesForBlock) { + for (RouteMatch spatialMatch : spatialMatchesForBlock) { if (!SpatialMatcher.problemMatchDueToLackOfHeadingInfo( spatialMatch, vehicleState, MatchingType.AUTO_ASSIGNING_MATCHING) && matchOkForRouteMatching(spatialMatch)) @@ -779,7 +779,7 @@ private boolean matchVehicleToBlockAssignment(Block block, // specifying the block assignment so it should find a match even // if it pretty far off. List potentialTrips = block.getTripsCurrentlyActive(avlReport); - List spatialMatches = + List spatialMatches = SpatialMatcher.getSpatialMatches(vehicleState.getAvlReport(), block, potentialTrips, MatchingType.STANDARD_MATCHING); logger.debug("For vehicleId={} and blockId={} spatial matches={}", @@ -819,7 +819,7 @@ private boolean matchVehicleToBlockAssignment(Block block, double distanceToSegment = firstStopInTripLoc.distance(avlReport.getLocation()); - SpatialMatch beginningOfTrip = new SpatialMatch( + RouteMatch beginningOfTrip = new RouteMatch( avlReport.getTime(), block, block.getTripIndex(trip), 0, // stopPathIndex 0, // segmentIndex diff --git a/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java new file mode 100644 index 000000000..28563bfc9 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java @@ -0,0 +1,43 @@ +package org.transitclock.core; + +import org.transitclock.core.diversion.model.Diversion; +import org.transitclock.db.structs.Block; +import org.transitclock.db.structs.Location; + +public class DiversionMatch extends SpatialMatch { + + public DiversionMatch(long avlTime, Block block, int tripIndex) { + super(avlTime, block, tripIndex); + } + + int distanceAlongDiversion; + int distanceToDiversion; + Location predictedLocation; + + public int getDistanceAlongDiversion() { + return distanceAlongDiversion; + } + + public void setDistanceAlongDiversion(int distanceAlongDiversion) { + this.distanceAlongDiversion = distanceAlongDiversion; + } + + public int getDistanceToDiversion() { + return distanceToDiversion; + } + + public void setDistanceToDiversion(int distanceToDiversion) { + this.distanceToDiversion = distanceToDiversion; + } + + public Diversion getDiversion() { + return diversion; + } + + public void setDiversion(Diversion diversion) { + this.diversion = diversion; + } + + Diversion diversion; + +} diff --git a/transitclock/src/main/java/org/transitclock/core/Indices.java b/transitclock/src/main/java/org/transitclock/core/Indices.java index 1db8b953c..b7228a3b5 100644 --- a/transitclock/src/main/java/org/transitclock/core/Indices.java +++ b/transitclock/src/main/java/org/transitclock/core/Indices.java @@ -88,7 +88,7 @@ public Indices(Block block, int tripIndex, int stopPathIndex, * * @param spatialMatch */ - public Indices(SpatialMatch spatialMatch) { + public Indices(RouteMatch spatialMatch) { this.block = spatialMatch.getBlock(); this.tripIndex = spatialMatch.getTripIndex(); this.stopPathIndex = spatialMatch.getStopPathIndex(); diff --git a/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java b/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java index f09dd23dc..b6dd425ad 100755 --- a/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java +++ b/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java @@ -584,7 +584,7 @@ public long getStopTimeForPath(Indices indices, AvlReport avlReport, VehicleStat return prediction; } - public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, SpatialMatch match) + public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, RouteMatch match) { TravelTimes travelTimes = TravelTimes.getInstance(); return travelTimes.expectedTravelTimeFromMatchToEndOfStopPath(match); diff --git a/transitclock/src/main/java/org/transitclock/core/RealTimeSchedAdhProcessor.java b/transitclock/src/main/java/org/transitclock/core/RealTimeSchedAdhProcessor.java index 276ace35f..ee8050b53 100644 --- a/transitclock/src/main/java/org/transitclock/core/RealTimeSchedAdhProcessor.java +++ b/transitclock/src/main/java/org/transitclock/core/RealTimeSchedAdhProcessor.java @@ -134,7 +134,7 @@ public static TemporalDifference generate(VehicleState vehicleState) { // at the next stop with a scheduled time. Determine the // appropriate match to use for the upcoming stop where there is a // schedule time. - SpatialMatch matchAtStopWithScheduleTime = + RouteMatch matchAtStopWithScheduleTime = match.getMatchAtNextStopWithScheduleTime(); if (matchAtStopWithScheduleTime == null) return null; diff --git a/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java b/transitclock/src/main/java/org/transitclock/core/RouteMatch.java similarity index 94% rename from transitclock/src/main/java/org/transitclock/core/SpatialMatch.java rename to transitclock/src/main/java/org/transitclock/core/RouteMatch.java index c965d12d2..326852db3 100644 --- a/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java +++ b/transitclock/src/main/java/org/transitclock/core/RouteMatch.java @@ -38,11 +38,8 @@ * @author SkiBu Smith * */ -public class SpatialMatch { +public class RouteMatch extends SpatialMatch { - protected final long avlTime; - protected final Block block; - protected final int tripIndex; protected final int stopPathIndex; protected final int segmentIndex; protected final double distanceToSegment; @@ -51,17 +48,17 @@ public class SpatialMatch { protected final Location predictedLocation; private static final Logger logger = - LoggerFactory.getLogger(SpatialMatch.class); + LoggerFactory.getLogger(RouteMatch.class); /********************** Member Functions **************************/ - public SpatialMatch(long avlTime, Block block, + public RouteMatch(long avlTime, Block block, int tripIndex, int stopPathIndex, int segmentIndex, double distanceToSegment, double distanceAlongSegment) { - this.avlTime = avlTime; - this.block = block; - this.tripIndex = tripIndex; + + super(avlTime, block, tripIndex); + this.stopPathIndex = stopPathIndex; this.segmentIndex = segmentIndex; this.distanceToSegment = distanceToSegment; @@ -116,19 +113,15 @@ public Location computeLocation(Indices i, double distanceAlongSegment) { * The new trip to use for the copy. It is assumed to be for the * same trip pattern. It can be for a separate block. */ - public SpatialMatch(SpatialMatch toCopy, Trip newTrip) { + public RouteMatch(RouteMatch toCopy, Trip newTrip) { + // Use the new block and trip index info + super(toCopy.avlTime, newTrip.getBlock(), newTrip.getBlock().getTripIndex(newTrip)); if (toCopy.getTrip().getTripPattern() != newTrip.getTripPattern()) logger.error("Trying to create a copy of a SpatialMatch using a " + "new trip but they have different trip patterns. " + "toCopy={} toCopy.tripPattern={} newTrip.tripPattern={}", toCopy, toCopy.getTrip().getTripPattern().toShortString(), - newTrip.getTripPattern().toShortString()); - this.avlTime = toCopy.avlTime; - - // Use the new block and trip index info - this.block = newTrip.getBlock(); - this.tripIndex = newTrip.getBlock().getTripIndex(newTrip); - + newTrip.getTripPattern().toShortString()); this.stopPathIndex = toCopy.stopPathIndex; this.segmentIndex = toCopy.segmentIndex; this.distanceToSegment = toCopy.distanceToSegment; @@ -156,11 +149,9 @@ public SpatialMatch(SpatialMatch toCopy, Trip newTrip) { * @param newIndices * @param distanceAlongSegment */ - public SpatialMatch(SpatialMatch toCopy, Indices newIndices, - double distanceAlongSegment) { - this.avlTime = toCopy.avlTime; - this.block = toCopy.block; - this.tripIndex = newIndices.getTripIndex(); + public RouteMatch(RouteMatch toCopy, Indices newIndices, + double distanceAlongSegment) { + super(toCopy.avlTime, toCopy.block, newIndices.getTripIndex()); this.stopPathIndex = newIndices.getStopPathIndex(); this.segmentIndex = newIndices.getSegmentIndex(); this.distanceToSegment = toCopy.distanceToSegment; @@ -174,10 +165,8 @@ public SpatialMatch(SpatialMatch toCopy, Indices newIndices, * * @param toCopy */ - protected SpatialMatch(SpatialMatch toCopy) { - this.avlTime = toCopy.avlTime; - this.block = toCopy.block; - this.tripIndex = toCopy.tripIndex; + protected RouteMatch(RouteMatch toCopy) { + super(toCopy.getAvlTime(), toCopy.getBlock(), toCopy.getTripIndex()); this.stopPathIndex = toCopy.stopPathIndex; this.segmentIndex = toCopy.segmentIndex; this.distanceToSegment = toCopy.distanceToSegment; @@ -295,7 +284,7 @@ public boolean atBeginningOfPathStop() { * * @return SpatialMatch adjusted so it is at end of path for the stop */ - public SpatialMatch getMatchAdjustedToEndOfPath() { + public RouteMatch getMatchAdjustedToEndOfPath() { // If not at a stop then we have a problem if (atStop == null) { logger.error("Wrongly called " + @@ -321,7 +310,7 @@ public SpatialMatch getMatchAdjustedToEndOfPath() { Indices endOfStopPathIndices = new Indices(block, indices.getTripIndex(), indices.getStopPathIndex(), segmentIndex); - return new SpatialMatch(this, endOfStopPathIndices, + return new RouteMatch(this, endOfStopPathIndices, distanceAlongSegment); } @@ -331,7 +320,7 @@ public SpatialMatch getMatchAdjustedToEndOfPath() { * * @return */ - public SpatialMatch getMatchAtNextStopWithScheduleTime() { + public RouteMatch getMatchAtNextStopWithScheduleTime() { // Determine next stop with a schedule time (arrival or departure) // If there is no such stop then return null. List stopPaths = @@ -359,7 +348,7 @@ public SpatialMatch getMatchAtNextStopWithScheduleTime() { int segmentIndex = stopPath.getNumberSegments()-1; Vector segmentVector = stopPath.getSegmentVector(segmentIndex); double distanceAlongSegment = segmentVector.length(); - SpatialMatch matchAtStopWithScheduleTime = new SpatialMatch(this, + RouteMatch matchAtStopWithScheduleTime = new RouteMatch(this, indicesAtStopWithScheduleTime, distanceAlongSegment); @@ -376,7 +365,7 @@ public SpatialMatch getMatchAtNextStopWithScheduleTime() { * * @return SpatialMatch adjusted so it is at beginning of path for the stop */ - public SpatialMatch getMatchAdjustedToBeginningOfPath() { + public RouteMatch getMatchAdjustedToBeginningOfPath() { // If not at a stop then we have a problem if (atStop == null) { logger.error("Wrongly called " + @@ -400,7 +389,7 @@ public SpatialMatch getMatchAdjustedToBeginningOfPath() { Indices beginningOfStopPathIndices = new Indices(block, indices.getTripIndex(), indices.getStopPathIndex(), segmentIndex); - return new SpatialMatch(this, beginningOfStopPathIndices, + return new RouteMatch(this, beginningOfStopPathIndices, distanceAlongSegment); } @@ -414,7 +403,7 @@ public SpatialMatch getMatchAdjustedToBeginningOfPath() { * * @return This match or one after the stop if at end of stop path */ - private SpatialMatch getMatchAfterStopIfAtStop() { + private RouteMatch getMatchAfterStopIfAtStop() { // If the spatialMatch is not just before a stop then return // spatialMatch. The spatialMatch is just before a stop if // atStop trip and path indices are the same as for the match. @@ -424,7 +413,7 @@ private SpatialMatch getMatchAfterStopIfAtStop() { // The spatialMatch is just before a stop so create a new spatial // match but use the beginning of the next path. Indices nextPathIndices = getIndices().incrementStopPath(); - return new SpatialMatch(this, nextPathIndices, 0.0); + return new RouteMatch(this, nextPathIndices, 0.0); } /** @@ -433,10 +422,10 @@ private SpatialMatch getMatchAfterStopIfAtStop() { * * @return */ - public SpatialMatch getMatchAtJustBeforeNextStop() { + public RouteMatch getMatchAtJustBeforeNextStop() { // First need to get on the proper path. If just before a stop // then need to get a match just after that stop. - SpatialMatch m = getMatchAfterStopIfAtStop(); + RouteMatch m = getMatchAfterStopIfAtStop(); int segmentIndex = block.numSegments(m.getTripIndex(), m.getStopPathIndex())-1; @@ -445,7 +434,7 @@ public SpatialMatch getMatchAtJustBeforeNextStop() { double segmentLength = segmentVector.length(); // Return a match that is at the end of the path - return new SpatialMatch( + return new RouteMatch( 0, // Don't worry about avlTime for this special case block, m.getTripIndex(), @@ -465,7 +454,7 @@ public SpatialMatch getMatchAtJustBeforeNextStop() { * * @return This match or one before the stop if at beginning of stop path */ - public SpatialMatch getMatchBeforeStopIfAtStop() { + public RouteMatch getMatchBeforeStopIfAtStop() { // If the spatialMatch is not just after a stop then return // spatialMatch. if (!atBeginningOfPathStop()) @@ -474,7 +463,7 @@ public SpatialMatch getMatchBeforeStopIfAtStop() { // The spatialMatch is just after a stop so create a new spatial // match but use the end of the previous path. Indices previousPathIndices = getIndices().decrementStopPath(); - return new SpatialMatch(this, previousPathIndices, + return new RouteMatch(this, previousPathIndices, previousPathIndices.getSegment().length()); } @@ -487,7 +476,7 @@ public SpatialMatch getMatchBeforeStopIfAtStop() { * previous stop (the current match is for the beginning of the * block). */ - public SpatialMatch getMatchAtPreviousStop() { + public RouteMatch getMatchAtPreviousStop() { // First need to get on the proper path. If just before a stop // then need to get a match just after that stop. Indices indices = @@ -504,7 +493,7 @@ public SpatialMatch getMatchAtPreviousStop() { indices.getSegmentIndex()); double segmentVectorLength = segmentVector!=null ? segmentVector.length() : Double.NaN; - return new SpatialMatch( + return new RouteMatch( 0, // Don't worry about avlTime for this special case block, indices.getTripIndex(), @@ -656,7 +645,7 @@ public double getDistanceRemainingInStopPath() { * @param otherSpatialMatch * @return Distance in meters between the matches */ - public double distanceBetweenMatches(SpatialMatch otherSpatialMatch) { + public double distanceBetweenMatches(RouteMatch otherSpatialMatch) { // Determine the distances from the beginning of the stop paths // and the matches double distanceAlongFirstPath = @@ -692,7 +681,7 @@ public double distanceBetweenMatches(SpatialMatch otherSpatialMatch) { * @return true if there is a wait stop between this match and the other * match */ - public boolean traversedWaitStop(SpatialMatch otherSpatialMatch) { + public boolean traversedWaitStop(RouteMatch otherSpatialMatch) { // If either this match or the other match are at a wait stop then // indeed a wait stop is in effect VehicleAtStopInfo atStop = getAtStop(); @@ -745,7 +734,7 @@ public Indices getIndicesForDistanceBeforeMatch(double distanceBeforeMatch) { * The Spatial Match to compare to * @return true if this is before or equal to the other SpatialMatch */ - public boolean lessThanOrEqualTo(SpatialMatch other) { + public boolean lessThanOrEqualTo(RouteMatch other) { if (tripIndex > other.tripIndex) return false; if (tripIndex < other.tripIndex) @@ -774,7 +763,7 @@ public boolean lessThanOrEqualTo(SpatialMatch other) { * The Spatial Match to compare to * @return true if this is before the other SpatialMatch */ - public boolean lessThan(SpatialMatch other) { + public boolean lessThan(RouteMatch other) { if (tripIndex > other.tripIndex) return false; if (tripIndex < other.tripIndex) @@ -804,8 +793,8 @@ public boolean lessThan(SpatialMatch other) { * @param match2 * @return Number of stops */ - public static int numberStopsBetweenMatches(SpatialMatch match1, - SpatialMatch match2) { + public static int numberStopsBetweenMatches(RouteMatch match1, + RouteMatch match2) { // Stop index for first trip int stopIdxInFirstTrip = match1.getStopPathIndex(); diff --git a/transitclock/src/main/java/org/transitclock/core/SpatialMatcher.java b/transitclock/src/main/java/org/transitclock/core/SpatialMatcher.java index 5d70b9efb..58260240c 100644 --- a/transitclock/src/main/java/org/transitclock/core/SpatialMatcher.java +++ b/transitclock/src/main/java/org/transitclock/core/SpatialMatcher.java @@ -51,7 +51,7 @@ public class SpatialMatcher { // So that know where to start searching from - private SpatialMatch startSearchSpatialMatch = null; + private RouteMatch startSearchSpatialMatch = null; // For keeping track of whether getting closer or further away private double previousDistanceToSegment = Double.MAX_VALUE; @@ -60,12 +60,12 @@ public class SpatialMatcher { // For keeping track of potential matches where heading and // distance to segment are acceptable. - private SpatialMatch previousPotentialSpatialMatch = null; + private RouteMatch previousPotentialSpatialMatch = null; // For keeping track of match with best distance. This is useful for // logging in case something goes wrong. It lets one determine if // need to make the system more lenient. - private SpatialMatch smallestDistanceSpatialMatch = null; + private RouteMatch smallestDistanceSpatialMatch = null; // For keeping track of what kind of spatial matching being done public enum MatchingType {STANDARD_MATCHING, AUTO_ASSIGNING_MATCHING}; @@ -95,7 +95,7 @@ private SpatialMatcher() { * * @param startSearchSpatialMatch */ - private void setStartOfSearch(SpatialMatch startSearchSpatialMatch) { + private void setStartOfSearch(RouteMatch startSearchSpatialMatch) { this.startSearchSpatialMatch = startSearchSpatialMatch; } @@ -114,12 +114,12 @@ private void setStartOfSearch(SpatialMatch startSearchSpatialMatch) { * @return List of potential SpatialMatches. Can be empty but will not be * null. */ - private List getSpatialMatchesForTrip(AvlReport avlReport, + private List getSpatialMatchesForTrip(AvlReport avlReport, Trip trip, MatchingType matchingType) { Block block = trip.getBlock(); // The matches to be returned - List spatialMatches = new ArrayList(); + List spatialMatches = new ArrayList(); // Start looking for matches at the beginning of the trip. Indices indices = new Indices(block, block.getTripIndex(trip), @@ -160,9 +160,9 @@ private List getSpatialMatchesForTrip(AvlReport avlReport, * @param spatialMatchesForTrip * @return */ - private static SpatialMatch getFirstNonLayoverSpatialMatch( - List spatialMatchesForTrip) { - for (SpatialMatch match : spatialMatchesForTrip) { + private static RouteMatch getFirstNonLayoverSpatialMatch( + List spatialMatchesForTrip) { + for (RouteMatch match : spatialMatchesForTrip) { if (!match.isLayover()) return match; } @@ -192,7 +192,7 @@ private static SpatialMatch getFirstNonLayoverSpatialMatch( * heading in proper direction for the match. */ public static boolean problemMatchDueToLackOfHeadingInfo( - SpatialMatch spatialMatch, + RouteMatch spatialMatch, VehicleState vehicleState, MatchingType matchingType) { // If there was no spatial match then there can't be a problem @@ -227,13 +227,13 @@ public static boolean problemMatchDueToLackOfHeadingInfo( return true; // Determine matches for the previous AvlReport - List spatialMatchesForPreviousReport = + List spatialMatchesForPreviousReport = (new SpatialMatcher()).getSpatialMatchesForTrip( previousAvlReport, trip, matchingType); // There can be multiple matches, but only look at first // non-layover ones for the previous report - SpatialMatch previousNonLayoverSpatialMatch = + RouteMatch previousNonLayoverSpatialMatch = getFirstNonLayoverSpatialMatch( spatialMatchesForPreviousReport); @@ -277,12 +277,12 @@ public static boolean problemMatchDueToLackOfHeadingInfo( * for keeping track of what kind of spatial matching being done * @return non-null possibly empty list of spatial matches */ - public static List getSpatialMatches( + public static List getSpatialMatches( AvlReport avlReport, Block block, List tripsToInvestigate, MatchingType matchingType) { - List spatialMatchesForAllTrips = - new ArrayList(); + List spatialMatchesForAllTrips = + new ArrayList(); // If no trips to investigate then done if (tripsToInvestigate == null || tripsToInvestigate.isEmpty()) @@ -300,9 +300,9 @@ public static List getSpatialMatches( // So can determine when to stop copying. Need to stop // when starting to look at another trip. String tripIdThatFoundTripPatternFor = null; - List matchListForIteration = - new ArrayList(spatialMatchesForAllTrips); - for (SpatialMatch spatialMatch : matchListForIteration) { + List matchListForIteration = + new ArrayList(spatialMatchesForAllTrips); + for (RouteMatch spatialMatch : matchListForIteration) { String spatialMatchTripPatternId = spatialMatch.getTrip() .getTripPattern().getId(); String currentTripPatternId = trip.getTripPattern().getId(); @@ -310,7 +310,7 @@ public static List getSpatialMatches( && (tripIdThatFoundTripPatternFor == null || tripIdThatFoundTripPatternFor .equals(spatialMatch.getTrip().getId()))) { foundTripPattern = true; - SpatialMatch spatialMatchCopy = new SpatialMatch( + RouteMatch spatialMatchCopy = new RouteMatch( spatialMatch, trip); spatialMatchesForAllTrips.add(spatialMatchCopy); tripIdThatFoundTripPatternFor = spatialMatch.getTrip() @@ -328,7 +328,7 @@ public static List getSpatialMatches( } else { // Haven't already examined this trip pattern for spatial // matches so do so now. - List spatialMatchesForTrip = + List spatialMatchesForTrip = (new SpatialMatcher()).getSpatialMatchesForTrip( avlReport, trip, matchingType); @@ -345,10 +345,10 @@ public static List getSpatialMatches( // will frequently be at the end of the trip, which should be considered // fine. if (!block.isNoSchedule()) { - Iterator iterator = + Iterator iterator = spatialMatchesForAllTrips.iterator(); while (iterator.hasNext()) { - SpatialMatch match = iterator.next(); + RouteMatch match = iterator.next(); if (block.nearEndOfBlock(match, CoreConfig .getDistanceFromEndOfBlockForInitialMatching())) { // The match is too close to end of block so don't use it @@ -392,18 +392,18 @@ public static List getSpatialMatches( * through all trips. * @return non-null possibly empty list of spatial matches */ - public static List getSpatialMatchesForAutoAssigning( + public static List getSpatialMatchesForAutoAssigning( AvlReport avlReport, Block block, List tripsToInvestigate) { // Get all the spatial matches - List allSpatialMatches = + List allSpatialMatches = getSpatialMatches(avlReport, block, tripsToInvestigate, MatchingType.AUTO_ASSIGNING_MATCHING); // Filter out the ones that are layovers - List spatialMatches = - new ArrayList(); - for (SpatialMatch spatialMatch : allSpatialMatches) { + List spatialMatches = + new ArrayList(); + for (RouteMatch spatialMatch : allSpatialMatches) { if (!spatialMatch.isLayover() || spatialMatchToLayoversAllowedForAutoAssignment.getValue()) spatialMatches.add(spatialMatch); } @@ -543,7 +543,7 @@ private boolean withinAllowableDistanceOfLayover(String vehicleId, */ private void processPossiblePotentialMatch(AvlReport avlReport, Indices potentialMatchIndices, - List spatialMatches, + List spatialMatches, MatchingType matchingType) { // Convenience variables VectorWithHeading segmentVector = potentialMatchIndices.getSegment(); @@ -611,7 +611,7 @@ private void processPossiblePotentialMatch(AvlReport avlReport, } // Create the SpatialMatch object for the specified indices - SpatialMatch spatialMatch = new SpatialMatch( + RouteMatch spatialMatch = new RouteMatch( avlReport.getTime(), potentialMatchIndices.getBlock(), potentialMatchIndices.getTripIndex(), @@ -730,14 +730,14 @@ && withinAllowableDistanceOfLayover(avlReport.getVehicleId(), * @return list of possible spatial matches. If no spatial matches then * returns empty list (as opposed to null) */ - public static List + public static List getSpatialMatches(VehicleState vehicleState) { // Some convenience variables TemporalMatch previousMatch = vehicleState.getMatch(); SpatialMatcher spatialMatcher = new SpatialMatcher(); // The matches to be returned - List spatialMatches = new ArrayList(); + List spatialMatches = new ArrayList(); // Don't want to waste time search forward too far. So limit distance // such that vehicle would have traveled at 30% more than the max speed @@ -848,7 +848,7 @@ && withinAllowableDistanceOfLayover(avlReport.getVehicleId(), int indexOfLastSegment = lastStopPath.getNumberSegments()-1; double segmentLength = lastStopPath.getSegmentVector(indexOfLastSegment).length(); - SpatialMatch matchAtEndOfBlock = new SpatialMatch( + RouteMatch matchAtEndOfBlock = new RouteMatch( vehicleState.getAvlReport().getTime(), block, previousMatch.getTripIndex(), diff --git a/transitclock/src/main/java/org/transitclock/core/TemporalMatch.java b/transitclock/src/main/java/org/transitclock/core/TemporalMatch.java index ce37c04e3..db9be16c7 100644 --- a/transitclock/src/main/java/org/transitclock/core/TemporalMatch.java +++ b/transitclock/src/main/java/org/transitclock/core/TemporalMatch.java @@ -31,13 +31,13 @@ * @author SkiBu Smith * */ -public class TemporalMatch extends SpatialMatch { +public class TemporalMatch extends RouteMatch { private final TemporalDifference temporalDifference; /********************** Member Functions **************************/ - public TemporalMatch(SpatialMatch spatialMatch, + public TemporalMatch(RouteMatch spatialMatch, TemporalDifference temporalDifference) { super(spatialMatch); this.temporalDifference = temporalDifference; diff --git a/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java b/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java index fc2cac910..8131ebfec 100644 --- a/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java +++ b/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java @@ -82,7 +82,7 @@ public static TemporalMatcher getInstance() { * difference is beyond the allowable bounds. */ private static TemporalDifference determineHowFarOffScheduledTime( - String vehicleId, Date date, SpatialMatch spatialMatch, + String vehicleId, Date date, RouteMatch spatialMatch, boolean isFirstSpatialMatch) { // check to see if we are frequency based @@ -95,7 +95,7 @@ private static TemporalDifference determineHowFarOffScheduledTime( // Determine how long it should take to travel along trip to the match. // Can add this time to the trip scheduled start time to determine // when the vehicle is predicted to be at the match. - SpatialMatch beginningOfTrip = new SpatialMatch( + RouteMatch beginningOfTrip = new RouteMatch( 0, // AVL time doesn't matter spatialMatch.getBlock(), spatialMatch.getTripIndex(), @@ -177,7 +177,7 @@ private static TemporalDifference determineHowFarOffScheduledTime( * @return */ private TemporalDifference temporalDifferenceForSpecialLayover(VehicleState vehicleState, - SpatialMatch spatialMatch, int expectedTravelTimeMsec) { + RouteMatch spatialMatch, int expectedTravelTimeMsec) { AvlReport avlReport = vehicleState.getAvlReport(); Date avlTime = avlReport.getDate(); @@ -240,7 +240,7 @@ private TemporalDifference temporalDifferenceForSpecialLayover(VehicleState vehi * @return True if current temporal match is better and should be used */ private static boolean currentMatchIsBetter( - TemporalMatch bestTemporalMatchSoFar, SpatialMatch currentSpatialMatch, + TemporalMatch bestTemporalMatchSoFar, RouteMatch currentSpatialMatch, TemporalDifference differenceFromExpectedTime) { // If there is no current match then it can't be better if (currentSpatialMatch == null || differenceFromExpectedTime == null) @@ -307,9 +307,9 @@ private static boolean currentMatchIsBetter( * @return true if it is a problematic layover match that should not be used */ private boolean isProblematicLayover(VehicleState vehicleState, - List spatialMatches, int matchIdx) { - SpatialMatch previousMatch = vehicleState.getMatch(); - SpatialMatch spatialMatch = spatialMatches.get(matchIdx); + List spatialMatches, int matchIdx) { + RouteMatch previousMatch = vehicleState.getMatch(); + RouteMatch spatialMatch = spatialMatches.get(matchIdx); // If not even a layover then false if (!previousMatch.isLayover()) @@ -359,9 +359,9 @@ private boolean isProblematicLayover(VehicleState vehicleState, * valid temporal match found then returns null. */ public TemporalMatch getBestTemporalMatch(VehicleState vehicleState, - List spatialMatches) { + List spatialMatches) { // Convenience variables - SpatialMatch previousMatch = vehicleState.getMatch(); + RouteMatch previousMatch = vehicleState.getMatch(); Date previousAvlTime = vehicleState.getPreviousAvlReportFromSuccessfulMatch().getDate(); AvlReport avlReport = vehicleState.getAvlReport(); @@ -378,7 +378,7 @@ public TemporalMatch getBestTemporalMatch(VehicleState vehicleState, // Find best temporal match of the spatial matches TemporalMatch bestTemporalMatchSoFar = null; for (int matchIdx = 0; matchIdx < spatialMatches.size(); ++matchIdx) { - SpatialMatch spatialMatch = spatialMatches.get(matchIdx); + RouteMatch spatialMatch = spatialMatches.get(matchIdx); logger.debug("Examining spatial match {}", spatialMatch); // There is a complication with vehicles leaving a layover slightly @@ -522,9 +522,9 @@ public TemporalMatch getBestTemporalMatch(VehicleState vehicleState, * should be. Returns null if no adequate temporal match. */ public TemporalMatch getBestTemporalMatchComparedToSchedule( - AvlReport avlReport, List spatialMatches) { + AvlReport avlReport, List spatialMatches) { TemporalDifference bestDifferenceFromExpectedTime = null; - SpatialMatch bestSpatialMatch = null; + RouteMatch bestSpatialMatch = null; logger.debug("getBestTemporalMatchComparedToSchedule has spatialMatches {}", spatialMatches); @@ -536,7 +536,7 @@ public TemporalMatch getBestTemporalMatchComparedToSchedule( } for (int i=0; i spatialMatchCache = - new HashMap(); + private Map spatialMatchCache = + new HashMap(); /****************************** Config params **********************/ @@ -252,7 +252,7 @@ private TemporalMatch bestNoScheduleMatch(Block block) { // is only for use with no schedule assignments. AvlReport avlReport = getAvlReport(); List potentialTrips = block.getTripsCurrentlyActive(avlReport); - List spatialMatches = SpatialMatcher + List spatialMatches = SpatialMatcher .getSpatialMatchesForAutoAssigning(getAvlReport(), block, potentialTrips); if (spatialMatches.isEmpty()) @@ -261,7 +261,7 @@ private TemporalMatch bestNoScheduleMatch(Block block) { // Determine all possible spatial matches for the previous AVL report so // that can make sure that it too matches the assignment. AvlReport previousAvlReport = getPreviousAvlReport(); - List prevSpatialMatches = SpatialMatcher + List prevSpatialMatches = SpatialMatcher .getSpatialMatchesForAutoAssigning(previousAvlReport, block, potentialTrips); if (prevSpatialMatches.isEmpty()) @@ -278,9 +278,9 @@ private TemporalMatch bestNoScheduleMatch(Block block) { // the previous AVL report. Find one where the expected travel time // closely matches the time between the AVL reports. TemporalDifference bestTemporalDifference = null; - SpatialMatch bestSpatialMatch = null; - for (SpatialMatch prevSpatialMatch : prevSpatialMatches) { - for (SpatialMatch spatialMatch : spatialMatches) { + RouteMatch bestSpatialMatch = null; + for (RouteMatch prevSpatialMatch : prevSpatialMatches) { + for (RouteMatch spatialMatch : spatialMatches) { // Determine according to the historic travel times how long // it was expected to take to travel from the previous match // to the current one. @@ -334,13 +334,13 @@ private TemporalMatch bestNoScheduleMatch(Block block) { * * @return All possible spatial matches */ - private List getSpatialMatches(AvlReport avlReport, + private List getSpatialMatches(AvlReport avlReport, Block block) { // Convenience variable String vehicleId = avlReport.getVehicleId(); // For returning results of this method - List spatialMatches = new ArrayList(); + List spatialMatches = new ArrayList(); // Determine which trips are currently active so that don't bother // looking at all trips @@ -367,7 +367,7 @@ private List getSpatialMatches(AvlReport avlReport, if (spatialMatchCache.containsKey(tripPatternId)) { // Already processed this trip pattern so use cached results. // Can be null - SpatialMatch previouslyFoundMatch = + RouteMatch previouslyFoundMatch = spatialMatchCache.get(tripPatternId); // If there actually was a successful spatial match to the @@ -376,8 +376,8 @@ private List getSpatialMatches(AvlReport avlReport, // The cached match has the wrong trip info so need // to create an equivalent match with the proper trip block // info - SpatialMatch matchWithProperBlock = - new SpatialMatch(previouslyFoundMatch, trip); + RouteMatch matchWithProperBlock = + new RouteMatch(previouslyFoundMatch, trip); // Add to list of spatial matches to return spatialMatches.add(matchWithProperBlock); @@ -408,13 +408,13 @@ private List getSpatialMatches(AvlReport avlReport, // spatial matches that are not layovers. If match is to a layover can // ignore it since layover matches are far too flexible to really be // considered a spatial match - List newSpatialMatches = SpatialMatcher + List newSpatialMatches = SpatialMatcher .getSpatialMatchesForAutoAssigning(avlReport, block, tripsNeedToInvestigate); // Add newly discovered matches to the cache and to the list of spatial // matches to be returned - for (SpatialMatch newSpatialMatch : newSpatialMatches) { + for (RouteMatch newSpatialMatch : newSpatialMatches) { logger.debug("For vehicleId={} for tripId={} with " + "tripPatternId={} found new spatial match {}.", vehicleId, newSpatialMatch.getTrip().getId(), @@ -440,7 +440,7 @@ private List getSpatialMatches(AvlReport avlReport, // for the trip pattern String tripPatternId = tripInvestigated.getTripPattern().getId(); boolean spatialMatchFound = false; - for (SpatialMatch newSpatialMatch : newSpatialMatches) { + for (RouteMatch newSpatialMatch : newSpatialMatches) { String spatialMatchTripPatternId = newSpatialMatch.getTrip().getTripPattern().getId(); if (spatialMatchTripPatternId.equals(tripPatternId)) { @@ -477,14 +477,14 @@ private List getSpatialMatches(AvlReport avlReport, * * @return list of spatial matches for the avlReport */ - private List getSpatialMatchesWithoutCache( + private List getSpatialMatchesWithoutCache( AvlReport avlReport, Block block) { // Determine which trips are currently active so that don't bother // looking at all trips List activeTrips = block.getTripsCurrentlyActive(avlReport); // Get and return the spatial matches - List spatialMatches = SpatialMatcher + List spatialMatches = SpatialMatcher .getSpatialMatchesForAutoAssigning(avlReport, block, activeTrips); return spatialMatches; @@ -512,7 +512,7 @@ private List getSpatialMatchesWithoutCache( private TemporalMatch bestTemporalMatch(AvlReport avlReport, Block block, boolean useCache) { // Determine all potential spatial matches for the block - List spatialMatches = useCache ? + List spatialMatches = useCache ? getSpatialMatches(avlReport, block) : getSpatialMatchesWithoutCache(avlReport, block); diff --git a/transitclock/src/main/java/org/transitclock/core/dataCache/ehcache/scheduled/TripDataHistoryCacheExpiry.java b/transitclock/src/main/java/org/transitclock/core/dataCache/ehcache/scheduled/TripDataHistoryCacheExpiry.java new file mode 100644 index 000000000..7a6aed135 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/dataCache/ehcache/scheduled/TripDataHistoryCacheExpiry.java @@ -0,0 +1,29 @@ +package org.transitclock.core.dataCache.ehcache.scheduled; + +import java.util.concurrent.TimeUnit; + +import org.ehcache.ValueSupplier; +import org.ehcache.expiry.Duration; +import org.ehcache.expiry.Expiry; +import org.transitclock.core.dataCache.TripEvents; +import org.transitclock.core.dataCache.TripKey; + +public class TripDataHistoryCacheExpiry implements Expiry { + + @Override + public Duration getExpiryForCreation(TripKey key, TripEvents value) { + Duration duration=new Duration(21, TimeUnit.DAYS); + return duration; + } + + @Override + public Duration getExpiryForAccess(TripKey key, ValueSupplier value) { + return null; + } + + @Override + public Duration getExpiryForUpdate(TripKey key, ValueSupplier oldValue, TripEvents newValue) { + return null; + } + +} diff --git a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/average/HistoricalAveragePredictionGeneratorImpl.java b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/average/HistoricalAveragePredictionGeneratorImpl.java index 4a5ac82c1..1f207adf4 100755 --- a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/average/HistoricalAveragePredictionGeneratorImpl.java +++ b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/average/HistoricalAveragePredictionGeneratorImpl.java @@ -9,7 +9,7 @@ import org.transitclock.config.IntegerConfigValue; import org.transitclock.core.Indices; import org.transitclock.core.PredictionGeneratorDefaultImpl; -import org.transitclock.core.SpatialMatch; +import org.transitclock.core.RouteMatch; import org.transitclock.core.VehicleState; import org.transitclock.core.dataCache.HistoricalAverage; import org.transitclock.core.dataCache.StopPathCacheKey; @@ -85,7 +85,7 @@ public long getTravelTimeForPath(Indices indices, AvlReport avlReport, VehicleSt } @Override - public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport,SpatialMatch match) { + public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport,RouteMatch match) { Indices indices = match.getIndices(); Integer time=FrequencyBasedHistoricalAverageCache.secondsFromMidnight(new Date(match.getAvlTime()),2); diff --git a/transitclock/src/main/java/org/transitclock/db/structs/Block.java b/transitclock/src/main/java/org/transitclock/db/structs/Block.java index f5a2a21a6..808aa19b0 100644 --- a/transitclock/src/main/java/org/transitclock/db/structs/Block.java +++ b/transitclock/src/main/java/org/transitclock/db/structs/Block.java @@ -58,7 +58,7 @@ import org.transitclock.config.StringConfigValue; import org.transitclock.configData.AgencyConfig; import org.transitclock.configData.CoreConfig; -import org.transitclock.core.SpatialMatch; +import org.transitclock.core.RouteMatch; import org.transitclock.db.hibernate.HibernateUtils; import org.transitclock.gtfs.DbConfig; import org.transitclock.logging.Markers; @@ -1280,7 +1280,7 @@ public ScheduleTime getScheduleTime(int tripIndex, int stopPathIndex) { * @param distance * @return True if within distance of end of block */ - public boolean nearEndOfBlock(SpatialMatch match, double distance) { + public boolean nearEndOfBlock(RouteMatch match, double distance) { // If not last trip of block then not considered near end // so return false. if (match.getTripIndex() != trips.size()-1) diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicle.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicle.java index 422da6ca1..8507c9320 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicle.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicle.java @@ -28,7 +28,7 @@ import org.transitclock.applications.Core; import org.transitclock.core.BlockAssignmentMethod; -import org.transitclock.core.SpatialMatch; +import org.transitclock.core.RouteMatch; import org.transitclock.core.TemporalDifference; import org.transitclock.core.VehicleState; import org.transitclock.core.dataCache.PredictionDataCache; @@ -113,7 +113,7 @@ public IpcVehicle(VehicleState vs) { // Get the match. If match is just after a stop then adjust // it to just before the stop so that can determine proper // stop ID and such. - SpatialMatch match = vs.getMatch().getMatchBeforeStopIfAtStop(); + RouteMatch match = vs.getMatch().getMatchBeforeStopIfAtStop(); // Determine if vehicle is at layover, and if so, what time it // should depart. The departure time isn't necessarily the diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleComplete.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleComplete.java index 0dfbb42f1..45dabddee 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleComplete.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleComplete.java @@ -24,7 +24,7 @@ import java.util.List; import org.transitclock.core.BlockAssignmentMethod; -import org.transitclock.core.SpatialMatch; +import org.transitclock.core.RouteMatch; import org.transitclock.core.TemporalDifference; import org.transitclock.core.VehicleState; import org.transitclock.db.structs.Trip; @@ -75,7 +75,7 @@ public IpcVehicleComplete(VehicleState vs) { // Get the match. If match is just after a stop then adjust // it to just before the stop so that can determine proper // stop ID and such. - SpatialMatch match = vs.getMatch().getMatchBeforeStopIfAtStop(); + RouteMatch match = vs.getMatch().getMatchBeforeStopIfAtStop(); // If vehicle is at a stop then "next" stop will actually be // the current stop. this.distanceToNextStop = match.getDistanceRemainingInStopPath(); diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleGtfsRealtime.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleGtfsRealtime.java index e6765a818..88bac5ee8 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleGtfsRealtime.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcVehicleGtfsRealtime.java @@ -22,7 +22,7 @@ import org.transitclock.applications.Core; import org.transitclock.core.BlockAssignmentMethod; -import org.transitclock.core.SpatialMatch; +import org.transitclock.core.RouteMatch; import org.transitclock.core.TemporalDifference; import org.transitclock.core.TemporalMatch; import org.transitclock.core.VehicleState; @@ -89,7 +89,7 @@ public IpcVehicleGtfsRealtime(VehicleState vs) { // stop ID and gtfs stop sequence. TemporalMatch temporalMatch = vs.getMatch(); if (temporalMatch != null) { - SpatialMatch match = vs.getMatch().getMatchBeforeStopIfAtStop(); + RouteMatch match = vs.getMatch().getMatchBeforeStopIfAtStop(); atStop = match.getAtStop() != null; // Determine stop info depending on whether it is at a stop or in From cd6e57d10818d86ba3a54a17766470d06fb0880f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sean=20=C3=93g=20Crudden?= Date: Sun, 22 Mar 2020 14:15:10 +0000 Subject: [PATCH 06/17] More scaffolding. Connect api to rmi server for diversions. --- .../clients/DiversionsInterfaceFactory.java | 61 +++++++++++++++++++ .../api/rootResources/DiversionApi.java | 20 +++++- .../api/utils/StandardParameters.java | 18 ++++++ 3 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 transitclock/src/main/java/org/transitclock/ipc/clients/DiversionsInterfaceFactory.java diff --git a/transitclock/src/main/java/org/transitclock/ipc/clients/DiversionsInterfaceFactory.java b/transitclock/src/main/java/org/transitclock/ipc/clients/DiversionsInterfaceFactory.java new file mode 100644 index 000000000..065e79861 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/ipc/clients/DiversionsInterfaceFactory.java @@ -0,0 +1,61 @@ +/* + * This file is part of Transitime.org + * + * Transitime.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License (GPL) as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * Transitime.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Transitime.org . If not, see . + */ +package org.transitclock.ipc.clients; + +import java.util.HashMap; +import java.util.Map; + +import org.transitclock.ipc.interfaces.CacheQueryInterface; +import org.transitclock.ipc.interfaces.CommandsInterface; +import org.transitclock.ipc.interfaces.DiversionsInterface; +import org.transitclock.ipc.interfaces.HoldingTimeInterface; +import org.transitclock.ipc.rmi.ClientFactory; + +/** + * Provides a DiversionsInterface client that can be sent diversion queries. + * + * @author Sean Og Crudden + * + */ +public class DiversionsInterfaceFactory { + + // Keyed by agencyId + private static Map diversionsInterfaceMap = + new HashMap(); + + /********************** Member Functions **************************/ + + /** + * Gets the singleton instance. + * + * @param agencyId + * @return + */ + public static DiversionsInterface get(String agencyId) { + DiversionsInterface diversionInterface = + diversionsInterfaceMap.get(agencyId); + if (diversionInterface == null) { + + diversionInterface = ClientFactory.getInstance(agencyId, DiversionsInterface.class); + + diversionsInterfaceMap.put(agencyId, diversionInterface); + + } + return diversionInterface; + } + +} diff --git a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java index e1553dbd3..d0860a628 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java +++ b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java @@ -12,6 +12,8 @@ import org.transitclock.api.data.ApiDiversion; import org.transitclock.api.data.ApiDiversions; import org.transitclock.api.utils.StandardParameters; +import org.transitclock.ipc.data.IpcDiversions; +import org.transitclock.ipc.interfaces.DiversionsInterface; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -28,8 +30,15 @@ public Response getDiversionsByRouteId(@BeanParam StandardParameters stdParamete @Parameter(description="routeId to get diversions for.",required=true) @PathParam("routeId") String routeId) { stdParameters.validate(); + + DiversionsInterface diverionsInterface = stdParameters.getDiversionInterface(); - return stdParameters.createResponse(new ApiDiversions()); + IpcDiversions ipcDiversions = diverionsInterface.getDiversionsForRoute(routeId); + + ApiDiversions apiDiversions=new ApiDiversions(ipcDiversions.getDiversions()); + + return stdParameters.createResponse(apiDiversions); + } @Path("/command/getDiversionsByTrip") @GET @@ -41,8 +50,13 @@ public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameter @Parameter(description="tripId to get diversions for.",required=true) @PathParam("tripId") String tripId) { stdParameters.validate(); - - return stdParameters.createResponse(new ApiDiversions()); + DiversionsInterface diverionsInterface = stdParameters.getDiversionInterface(); + + IpcDiversions ipcDiversions = diverionsInterface.getDiversionsForTrip(tripId); + + ApiDiversions apiDiversions=new ApiDiversions(ipcDiversions.getDiversions()); + + return stdParameters.createResponse(apiDiversions); } } diff --git a/transitclockApi/src/main/java/org/transitclock/api/utils/StandardParameters.java b/transitclockApi/src/main/java/org/transitclock/api/utils/StandardParameters.java index 1a2052e8b..5ffffce5d 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/utils/StandardParameters.java +++ b/transitclockApi/src/main/java/org/transitclock/api/utils/StandardParameters.java @@ -33,6 +33,7 @@ import org.transitclock.ipc.clients.CacheQueryInterfaceFactory; import org.transitclock.ipc.clients.CommandsInterfaceFactory; import org.transitclock.ipc.clients.ConfigInterfaceFactory; +import org.transitclock.ipc.clients.DiversionsInterfaceFactory; import org.transitclock.ipc.clients.HoldingTimeInterfaceFactory; import org.transitclock.ipc.clients.PredictionAnalysisInterfaceFactory; import org.transitclock.ipc.clients.PredictionsInterfaceFactory; @@ -41,6 +42,7 @@ import org.transitclock.ipc.interfaces.CacheQueryInterface; import org.transitclock.ipc.interfaces.CommandsInterface; import org.transitclock.ipc.interfaces.ConfigInterface; +import org.transitclock.ipc.interfaces.DiversionsInterface; import org.transitclock.ipc.interfaces.HoldingTimeInterface; import org.transitclock.ipc.interfaces.PredictionAnalysisInterface; import org.transitclock.ipc.interfaces.PredictionsInterface; @@ -315,6 +317,22 @@ public HoldingTimeInterface getHoldingTimeInterface() return holdingTimeInterface ; } + /** + * Gets the DiversionsInterface for the specified agencyId. If not valid + * then throws WebApplicationException. + * + * @return The PredictionAnalysisInterface + */ + public DiversionsInterface getDiversionInterface() + { + DiversionsInterface diversionsInterface = DiversionsInterfaceFactory.get(agencyId); + if (diversionsInterface == null) + throw WebUtils.badRequestException("Agency ID " + agencyId + + " is not valid"); + + return diversionsInterface ; + } + /** * Simple getter for the key * From 1ec8a6e19d367d87d42d4db0a99bb1c012a59c93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sean=20=C3=93g=20Crudden?= Date: Sun, 22 Mar 2020 18:09:18 +0000 Subject: [PATCH 07/17] Base class for DiversionMatch and RouteMatch. --- .../org/transitclock/core/SpatialMatch.java | 26 +++++++++++++++++++ .../PredictionComponentElementsGenerator.java | 4 +-- 2 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 transitclock/src/main/java/org/transitclock/core/SpatialMatch.java diff --git a/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java b/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java new file mode 100644 index 000000000..edd02424c --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java @@ -0,0 +1,26 @@ +package org.transitclock.core; + +import org.transitclock.db.structs.Block; + +public class SpatialMatch { + protected final long avlTime; + protected final Block block; + protected final int tripIndex; + + public SpatialMatch(long avlTime, Block block, int tripIndex) { + super(); + this.avlTime = avlTime; + this.block = block; + this.tripIndex = tripIndex; + } + public long getAvlTime() { + return avlTime; + } + public Block getBlock() { + return block; + } + public int getTripIndex() { + return tripIndex; + } + +} diff --git a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/PredictionComponentElementsGenerator.java b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/PredictionComponentElementsGenerator.java index c521bcf0a..df32d1cdc 100755 --- a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/PredictionComponentElementsGenerator.java +++ b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/PredictionComponentElementsGenerator.java @@ -3,7 +3,7 @@ import org.transitclock.core.HeadwayDetails; import org.transitclock.core.Indices; -import org.transitclock.core.SpatialMatch; +import org.transitclock.core.RouteMatch; import org.transitclock.core.VehicleState; import org.transitclock.db.structs.AvlReport; import org.transitclock.ipc.data.IpcPrediction; @@ -14,6 +14,6 @@ public interface PredictionComponentElementsGenerator { long getStopTimeForPath(Indices indices, AvlReport avlReport, VehicleState vehicleState); - long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, SpatialMatch match); + long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, RouteMatch match); } \ No newline at end of file From d1d3a7372eb24ef0bab793126268f154e02fe8c1 Mon Sep 17 00:00:00 2001 From: scrudden Date: Fri, 3 Apr 2020 17:43:30 +0100 Subject: [PATCH 08/17] More scaffolding for diversion support. --- .../transitclock/ipc/data/IpcDiversion.java | 17 ++++++++++++ .../transitclock/ipc/data/IpcDiversions.java | 3 +++ .../ipc/servers/DiversionsServer.java | 27 +++++++++++++++++-- 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java index 0b3731738..2eee33c3a 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java @@ -4,6 +4,7 @@ import java.util.Date; import java.util.List; +import org.transitclock.core.diversion.model.Diversion; import org.transitclock.db.structs.Location; public class IpcDiversion implements Serializable{ @@ -56,6 +57,22 @@ public IpcDiversion(String routeId, String tripId, String shapeId, int startStop this.endTime = endTime; } + public IpcDiversion(Diversion diversion) { + + this.routeId = diversion.getRouteId(); + this.tripId = diversion.getTripId(); + this.shapeId = diversion.getShapeId(); + this.startStopSeq = diversion.getStartStopSeq(); + + this.distanceStartAlongSegment = diversion.getDistanceStartAlongSegment(); + this.returnStopSeq = diversion.getReturnStopSeq(); + this.distanceEndAlongSegment = diversion.getDistanceEndAlongSegment(); + this.detourPath = diversion.getDetourPath(); + this.stopLocations = diversion.getStopLocations(); + this.startTime = diversion.getStartTime(); + this.endTime = diversion.getEndTime(); + } + public String getRouteId() { return routeId; } diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java index 8be99ccc6..28bbf5593 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java @@ -3,6 +3,8 @@ import java.io.Serializable; import java.util.List; +import org.transitclock.core.diversion.cache.DiversionsList; + public class IpcDiversions implements Serializable{ /** * @@ -15,6 +17,7 @@ public IpcDiversions(List diversions) { super(); this.diversions = diversions; } + public List getDiversions() { return diversions; } diff --git a/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java index da129cfeb..d4dbecfe4 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java +++ b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java @@ -1,5 +1,15 @@ package org.transitclock.ipc.servers; +import java.util.ArrayList; +import java.util.List; + +import org.transitclock.applications.Core; +import org.transitclock.core.diversion.cache.DiversionsCacheFactory; +import org.transitclock.core.diversion.cache.DiversionsKey; +import org.transitclock.core.diversion.cache.DiversionsList; +import org.transitclock.core.diversion.model.Diversion; +import org.transitclock.db.structs.Trip; +import org.transitclock.ipc.data.IpcDiversion; import org.transitclock.ipc.data.IpcDiversions; import org.transitclock.ipc.interfaces.DiversionsInterface; import org.transitclock.ipc.rmi.AbstractServer; @@ -13,13 +23,26 @@ protected DiversionsServer(String agencyId, String objectName) { @Override public IpcDiversions getDiversionsForTrip(String tripId) { - // TODO Auto-generated method stub - return null; + Core core = Core.getInstance(); + Trip trip = core.getDbConfig().getTrip(tripId); + DiversionsKey key=new DiversionsKey(tripId, trip.getRouteId()); + + DiversionsList diversions = DiversionsCacheFactory.getInstance().getDiversions(key); + + List ipcDiversions=new ArrayList(); + + for( Diversion diversion:diversions.getDiversions()) + { + ipcDiversions.add(new IpcDiversion(diversion)); + } + + return new IpcDiversions(ipcDiversions); } @Override public IpcDiversions getDiversionsForRoute(String routeId) { // TODO Auto-generated method stub + DiversionsCacheFactory.getInstance(); return null; } From eadb5d8541b8cac25347c381da96702ed221e64d Mon Sep 17 00:00:00 2001 From: scrudden Date: Mon, 6 Apr 2020 17:47:41 +0100 Subject: [PATCH 09/17] Fixes for issues found running against test data. --- .../org/transitclock/applications/Core.java | 2 + .../transitclock/applications/RmiQuery.java | 22 ++++++- .../core/diversion/cache/DiversionsKey.java | 61 ++++++++++++++++++- .../core/diversion/cache/DiversionsList.java | 3 +- .../core/diversion/model/Diversion.java | 13 +++- .../transitclock/ipc/data/IpcDiversion.java | 8 +++ .../transitclock/ipc/data/IpcDiversions.java | 6 ++ .../ipc/interfaces/DiversionsInterface.java | 5 +- .../ipc/servers/DiversionsServer.java | 53 ++++++++++++---- 9 files changed, 149 insertions(+), 24 deletions(-) diff --git a/transitclock/src/main/java/org/transitclock/applications/Core.java b/transitclock/src/main/java/org/transitclock/applications/Core.java index 6fe291402..45a99d8b8 100755 --- a/transitclock/src/main/java/org/transitclock/applications/Core.java +++ b/transitclock/src/main/java/org/transitclock/applications/Core.java @@ -56,6 +56,7 @@ import org.transitclock.ipc.servers.CacheQueryServer; import org.transitclock.ipc.servers.CommandsServer; import org.transitclock.ipc.servers.ConfigServer; +import org.transitclock.ipc.servers.DiversionsServer; import org.transitclock.ipc.servers.HoldingTimeServer; import org.transitclock.ipc.servers.PredictionAnalysisServer; import org.transitclock.ipc.servers.PredictionsServer; @@ -409,6 +410,7 @@ public static void startRmiServers(String agencyId) { CacheQueryServer.start(agencyId); PredictionAnalysisServer.start(agencyId); HoldingTimeServer.start(agencyId); + DiversionsServer.start(agencyId); } static private void populateCaches() throws Exception diff --git a/transitclock/src/main/java/org/transitclock/applications/RmiQuery.java b/transitclock/src/main/java/org/transitclock/applications/RmiQuery.java index 7b90ffeb3..873ddae00 100644 --- a/transitclock/src/main/java/org/transitclock/applications/RmiQuery.java +++ b/transitclock/src/main/java/org/transitclock/applications/RmiQuery.java @@ -34,11 +34,13 @@ import org.transitclock.db.structs.Location; import org.transitclock.ipc.clients.CommandsInterfaceFactory; import org.transitclock.ipc.clients.ConfigInterfaceFactory; +import org.transitclock.ipc.clients.DiversionsInterfaceFactory; import org.transitclock.ipc.clients.PredictionsInterfaceFactory; import org.transitclock.ipc.clients.VehiclesInterfaceFactory; import org.transitclock.ipc.data.IpcActiveBlock; import org.transitclock.ipc.data.IpcBlock; import org.transitclock.ipc.data.IpcDirectionsForRoute; +import org.transitclock.ipc.data.IpcDiversions; import org.transitclock.ipc.data.IpcPredictionsForRouteStopDest; import org.transitclock.ipc.data.IpcRoute; import org.transitclock.ipc.data.IpcRouteSummary; @@ -48,6 +50,7 @@ import org.transitclock.ipc.data.IpcVehicleComplete; import org.transitclock.ipc.interfaces.CommandsInterface; import org.transitclock.ipc.interfaces.ConfigInterface; +import org.transitclock.ipc.interfaces.DiversionsInterface; import org.transitclock.ipc.interfaces.PredictionsInterface; import org.transitclock.ipc.interfaces.VehiclesInterface; import org.transitclock.ipc.interfaces.PredictionsInterface.RouteStop; @@ -79,7 +82,7 @@ public class RmiQuery { private static enum Command {NOT_SPECIFIED, GET_PREDICTIONS, GET_VEHICLES, GET_ROUTE_CONFIG, GET_CONFIG, - GET_ACTIVE_BLOCKS, RESET_VEHICLE}; + GET_ACTIVE_BLOCKS, RESET_VEHICLE, GET_DETOURS}; /********************** Member Functions **************************/ @@ -197,6 +200,8 @@ else if ("activeBlocks".equals(commandStr)) command = Command.GET_ACTIVE_BLOCKS; else if ("resetVehicle".equals(commandStr)) command = Command.RESET_VEHICLE; + else if("detours".equals(commandStr)) + command = Command.GET_DETOURS; else { System.out.println("Command \"" + commandStr + "\" is not valid.\n"); displayCommandLineOptionsAndExit(options); @@ -461,13 +466,26 @@ public static void main(String[] args) { getActiveBlocks(); } else if(command == Command.RESET_VEHICLE) { resetVehicles(); - } + } else if(command == Command.GET_DETOURS) + getDetours(); + } catch (Exception e) { // Output stack trace as error message e.printStackTrace(); } } + private static void getDetours() throws Exception { + // TODO Auto-generated method stub + DiversionsInterface detourInterface=DiversionsInterfaceFactory.get(agencyId); + + IpcDiversions result = detourInterface.getDiversionsForTrip(tripId); + + if(result!=null) + System.out.println(result.toString()); + + } + private static void resetVehicles() throws Exception { CommandsInterface commandsInterface = CommandsInterfaceFactory.get(agencyId); diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java index 4228b51d1..fd2a94652 100644 --- a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java @@ -1,14 +1,71 @@ package org.transitclock.core.diversion.cache; +import java.io.Serializable; + import org.transitclock.core.diversion.model.Diversion; -public class DiversionsKey { +public class DiversionsKey implements Serializable { + /** + * + */ + private static final long serialVersionUID = 5427491805221655172L; String tripId; String routeId; public DiversionsKey(Diversion diversion) { this.tripId=diversion.getTripId(); - this.routeId=diversion.getTripId(); + this.routeId=diversion.getRouteId(); } + public DiversionsKey(String tripId, String routeId) { + super(); + this.tripId = tripId; + this.routeId = routeId; + } + + + + public String getTripId() { + return tripId; + } + + + + public String getRouteId() { + return routeId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((routeId == null) ? 0 : routeId.hashCode()); + result = prime * result + ((tripId == null) ? 0 : tripId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DiversionsKey other = (DiversionsKey) obj; + if (routeId == null) { + if (other.routeId != null) + return false; + } else if (!routeId.equals(other.routeId)) + return false; + if (tripId == null) { + if (other.tripId != null) + return false; + } else if (!tripId.equals(other.tripId)) + return false; + return true; + } + + + } diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java index b7c9e62e9..7bd897322 100644 --- a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsList.java @@ -3,7 +3,6 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; - import org.transitclock.core.diversion.model.Diversion; public class DiversionsList implements Serializable { @@ -13,7 +12,7 @@ public class DiversionsList implements Serializable { */ private static final long serialVersionUID = -6633598451497950140L; - List diversions=null; + List diversions=new ArrayList(); public List getDiversions() { return diversions; diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java index e63986aa1..12736a380 100644 --- a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java +++ b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java @@ -1,5 +1,7 @@ package org.transitclock.core.diversion.model; +import java.io.Serializable; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -11,8 +13,13 @@ * @author Sean Óg Crudden * This is the starting point of modeling a detour. */ -public class Diversion { +public class Diversion implements Serializable { + /** + * + */ + private static final long serialVersionUID = 8573881954740003230L; + private String routeId; private String tripId; @@ -27,9 +34,9 @@ public class Diversion { private int distanceEndAlongSegment; - private List detourPath; + private List detourPath=new ArrayList(); - private List stopLocations; + private List stopLocations=new ArrayList(); private Date startTime; diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java index 2eee33c3a..aa6be9193 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java @@ -160,5 +160,13 @@ public Date getEndTime() { public void setEndTime(Date endTime) { this.endTime = endTime; } + + @Override + public String toString() { + return "IpcDiversion [routeId=" + routeId + ", tripId=" + tripId + ", shapeId=" + shapeId + ", startStopSeq=" + + startStopSeq + ", distanceStartAlongSegment=" + distanceStartAlongSegment + ", returnStopSeq=" + + returnStopSeq + ", distanceEndAlongSegment=" + distanceEndAlongSegment + ", detourPath=" + detourPath + + ", stopLocations=" + stopLocations + ", startTime=" + startTime + ", endTime=" + endTime + "]"; + } } diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java index 28bbf5593..bdacda570 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversions.java @@ -21,4 +21,10 @@ public IpcDiversions(List diversions) { public List getDiversions() { return diversions; } + + @Override + public String toString() { + return "IpcDiversions [diversions=" + diversions + "]"; + } + } diff --git a/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java b/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java index 577422750..27311a83d 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java +++ b/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java @@ -1,10 +1,11 @@ package org.transitclock.ipc.interfaces; import java.rmi.Remote; +import java.rmi.RemoteException; import org.transitclock.ipc.data.IpcDiversions; public interface DiversionsInterface extends Remote { - IpcDiversions getDiversionsForTrip(String tripId); - IpcDiversions getDiversionsForRoute(String routeId); + IpcDiversions getDiversionsForTrip(String tripId) throws RemoteException; + IpcDiversions getDiversionsForRoute(String routeId) throws RemoteException; } diff --git a/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java index d4dbecfe4..1bb2b4459 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java +++ b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java @@ -1,8 +1,11 @@ package org.transitclock.ipc.servers; +import java.rmi.RemoteException; import java.util.ArrayList; import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.transitclock.applications.Core; import org.transitclock.core.diversion.cache.DiversionsCacheFactory; import org.transitclock.core.diversion.cache.DiversionsKey; @@ -12,35 +15,59 @@ import org.transitclock.ipc.data.IpcDiversion; import org.transitclock.ipc.data.IpcDiversions; import org.transitclock.ipc.interfaces.DiversionsInterface; +import org.transitclock.ipc.interfaces.HoldingTimeInterface; import org.transitclock.ipc.rmi.AbstractServer; public class DiversionsServer extends AbstractServer implements DiversionsInterface { - - protected DiversionsServer(String agencyId, String objectName) { - super(agencyId, objectName); - // TODO Auto-generated constructor stub + private static DiversionsServer singleton; + + private static final Logger logger = LoggerFactory.getLogger(DiversionsServer.class); + + protected DiversionsServer(String agencyId) { + super(agencyId, DiversionsInterface.class.getSimpleName()); + } + + public static DiversionsServer start(String agencyId) { + if (singleton == null) { + singleton = new DiversionsServer(agencyId); + } + if (!singleton.getAgencyId().equals(agencyId)) { + logger.error( + "Tried calling DiversionsServer.start() for " + + "agencyId={} but the singleton was created for agencyId={}", + agencyId, singleton.getAgencyId()); + return null; + } + return singleton; } @Override - public IpcDiversions getDiversionsForTrip(String tripId) { + public IpcDiversions getDiversionsForTrip(String tripId) throws RemoteException { Core core = Core.getInstance(); Trip trip = core.getDbConfig().getTrip(tripId); - DiversionsKey key=new DiversionsKey(tripId, trip.getRouteId()); - DiversionsList diversions = DiversionsCacheFactory.getInstance().getDiversions(key); + if(trip!=null) + { + DiversionsKey key=new DiversionsKey(tripId, trip.getRouteId()); - List ipcDiversions=new ArrayList(); + DiversionsList diversions = DiversionsCacheFactory.getInstance().getDiversions(key); - for( Diversion diversion:diversions.getDiversions()) + List ipcDiversions=new ArrayList(); + + for( Diversion diversion:diversions.getDiversions()) + { + ipcDiversions.add(new IpcDiversion(diversion)); + } + + return new IpcDiversions(ipcDiversions); + }else { - ipcDiversions.add(new IpcDiversion(diversion)); + return null; } - - return new IpcDiversions(ipcDiversions); } @Override - public IpcDiversions getDiversionsForRoute(String routeId) { + public IpcDiversions getDiversionsForRoute(String routeId) throws RemoteException { // TODO Auto-generated method stub DiversionsCacheFactory.getInstance(); return null; From 9eb8c263c6b9ea267b286680930631047ba87835 Mon Sep 17 00:00:00 2001 From: scrudden Date: Mon, 6 Apr 2020 19:50:36 +0100 Subject: [PATCH 10/17] Now can get detours from RMI server. --- .../core/diversion/cache/DiversionsKey.java | 20 ++---- .../GtfsRtVehiclePositionsReaderBase.java | 63 +++++++++++-------- .../api/rootResources/DiversionApi.java | 44 ++++++++----- 3 files changed, 70 insertions(+), 57 deletions(-) diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java index fd2a94652..26c17e189 100644 --- a/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java +++ b/transitclock/src/main/java/org/transitclock/core/diversion/cache/DiversionsKey.java @@ -10,17 +10,16 @@ public class DiversionsKey implements Serializable { */ private static final long serialVersionUID = 5427491805221655172L; String tripId; - String routeId; + public DiversionsKey(Diversion diversion) { this.tripId=diversion.getTripId(); - this.routeId=diversion.getRouteId(); + } public DiversionsKey(String tripId, String routeId) { super(); this.tripId = tripId; - this.routeId = routeId; } @@ -29,17 +28,10 @@ public String getTripId() { return tripId; } - - - public String getRouteId() { - return routeId; - } - @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((routeId == null) ? 0 : routeId.hashCode()); result = prime * result + ((tripId == null) ? 0 : tripId.hashCode()); return result; } @@ -53,11 +45,6 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; DiversionsKey other = (DiversionsKey) obj; - if (routeId == null) { - if (other.routeId != null) - return false; - } else if (!routeId.equals(other.routeId)) - return false; if (tripId == null) { if (other.tripId != null) return false; @@ -68,4 +55,7 @@ public boolean equals(Object obj) { + + + } diff --git a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java index 653df5d3b..6836fe970 100644 --- a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java +++ b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java @@ -20,8 +20,8 @@ import java.io.InputStream; import java.net.URI; import java.net.URL; - - +import java.util.HashMap; +import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -128,11 +128,25 @@ private void processMessage(FeedMessage message) { logger.info("Processing each individual AvlReport..."); IntervalTimer timer = new IntervalTimer(); + Map shapes=new HashMap(); + // For each entity/vehicle process the data int counter = 0; + + for (FeedEntity entity : message.getEntityList()) + { + if(entity.hasShape()) + { + Shape shape = entity.getShape(); + + if(!shapes.containsKey(shape.getShapeId())) + { + shapes.put(shape.getShapeId(), shape); + } + } + } for (FeedEntity entity : message.getEntityList()) { - // If no vehicles in the entity then nothing to process - + // If no vehicles in the entity then nothing to process if(entity.hasTripUpdate()) { TripUpdate tripUpdate = entity.getTripUpdate(); @@ -140,31 +154,26 @@ private void processMessage(FeedMessage message) { { TripProperties tripProperties = tripUpdate.getTripProperties(); if(tripProperties.hasShapeId()) - { - tripProperties.getShapeId(); - - if(entity.hasShape()) + { + if(shapes.containsKey(tripProperties.getShapeId())) { - Shape shape = entity.getShape(); - shape.getShapeId(); - - if(tripProperties.getShapeId().equals(shape.getShapeId())) - { - Diversion detour=new Diversion(); - detour.setTripId(tripUpdate.getTrip().getTripId()); - detour.setRouteId(tripUpdate.getTrip().getRouteId()); - - for(ShapePoint shapePoint : shape.getShapePointList()) - { - Location location=new Location(shapePoint.getShapePtLat(), shapePoint.getShapePtLon()); - detour.getStopLocations().add(location); - } - - if(DiversionsCacheFactory.getInstance()!=null) - DiversionsCacheFactory.getInstance().putDiversion(detour); - - logger.debug("Have found shape update to process.",tripUpdate.toString()); + Shape shape = shapes.get(tripProperties.getShapeId()); + + Diversion detour=new Diversion(); + detour.setShapeId(tripProperties.getShapeId()); + detour.setTripId(tripUpdate.getTrip().getTripId()); + detour.setRouteId(tripUpdate.getTrip().getRouteId()); + + for(ShapePoint shapePoint : shape.getShapePointList()) + { + Location location=new Location(shapePoint.getShapePtLat(), shapePoint.getShapePtLon()); + detour.getDetourPath().add(location); } + + if(DiversionsCacheFactory.getInstance()!=null) + DiversionsCacheFactory.getInstance().putDiversion(detour); + + logger.debug("Have found shape update to process.",tripUpdate.toString()); } } } diff --git a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java index d0860a628..2b0f78e15 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java +++ b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java @@ -1,10 +1,13 @@ package org.transitclock.api.rootResources; +import java.rmi.RemoteException; + import javax.ws.rs.BeanParam; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -12,6 +15,7 @@ import org.transitclock.api.data.ApiDiversion; import org.transitclock.api.data.ApiDiversions; import org.transitclock.api.utils.StandardParameters; +import org.transitclock.api.utils.WebUtils; import org.transitclock.ipc.data.IpcDiversions; import org.transitclock.ipc.interfaces.DiversionsInterface; @@ -27,18 +31,22 @@ public class DiversionApi { description="This is to give the means of manually setting a vehicle unpredictable and unassigned so it will be reassigned quickly.", tags= {"command","vehicle"}) public Response getDiversionsByRouteId(@BeanParam StandardParameters stdParameters, - @Parameter(description="routeId to get diversions for.",required=true) @PathParam("routeId") String routeId) + @Parameter(description="routeId to get diversions for.",required=true) @PathParam("routeId") String routeId) throws WebApplicationException { stdParameters.validate(); - - DiversionsInterface diverionsInterface = stdParameters.getDiversionInterface(); - - IpcDiversions ipcDiversions = diverionsInterface.getDiversionsForRoute(routeId); - - ApiDiversions apiDiversions=new ApiDiversions(ipcDiversions.getDiversions()); + try { + DiversionsInterface diverionsInterface = stdParameters.getDiversionInterface(); + + IpcDiversions ipcDiversions = diverionsInterface.getDiversionsForRoute(routeId); - return stdParameters.createResponse(apiDiversions); + ApiDiversions apiDiversions=new ApiDiversions(ipcDiversions.getDiversions()); + return stdParameters.createResponse(apiDiversions); + + } catch (Exception e) { + // If problem getting data then return a Bad Request + throw WebUtils.badRequestException(e); + } } @Path("/command/getDiversionsByTrip") @GET @@ -47,16 +55,22 @@ public Response getDiversionsByRouteId(@BeanParam StandardParameters stdParamete description="This is to give the means of manually setting a vehicle unpredictable and unassigned so it will be reassigned quickly.", tags= {"command","vehicle"}) public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameters, - @Parameter(description="tripId to get diversions for.",required=true) @PathParam("tripId") String tripId) + @Parameter(description="tripId to get diversions for.",required=true) @PathParam("tripId") String tripId) throws WebApplicationException { stdParameters.validate(); - DiversionsInterface diverionsInterface = stdParameters.getDiversionInterface(); - - IpcDiversions ipcDiversions = diverionsInterface.getDiversionsForTrip(tripId); - - ApiDiversions apiDiversions=new ApiDiversions(ipcDiversions.getDiversions()); + try { + DiversionsInterface diverionsInterface = stdParameters.getDiversionInterface(); + + IpcDiversions ipcDiversions = diverionsInterface.getDiversionsForTrip(tripId); + + ApiDiversions apiDiversions=new ApiDiversions(ipcDiversions.getDiversions()); + + return stdParameters.createResponse(apiDiversions); - return stdParameters.createResponse(apiDiversions); + } catch (Exception e) { + // If problem getting data then return a Bad Request + throw WebUtils.badRequestException(e); + } } } From c04baee2dfc62d3ecbf569a5bb428e4dea7826c2 Mon Sep 17 00:00:00 2001 From: scrudden Date: Thu, 9 Apr 2020 17:09:55 +0100 Subject: [PATCH 11/17] Start of diversion matching work. WIP. --- .../org/transitclock/core/AvlProcessor.java | 13 +++- .../org/transitclock/core/DiversionMatch.java | 59 +++++++++++++-- .../transitclock/core/DiversionMatcher.java | 73 +++++++++++++++++++ .../transitclock/core/TemporalMatcher.java | 3 +- .../core/diversion/model/Diversion.java | 72 ++++++++++++------ .../transitclock/db/structs/Diversion.java | 58 ++++++++++++++- .../transitclock/api/data/ApiDiversions.java | 2 +- .../api/rootResources/DiversionApi.java | 18 ++++- 8 files changed, 258 insertions(+), 40 deletions(-) create mode 100644 transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java diff --git a/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java b/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java index 59dea4f18..794710391 100644 --- a/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java +++ b/transitclock/src/main/java/org/transitclock/core/AvlProcessor.java @@ -441,17 +441,24 @@ public void matchNewFixForPredictableVehicle(VehicleState vehicleState) { logger.debug("Matching already predictable vehicle using new AVL " + "report. The old spatial match is {}", vehicleState); - // Find possible spatial matches + // Find possible route matches List spatialMatches = SpatialMatcher .getSpatialMatches(vehicleState); logger.debug("For vehicleId={} found the following {} spatial " + "matches: {}", vehicleState.getVehicleId(), spatialMatches.size(), spatialMatches); + + // Find possible diversion matches. + List divesionMatches = DiversionMatcher.getDiversionMatches(vehicleState); + logger.debug("For vehicleId={} found the following {} diversion " + + "matches: {}", vehicleState.getVehicleId(), + divesionMatches.size(), divesionMatches); + // Find best temporal match of the spatial matches TemporalMatch bestTemporalMatch = TemporalMatcher.getInstance() - .getBestTemporalMatch(vehicleState, spatialMatches); - + .getBestTemporalMatch(vehicleState, spatialMatches, divesionMatches); + // Log this as info since matching is a significant milestone logger.info("For vehicleId={} the best match is {}", vehicleState.getVehicleId(), bestTemporalMatch); diff --git a/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java index 28563bfc9..26dcbd578 100644 --- a/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java +++ b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java @@ -6,27 +6,40 @@ public class DiversionMatch extends SpatialMatch { - public DiversionMatch(long avlTime, Block block, int tripIndex) { + public DiversionMatch(Double distanceToDiversion, Double distanceAlongDiversion, long avlTime, Block block, int tripIndex, String shapeId, String tripId, String routeId) { super(avlTime, block, tripIndex); + + this.routeId=routeId; + this.tripId=tripId; + this.shapeId=shapeId; + this.distanceAlongDiversion=distanceAlongDiversion; + } - int distanceAlongDiversion; - int distanceToDiversion; + Double distanceAlongDiversion; + Double distanceToDiversion; + Location predictedLocation; + + String routeId; + String tripId; + String shapeId; - public int getDistanceAlongDiversion() { + + + public Double getDistanceAlongDiversion() { return distanceAlongDiversion; } - public void setDistanceAlongDiversion(int distanceAlongDiversion) { + public void setDistanceAlongDiversion(Double distanceAlongDiversion) { this.distanceAlongDiversion = distanceAlongDiversion; } - public int getDistanceToDiversion() { + public Double getDistanceToDiversion() { return distanceToDiversion; } - public void setDistanceToDiversion(int distanceToDiversion) { + public void setDistanceToDiversion(Double distanceToDiversion) { this.distanceToDiversion = distanceToDiversion; } @@ -37,6 +50,38 @@ public Diversion getDiversion() { public void setDiversion(Diversion diversion) { this.diversion = diversion; } + + public String getRouteId() { + return routeId; + } + + public void setRouteId(String routeId) { + this.routeId = routeId; + } + + public String getTripId() { + return tripId; + } + + public void setTripId(String tripId) { + this.tripId = tripId; + } + + public String getShapeId() { + return shapeId; + } + + public void setShapeId(String shapeId) { + this.shapeId = shapeId; + } + + public Location getPredictedLocation() { + return predictedLocation; + } + + public void setPredictedLocation(Location predictedLocation) { + this.predictedLocation = predictedLocation; + } Diversion diversion; diff --git a/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java b/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java new file mode 100644 index 000000000..6bad216b7 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java @@ -0,0 +1,73 @@ +package org.transitclock.core; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import org.transitclock.applications.Core; +import org.transitclock.configData.CoreConfig; +import org.transitclock.core.diversion.cache.DiversionsCacheFactory; +import org.transitclock.core.diversion.cache.DiversionsKey; +import org.transitclock.core.diversion.cache.DiversionsList; +import org.transitclock.core.diversion.model.Diversion; +import org.transitclock.db.structs.AvlReport; +import org.transitclock.db.structs.VectorWithHeading; + +/** + * @author scrudden This is to find possible matches to a diversion. + * + */ + +public class DiversionMatcher { + + public static List getDiversionMatches(VehicleState vehicleState) { + AvlReport avlReport = vehicleState.getAvlReport(); + // The matches to be returned + List diversionMatches = new ArrayList(); + + String tripId = vehicleState.getTrip().getId(); + String routeId = vehicleState.getRouteId(); + + DiversionsKey key = new DiversionsKey(tripId, routeId); + + DiversionsList diversions = DiversionsCacheFactory.getInstance().getDiversions(key); + + if (diversions != null && diversions.getDiversions() != null) { + for (Diversion diversion : diversions.getDiversions()) { + /* Check if diversion applies to this trip. */ + if (diversion.getTripId().equals(vehicleState.getTrip().getId())) { + + /* + * Check if diversion is currently in place. Null start and end time means in + * place all the time. + */ + if ((diversion.getStartTime() == null && diversion.getEndTime() == null) + || (diversion.getStartTime().before(new Date(Core.getInstance().getSystemTime())) + && diversion.getEndTime().after(new Date(Core.getInstance().getSystemTime())))) { + Double minDistanceToSegment = null; + for (VectorWithHeading vector : diversion.getVectors()) { + Double distanceToSegment = vector.distance(avlReport.getLocation()); + + if (distanceToSegment < minDistanceToSegment || minDistanceToSegment < 0) { + minDistanceToSegment = distanceToSegment; + } + } + + // Check if within acceptable range of diversion to match to it. + if (minDistanceToSegment < CoreConfig.getMaxDistanceFromSegment()) { + DiversionMatch diversionMatch = new DiversionMatch(minDistanceToSegment, null, + avlReport.getTime(), vehicleState.getBlock(), + vehicleState.getTrip().getIndexInBlock(), diversion.getShapeId(), + diversion.getTripId(), diversion.getRouteId()); + + diversionMatches.add(diversionMatch); + } + + } + } + } + } + + return diversionMatches; + } +} diff --git a/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java b/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java index 8131ebfec..dcd5349e6 100644 --- a/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java +++ b/transitclock/src/main/java/org/transitclock/core/TemporalMatcher.java @@ -355,11 +355,12 @@ private boolean isProblematicLayover(VehicleState vehicleState, * * @param vehicleState * @param spatialMatches + * @param divesionMatches * @return The best temporal match for the spatial matches passed in. If no * valid temporal match found then returns null. */ public TemporalMatch getBestTemporalMatch(VehicleState vehicleState, - List spatialMatches) { + List spatialMatches, List divesionMatches) { // Convenience variables RouteMatch previousMatch = vehicleState.getMatch(); Date previousAvlTime = diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java index 12736a380..9db54b312 100644 --- a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java +++ b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java @@ -5,50 +5,56 @@ import java.util.Date; import java.util.List; +import javax.persistence.Transient; + import org.transitclock.db.structs.Location; import org.transitclock.db.structs.Route; import org.transitclock.db.structs.Trip; +import org.transitclock.db.structs.VectorWithHeading; /** - * @author Sean Óg Crudden - * This is the starting point of modeling a detour. + * @author Sean Óg Crudden This is the starting point of modeling a detour. */ public class Diversion implements Serializable { - + /** * */ private static final long serialVersionUID = 8573881954740003230L; private String routeId; - + private String tripId; - + private String shapeId; - + private int startStopSeq; - + private int distanceStartAlongSegment; - + private int returnStopSeq; - + private int distanceEndAlongSegment; - - private List detourPath=new ArrayList(); - - private List stopLocations=new ArrayList(); - + + private List detourPath = new ArrayList(); + + private List stopLocations = new ArrayList(); + private Date startTime; - - private Date endTime; + + private Date endTime; + + private List vectors = null; + public Diversion() { super(); // TODO Auto-generated constructor stub } - public Diversion(String routeId, String tripId,String shapeId, int startStopSeq, int distanceStartAlongSegment, int returnStopSeq, - int distanceEndAlongSegment, List detourPath, List stopLocations, Date startTime, Date endTime) { + public Diversion(String routeId, String tripId, String shapeId, int startStopSeq, int distanceStartAlongSegment, + int returnStopSeq, int distanceEndAlongSegment, List detourPath, List stopLocations, + Date startTime, Date endTime) { super(); this.routeId = routeId; this.tripId = tripId; @@ -59,8 +65,25 @@ public Diversion(String routeId, String tripId,String shapeId, int startStopSeq, this.distanceEndAlongSegment = distanceEndAlongSegment; this.detourPath = detourPath; this.stopLocations = stopLocations; - this.startTime=startTime; - this.endTime=endTime; + this.startTime = startTime; + this.endTime = endTime; + + initVectors(); + } + private void initVectors() + { + vectors = new ArrayList(detourPath.size() - 1); + for (int segmentIndex = 0; segmentIndex < detourPath.size() - 1; ++segmentIndex) { + VectorWithHeading v = new VectorWithHeading(nullSafeLocation(detourPath.get(segmentIndex)), + nullSafeLocation(detourPath.get(segmentIndex + 1))); + vectors.add(v); + } + } + private Location nullSafeLocation(Location location) { + if (location == null) { + location = new Location(0.0, 0.0); + } + return location; } public Date getStartTime() { @@ -150,6 +173,12 @@ public String getShapeId() { public void setShapeId(String shapeId) { this.shapeId = shapeId; } + + public List getVectors() { + if(vectors==null) + initVectors(); + return vectors; + } @Override public int hashCode() { @@ -224,7 +253,4 @@ public boolean equals(Object obj) { return true; } - - - } diff --git a/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java b/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java index 055bf931d..56cc29ff2 100644 --- a/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java +++ b/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java @@ -1,6 +1,7 @@ package org.transitclock.db.structs; import java.io.Serializable; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -10,12 +11,16 @@ import javax.persistence.Id; import javax.persistence.OrderColumn; import javax.persistence.Table; +import javax.persistence.Transient; +import org.hibernate.CallbackException; +import org.hibernate.Session; import org.hibernate.annotations.DynamicUpdate; +import org.hibernate.classic.Lifecycle; @Entity @DynamicUpdate @Table(name="Diversions") -public class Diversion implements Serializable{ +public class Diversion implements Serializable, Lifecycle { /** * */ @@ -55,7 +60,13 @@ public class Diversion implements Serializable{ @ElementCollection @OrderColumn private List stopLocations; + + @Transient + private List vectors = null; + public Diversion() { + super(); + } public Diversion(String routeId, String tripId, String shapeId, Date startTime, Date endTime, int startStopSeq, int distanceStartAlongSegment, int returnStopSeq, int distanceEndAlongSegment, List detourPath, List stopLocations) { @@ -71,6 +82,30 @@ public Diversion(String routeId, String tripId, String shapeId, Date startTime, this.distanceEndAlongSegment = distanceEndAlongSegment; this.detourPath = detourPath; this.stopLocations = stopLocations; + + vectors = new ArrayList(detourPath.size()-1); + for (int segmentIndex=0; segmentIndex(detourPath.size()-1); + for (int segmentIndex=0; segmentIndex getStopLocations() { public void setStopLocations(List stopLocations) { this.stopLocations = stopLocations; } + + + public List getVectors() { + return vectors; + } + @Override public int hashCode() { final int prime = 31; @@ -233,6 +274,21 @@ public boolean equals(Object obj) { return false; return true; } + @Override + public boolean onSave(Session s) throws CallbackException { + // TODO Auto-generated method stub + return false; + } + @Override + public boolean onUpdate(Session s) throws CallbackException { + // TODO Auto-generated method stub + return false; + } + @Override + public boolean onDelete(Session s) throws CallbackException { + // TODO Auto-generated method stub + return false; + } } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java index bbd0639d7..233ad5206 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java @@ -22,7 +22,7 @@ public ApiDiversions(List ipcDiversions) { diversions.add(new ApiDiversion(ipcDiversion)); } } - @XmlElement + @XmlElement(name="diversion") private List diversions; public List getDiversions() { return diversions; diff --git a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java index 2b0f78e15..7f8c088dc 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java +++ b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java @@ -7,6 +7,7 @@ import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -31,7 +32,7 @@ public class DiversionApi { description="This is to give the means of manually setting a vehicle unpredictable and unassigned so it will be reassigned quickly.", tags= {"command","vehicle"}) public Response getDiversionsByRouteId(@BeanParam StandardParameters stdParameters, - @Parameter(description="routeId to get diversions for.",required=true) @PathParam("routeId") String routeId) throws WebApplicationException + @Parameter(description="routeId to get diversions for.",required=true) @QueryParam("routeId") String routeId) throws WebApplicationException { stdParameters.validate(); try { @@ -55,7 +56,7 @@ public Response getDiversionsByRouteId(@BeanParam StandardParameters stdParamete description="This is to give the means of manually setting a vehicle unpredictable and unassigned so it will be reassigned quickly.", tags= {"command","vehicle"}) public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameters, - @Parameter(description="tripId to get diversions for.",required=true) @PathParam("tripId") String tripId) throws WebApplicationException + @Parameter(description="tripId to get diversions for.",required=true) @QueryParam("tripId") String tripId) throws WebApplicationException { stdParameters.validate(); @@ -65,8 +66,17 @@ public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameter IpcDiversions ipcDiversions = diverionsInterface.getDiversionsForTrip(tripId); ApiDiversions apiDiversions=new ApiDiversions(ipcDiversions.getDiversions()); - - return stdParameters.createResponse(apiDiversions); + + Response result = null; + try { + result = stdParameters.createResponse(apiDiversions); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + return result; + } catch (Exception e) { // If problem getting data then return a Bad Request From c094c9edd1640056e248ea0dd25d4c9a339bb557 Mon Sep 17 00:00:00 2001 From: scrudden Date: Thu, 9 Apr 2020 19:10:28 +0100 Subject: [PATCH 12/17] DiversonMatcher now finds the closest point on the diversions to the current avl reading. --- .../transitclock/core/DiversionMatcher.java | 55 ++++++++++--------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java b/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java index 6bad216b7..f19ddded7 100644 --- a/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java +++ b/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java @@ -30,44 +30,45 @@ public static List getDiversionMatches(VehicleState vehicleState DiversionsKey key = new DiversionsKey(tripId, routeId); - DiversionsList diversions = DiversionsCacheFactory.getInstance().getDiversions(key); + if (DiversionsCacheFactory.getInstance() != null) { + DiversionsList diversions = DiversionsCacheFactory.getInstance().getDiversions(key); - if (diversions != null && diversions.getDiversions() != null) { - for (Diversion diversion : diversions.getDiversions()) { - /* Check if diversion applies to this trip. */ - if (diversion.getTripId().equals(vehicleState.getTrip().getId())) { + if (diversions != null && diversions.getDiversions() != null) { + for (Diversion diversion : diversions.getDiversions()) { + /* Check if diversion applies to this trip. */ + if (diversion.getTripId().equals(vehicleState.getTrip().getId())) { - /* - * Check if diversion is currently in place. Null start and end time means in - * place all the time. - */ - if ((diversion.getStartTime() == null && diversion.getEndTime() == null) - || (diversion.getStartTime().before(new Date(Core.getInstance().getSystemTime())) - && diversion.getEndTime().after(new Date(Core.getInstance().getSystemTime())))) { - Double minDistanceToSegment = null; - for (VectorWithHeading vector : diversion.getVectors()) { - Double distanceToSegment = vector.distance(avlReport.getLocation()); + /* + * Check if diversion is currently in place. Null start and end time means in + * place all the time. + */ + if ((diversion.getStartTime() == null && diversion.getEndTime() == null) || (diversion + .getStartTime().before(new Date(Core.getInstance().getSystemTime())) + && diversion.getEndTime().after(new Date(Core.getInstance().getSystemTime())))) { + Double minDistanceToSegment = null; + for (VectorWithHeading vector : diversion.getVectors()) { + Double distanceToSegment = vector.distance(avlReport.getLocation()); - if (distanceToSegment < minDistanceToSegment || minDistanceToSegment < 0) { - minDistanceToSegment = distanceToSegment; + if (minDistanceToSegment == null || distanceToSegment < minDistanceToSegment) { + minDistanceToSegment = distanceToSegment; + } } - } - // Check if within acceptable range of diversion to match to it. - if (minDistanceToSegment < CoreConfig.getMaxDistanceFromSegment()) { - DiversionMatch diversionMatch = new DiversionMatch(minDistanceToSegment, null, - avlReport.getTime(), vehicleState.getBlock(), - vehicleState.getTrip().getIndexInBlock(), diversion.getShapeId(), - diversion.getTripId(), diversion.getRouteId()); + // Check if within acceptable range of diversion to match to it. + if (minDistanceToSegment < CoreConfig.getMaxDistanceFromSegment()) { + DiversionMatch diversionMatch = new DiversionMatch(minDistanceToSegment, null, + avlReport.getTime(), vehicleState.getBlock(), + vehicleState.getTrip().getIndexInBlock(), diversion.getShapeId(), + diversion.getTripId(), diversion.getRouteId()); - diversionMatches.add(diversionMatch); - } + diversionMatches.add(diversionMatch); + } + } } } } } - return diversionMatches; } } From 51adec8a5a398f2c642724eacced232d854c1d37 Mon Sep 17 00:00:00 2001 From: scrudden Date: Tue, 14 Apr 2020 20:47:09 +0100 Subject: [PATCH 13/17] Refactor diversion model to include stoppaths, as we want to be able to handle stops on diversions. --- .../org/transitclock/core/DiversionMatch.java | 38 ++++++- .../transitclock/core/DiversionMatcher.java | 43 ++++++-- .../org/transitclock/core/RouteMatch.java | 6 +- .../org/transitclock/core/SpatialMatch.java | 9 +- .../core/diversion/model/Diversion.java | 95 +++++++---------- .../diversion/model/DiversionStopPath.java | 100 ++++++++++++++++++ .../transitclock/db/structs/Diversion.java | 23 ++-- .../GtfsRtVehiclePositionsReaderBase.java | 11 +- .../transitclock/ipc/data/IpcDiversion.java | 71 +++++-------- .../ipc/data/IpcDiversionStopPath.java | 77 ++++++++++++++ .../transitclock/ipc/data/IpcLocation.java | 37 +++++++ .../ipc/interfaces/DiversionsInterface.java | 3 + .../ipc/servers/DiversionsServer.java | 45 ++++---- .../transitclock/api/data/ApiDiversion.java | 37 +++---- .../api/data/ApiDiversionStopPath.java | 79 ++++++++++++++ .../transitclock/api/data/ApiLocation.java | 4 + .../api/rootResources/DiversionApi.java | 10 ++ 17 files changed, 518 insertions(+), 170 deletions(-) create mode 100644 transitclock/src/main/java/org/transitclock/core/diversion/model/DiversionStopPath.java create mode 100644 transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java create mode 100644 transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java create mode 100644 transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java diff --git a/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java index 26dcbd578..9c1e5eb0f 100644 --- a/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java +++ b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java @@ -6,16 +6,22 @@ public class DiversionMatch extends SpatialMatch { - public DiversionMatch(Double distanceToDiversion, Double distanceAlongDiversion, long avlTime, Block block, int tripIndex, String shapeId, String tripId, String routeId) { + public DiversionMatch(Diversion diversion, Integer stopPathIndex, Integer vectorIndex, Double distanceToDiversion, Double distanceAlongDiversion, long avlTime, Block block, int tripIndex, String shapeId, String tripId, String routeId) { super(avlTime, block, tripIndex); this.routeId=routeId; this.tripId=tripId; this.shapeId=shapeId; this.distanceAlongDiversion=distanceAlongDiversion; - + this.distanceToDiversion=distanceToDiversion; + this.stopPathIndex=stopPathIndex; + this.vectorIndex=vectorIndex; + this.predictedLocation=computeLocation(); + this.diversion=diversion; } - + + Diversion diversion; + Double distanceAlongDiversion; Double distanceToDiversion; @@ -25,6 +31,9 @@ public DiversionMatch(Double distanceToDiversion, Double distanceAlongDiversion, String tripId; String shapeId; + Integer stopPathIndex; + Integer vectorIndex; + public Double getDistanceAlongDiversion() { @@ -82,7 +91,28 @@ public Location getPredictedLocation() { public void setPredictedLocation(Location predictedLocation) { this.predictedLocation = predictedLocation; } + + public Integer getStopPathIndex() { + return stopPathIndex; + } - Diversion diversion; + public void setStopPathIndex(Integer stopPathIndex) { + this.stopPathIndex = stopPathIndex; + } + + + @Override + public String toString() { + return "DiversionMatch [diversion=" + diversion + ", distanceAlongDiversion=" + distanceAlongDiversion + + ", distanceToDiversion=" + distanceToDiversion + ", predictedLocation=" + predictedLocation + + ", routeId=" + routeId + ", tripId=" + tripId + ", shapeId=" + shapeId + ", stopPathIndex=" + + stopPathIndex + ", vectorIndex=" + vectorIndex + "]"; + } + + @Override + protected Location computeLocation() { + /* TODO figure out location */ + return null; + } } diff --git a/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java b/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java index f19ddded7..8884bdf3b 100644 --- a/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java +++ b/transitclock/src/main/java/org/transitclock/core/DiversionMatcher.java @@ -10,7 +10,9 @@ import org.transitclock.core.diversion.cache.DiversionsKey; import org.transitclock.core.diversion.cache.DiversionsList; import org.transitclock.core.diversion.model.Diversion; +import org.transitclock.core.diversion.model.DiversionStopPath; import org.transitclock.db.structs.AvlReport; +import org.transitclock.db.structs.Location; import org.transitclock.db.structs.VectorWithHeading; /** @@ -46,24 +48,48 @@ public static List getDiversionMatches(VehicleState vehicleState .getStartTime().before(new Date(Core.getInstance().getSystemTime())) && diversion.getEndTime().after(new Date(Core.getInstance().getSystemTime())))) { Double minDistanceToSegment = null; - for (VectorWithHeading vector : diversion.getVectors()) { - Double distanceToSegment = vector.distance(avlReport.getLocation()); - - if (minDistanceToSegment == null || distanceToSegment < minDistanceToSegment) { - minDistanceToSegment = distanceToSegment; + Integer minIndex = null; + Integer minVectorIndex = null; + Integer index = 0; + + for(DiversionStopPath diversionStopPath:diversion.getDiversionStopPaths()) + { + Integer vectorIndex=0; + for (VectorWithHeading vector : diversionStopPath.getVectors()) { + Double distanceToSegment = vector.distance(avlReport.getLocation()); + if (minDistanceToSegment == null || distanceToSegment < minDistanceToSegment) { + minDistanceToSegment = distanceToSegment; + minIndex = index; + minVectorIndex = vectorIndex; + } + vectorIndex++; } + index++; } - + + Double distanceAlongDiveresion = 0.0; + ArrayList diversionStopPaths=diversion.getDiversionStopPaths(); + for(int i=0;i getDiversionMatches(VehicleState vehicleState } return diversionMatches; } + } diff --git a/transitclock/src/main/java/org/transitclock/core/RouteMatch.java b/transitclock/src/main/java/org/transitclock/core/RouteMatch.java index 326852db3..fdcbfe1a0 100644 --- a/transitclock/src/main/java/org/transitclock/core/RouteMatch.java +++ b/transitclock/src/main/java/org/transitclock/core/RouteMatch.java @@ -45,7 +45,7 @@ public class RouteMatch extends SpatialMatch { protected final double distanceToSegment; protected final double distanceAlongSegment; protected final VehicleAtStopInfo atStop; - protected final Location predictedLocation; + private static final Logger logger = LoggerFactory.getLogger(RouteMatch.class); @@ -66,14 +66,14 @@ public RouteMatch(long avlTime, Block block, // Determine whether at stop this.atStop = atStop(); - this.predictedLocation = computeLocation(); + } /** * based on the current trip/stop path/sgement compute the predicted * vehicle location. */ - private Location computeLocation() { + protected Location computeLocation() { Trip trip = block.getTrip(tripIndex); if (trip != null) { StopPath stopPath = trip.getStopPath(stopPathIndex); diff --git a/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java b/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java index edd02424c..ca3e0363d 100644 --- a/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java +++ b/transitclock/src/main/java/org/transitclock/core/SpatialMatch.java @@ -1,17 +1,23 @@ package org.transitclock.core; import org.transitclock.db.structs.Block; +import org.transitclock.db.structs.Location; -public class SpatialMatch { +public abstract class SpatialMatch { protected final long avlTime; protected final Block block; protected final int tripIndex; + protected Location predictedLocation; + public Location getPredictedLocation() { + return predictedLocation; + } public SpatialMatch(long avlTime, Block block, int tripIndex) { super(); this.avlTime = avlTime; this.block = block; this.tripIndex = tripIndex; + this.predictedLocation=computeLocation(); } public long getAvlTime() { return avlTime; @@ -22,5 +28,6 @@ public Block getBlock() { public int getTripIndex() { return tripIndex; } + protected abstract Location computeLocation(); } diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java index 9db54b312..2f21af9be 100644 --- a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java +++ b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java @@ -11,6 +11,7 @@ import org.transitclock.db.structs.Route; import org.transitclock.db.structs.Trip; import org.transitclock.db.structs.VectorWithHeading; +import org.transitclock.ipc.data.IpcDiversion; /** * @author Sean Óg Crudden This is the starting point of modeling a detour. @@ -36,25 +37,19 @@ public class Diversion implements Serializable { private int distanceEndAlongSegment; - private List detourPath = new ArrayList(); - - private List stopLocations = new ArrayList(); + private ArrayList diversionStopPaths = new ArrayList(); private Date startTime; private Date endTime; - private List vectors = null; - - public Diversion() { super(); // TODO Auto-generated constructor stub } public Diversion(String routeId, String tripId, String shapeId, int startStopSeq, int distanceStartAlongSegment, - int returnStopSeq, int distanceEndAlongSegment, List detourPath, List stopLocations, - Date startTime, Date endTime) { + int returnStopSeq, int distanceEndAlongSegment, ArrayList diversionStopPaths,Date startTime, Date endTime) { super(); this.routeId = routeId; this.tripId = tripId; @@ -62,28 +57,38 @@ public Diversion(String routeId, String tripId, String shapeId, int startStopSeq this.startStopSeq = startStopSeq; this.distanceStartAlongSegment = distanceStartAlongSegment; this.returnStopSeq = returnStopSeq; - this.distanceEndAlongSegment = distanceEndAlongSegment; - this.detourPath = detourPath; - this.stopLocations = stopLocations; + this.distanceEndAlongSegment = distanceEndAlongSegment; + this.diversionStopPaths = diversionStopPaths; this.startTime = startTime; this.endTime = endTime; - initVectors(); } - private void initVectors() - { - vectors = new ArrayList(detourPath.size() - 1); - for (int segmentIndex = 0; segmentIndex < detourPath.size() - 1; ++segmentIndex) { - VectorWithHeading v = new VectorWithHeading(nullSafeLocation(detourPath.get(segmentIndex)), - nullSafeLocation(detourPath.get(segmentIndex + 1))); - vectors.add(v); - } + + public Diversion(IpcDiversion diversion) { + // TODO Auto-generated constructor stub + this.routeId = diversion.getRouteId(); + this.tripId = diversion.getTripId(); + this.shapeId = diversion.getShapeId(); + this.startStopSeq = diversion.getStartStopSeq(); + this.returnStopSeq = diversion.getReturnStopSeq(); + this.distanceStartAlongSegment = diversion.getDistanceStartAlongSegment(); + this.distanceEndAlongSegment = diversion.getDistanceEndAlongSegment(); + this.startTime = diversion.getStartTime(); + this.endTime = diversion.getEndTime(); + copyStopPaths(diversion); + + } + + void copyStopPaths(IpcDiversion diversion) { + } - private Location nullSafeLocation(Location location) { - if (location == null) { - location = new Location(0.0, 0.0); - } - return location; + + public ArrayList getDiversionStopPaths() { + return diversionStopPaths; + } + + public void setDiversionStopPaths(ArrayList diversionStopPaths) { + this.diversionStopPaths = diversionStopPaths; } public Date getStartTime() { @@ -150,22 +155,6 @@ public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { this.distanceEndAlongSegment = distanceEndAlongSegment; } - public List getDetourPath() { - return detourPath; - } - - public void setDetourPath(List detourPath) { - this.detourPath = detourPath; - } - - public List getStopLocations() { - return stopLocations; - } - - public void setStopLocations(List stopLocations) { - this.stopLocations = stopLocations; - } - public String getShapeId() { return shapeId; } @@ -173,18 +162,19 @@ public String getShapeId() { public void setShapeId(String shapeId) { this.shapeId = shapeId; } - - public List getVectors() { - if(vectors==null) - initVectors(); - return vectors; + + @Override + public String toString() { + return "Diversion [routeId=" + routeId + ", tripId=" + tripId + ", shapeId=" + shapeId + ", startStopSeq=" + + startStopSeq + ", distanceStartAlongSegment=" + distanceStartAlongSegment + ", returnStopSeq=" + + returnStopSeq + ", distanceEndAlongSegment=" + distanceEndAlongSegment + ", diversionStopPaths=" + + diversionStopPaths + ", startTime=" + startTime + ", endTime=" + endTime + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((detourPath == null) ? 0 : detourPath.hashCode()); result = prime * result + distanceEndAlongSegment; result = prime * result + distanceStartAlongSegment; result = prime * result + ((endTime == null) ? 0 : endTime.hashCode()); @@ -193,7 +183,6 @@ public int hashCode() { result = prime * result + ((shapeId == null) ? 0 : shapeId.hashCode()); result = prime * result + startStopSeq; result = prime * result + ((startTime == null) ? 0 : startTime.hashCode()); - result = prime * result + ((stopLocations == null) ? 0 : stopLocations.hashCode()); result = prime * result + ((tripId == null) ? 0 : tripId.hashCode()); return result; } @@ -207,11 +196,6 @@ public boolean equals(Object obj) { if (getClass() != obj.getClass()) return false; Diversion other = (Diversion) obj; - if (detourPath == null) { - if (other.detourPath != null) - return false; - } else if (!detourPath.equals(other.detourPath)) - return false; if (distanceEndAlongSegment != other.distanceEndAlongSegment) return false; if (distanceStartAlongSegment != other.distanceStartAlongSegment) @@ -240,11 +224,6 @@ public boolean equals(Object obj) { return false; } else if (!startTime.equals(other.startTime)) return false; - if (stopLocations == null) { - if (other.stopLocations != null) - return false; - } else if (!stopLocations.equals(other.stopLocations)) - return false; if (tripId == null) { if (other.tripId != null) return false; diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/DiversionStopPath.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/DiversionStopPath.java new file mode 100644 index 000000000..da55ef4b4 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/core/diversion/model/DiversionStopPath.java @@ -0,0 +1,100 @@ +package org.transitclock.core.diversion.model; + +import java.io.Serializable; +import java.util.ArrayList; + +import org.transitclock.db.structs.Location; +import org.transitclock.db.structs.VectorWithHeading; + +public class DiversionStopPath implements Serializable { + /** + * + */ + private static final long serialVersionUID = 1598813782991216200L; + private String stopId; + private String stopName; + private Integer stopSequence; + private Location stopLocation; + private String directionId; + private ArrayList path = new ArrayList(); + + private ArrayList vectors = null; + + public DiversionStopPath() { + super(); + // TODO Auto-generated constructor stub + } + public DiversionStopPath(String stopId, String stopName, Integer stopSequence, Location stopLocation, + String directionId, ArrayList path) { + super(); + this.stopId = stopId; + this.stopName = stopName; + this.stopSequence = stopSequence; + this.stopLocation = stopLocation; + this.directionId = directionId; + this.path = path; + } + public String getDirectionId() { + return directionId; + } + public void setDirectionId(String directionId) { + this.directionId = directionId; + } + public String getStopId() { + return stopId; + } + public void setStopId(String stopId) { + this.stopId = stopId; + } + public String getStopName() { + return stopName; + } + public void setStopName(String stopName) { + this.stopName = stopName; + } + public Integer getStopSequence() { + return stopSequence; + } + public void setStopSequence(Integer stopSequence) { + this.stopSequence = stopSequence; + } + public Location getStopLocation() { + return stopLocation; + } + public void setStopLocation(Location stopLocation) { + this.stopLocation = stopLocation; + } + public ArrayList getPath() { + return path; + } + public void setPath(ArrayList path) { + this.path = path; + } + public ArrayList getVectors() { + if(vectors==null) + initVectors(); + return vectors; + } + + private void initVectors() + { + vectors = new ArrayList(path.size() - 1); + for (int segmentIndex = 0; segmentIndex < path.size() - 1; ++segmentIndex) { + VectorWithHeading v = new VectorWithHeading(nullSafeLocation(path.get(segmentIndex)), + nullSafeLocation(path.get(segmentIndex + 1))); + vectors.add(v); + } + } + private Location nullSafeLocation(Location location) { + if (location == null) { + location = new Location(0.0, 0.0); + } + return location; + } + @Override + public String toString() { + return "DiversionStopPath [stopId=" + stopId + ", stopName=" + stopName + ", stopSequence=" + stopSequence + + ", stopLocation=" + stopLocation + ", directionId=" + directionId + "]"; + } + +} diff --git a/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java b/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java index 56cc29ff2..47a3860c2 100644 --- a/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java +++ b/transitclock/src/main/java/org/transitclock/db/structs/Diversion.java @@ -49,17 +49,21 @@ public class Diversion implements Serializable, Lifecycle { @Column private int returnStopSeq; - + @Column private int distanceEndAlongSegment; - @ElementCollection + @OrderColumn - private List detourPath; + private ArrayList detourPath; + - @ElementCollection @OrderColumn - private List stopLocations; + private ArrayList stopLocations; + + + @Column + private ArrayList expectedTravelTimes; @Transient private List vectors = null; @@ -68,8 +72,8 @@ public Diversion() { super(); } public Diversion(String routeId, String tripId, String shapeId, Date startTime, Date endTime, int startStopSeq, - int distanceStartAlongSegment, int returnStopSeq, int distanceEndAlongSegment, List detourPath, - List stopLocations) { + int distanceStartAlongSegment, int returnStopSeq, int distanceEndAlongSegment, ArrayList detourPath, + ArrayList stopLocations, ArrayListexpectedTravelTimes) { super(); this.routeId = routeId; this.tripId = tripId; @@ -82,6 +86,7 @@ public Diversion(String routeId, String tripId, String shapeId, Date startTime, this.distanceEndAlongSegment = distanceEndAlongSegment; this.detourPath = detourPath; this.stopLocations = stopLocations; + this.expectedTravelTimes = expectedTravelTimes; vectors = new ArrayList(detourPath.size()-1); for (int segmentIndex=0; segmentIndex getDetourPath() { return detourPath; } - public void setDetourPath(List detourPath) { + public void setDetourPath(ArrayList detourPath) { this.detourPath = detourPath; } @@ -192,7 +197,7 @@ public List getStopLocations() { return stopLocations; } - public void setStopLocations(List stopLocations) { + public void setStopLocations(ArrayList stopLocations) { this.stopLocations = stopLocations; } diff --git a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java index 6836fe970..4370e0e93 100644 --- a/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java +++ b/transitclock/src/main/java/org/transitclock/feed/gtfsRt/GtfsRtVehiclePositionsReaderBase.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.transitclock.core.diversion.cache.DiversionsCacheFactory; import org.transitclock.core.diversion.model.Diversion; +import org.transitclock.core.diversion.model.DiversionStopPath; import org.transitclock.db.structs.AvlReport; import org.transitclock.db.structs.AvlReport.AssignmentType; import org.transitclock.db.structs.Location; @@ -163,13 +164,15 @@ private void processMessage(FeedMessage message) { detour.setShapeId(tripProperties.getShapeId()); detour.setTripId(tripUpdate.getTrip().getTripId()); detour.setRouteId(tripUpdate.getTrip().getRouteId()); - + + DiversionStopPath diversionStopPath=new DiversionStopPath(); for(ShapePoint shapePoint : shape.getShapePointList()) { Location location=new Location(shapePoint.getShapePtLat(), shapePoint.getShapePtLon()); - detour.getDetourPath().add(location); - } - + diversionStopPath.getPath().add(location); + } + detour.getDiversionStopPaths().add(diversionStopPath); + if(DiversionsCacheFactory.getInstance()!=null) DiversionsCacheFactory.getInstance().putDiversion(detour); diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java index aa6be9193..e0ed3de04 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java @@ -1,39 +1,39 @@ package org.transitclock.ipc.data; import java.io.Serializable; +import java.util.ArrayList; import java.util.Date; import java.util.List; import org.transitclock.core.diversion.model.Diversion; +import org.transitclock.core.diversion.model.DiversionStopPath; import org.transitclock.db.structs.Location; -public class IpcDiversion implements Serializable{ +public class IpcDiversion implements Serializable { /** * */ private static final long serialVersionUID = 2548744289428304091L; private String routeId; - + private String tripId; - + private String shapeId; - + private int startStopSeq; - + private int distanceStartAlongSegment; - + private int returnStopSeq; - + private int distanceEndAlongSegment; - - private List detourPath; - - private List stopLocations; - + + private ArrayList diversionStopPaths = new ArrayList(); + private Date startTime; - - private Date endTime; + + private Date endTime; public IpcDiversion() { super(); @@ -41,8 +41,7 @@ public IpcDiversion() { } public IpcDiversion(String routeId, String tripId, String shapeId, int startStopSeq, int distanceStartAlongSegment, - int returnStopSeq, int distanceEndAlongSegment, List detourPath, List stopLocations, - Date startTime, Date endTime) { + int returnStopSeq, int distanceEndAlongSegment, Date startTime, Date endTime) { super(); this.routeId = routeId; this.tripId = tripId; @@ -51,8 +50,7 @@ public IpcDiversion(String routeId, String tripId, String shapeId, int startStop this.distanceStartAlongSegment = distanceStartAlongSegment; this.returnStopSeq = returnStopSeq; this.distanceEndAlongSegment = distanceEndAlongSegment; - this.detourPath = detourPath; - this.stopLocations = stopLocations; + this.startTime = startTime; this.endTime = endTime; } @@ -61,18 +59,23 @@ public IpcDiversion(Diversion diversion) { this.routeId = diversion.getRouteId(); this.tripId = diversion.getTripId(); - this.shapeId = diversion.getShapeId(); + this.shapeId = diversion.getShapeId(); this.startStopSeq = diversion.getStartStopSeq(); - + this.distanceStartAlongSegment = diversion.getDistanceStartAlongSegment(); this.returnStopSeq = diversion.getReturnStopSeq(); this.distanceEndAlongSegment = diversion.getDistanceEndAlongSegment(); - this.detourPath = diversion.getDetourPath(); - this.stopLocations = diversion.getStopLocations(); + this.startTime = diversion.getStartTime(); this.endTime = diversion.getEndTime(); + + for(DiversionStopPath stopPath:diversion.getDiversionStopPaths()) + { + this.diversionStopPaths.add(new IpcDiversionStopPath(stopPath)); + } } + public String getRouteId() { return routeId; } @@ -129,20 +132,12 @@ public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { this.distanceEndAlongSegment = distanceEndAlongSegment; } - public List getDetourPath() { - return detourPath; + public ArrayList getDiversionStopPaths() { + return diversionStopPaths; } - public void setDetourPath(List detourPath) { - this.detourPath = detourPath; - } - - public List getStopLocations() { - return stopLocations; - } - - public void setStopLocations(List stopLocations) { - this.stopLocations = stopLocations; + public void setDiversionStopPaths(ArrayList diversionStopPaths) { + this.diversionStopPaths = diversionStopPaths; } public Date getStartTime() { @@ -161,12 +156,4 @@ public void setEndTime(Date endTime) { this.endTime = endTime; } - @Override - public String toString() { - return "IpcDiversion [routeId=" + routeId + ", tripId=" + tripId + ", shapeId=" + shapeId + ", startStopSeq=" - + startStopSeq + ", distanceStartAlongSegment=" + distanceStartAlongSegment + ", returnStopSeq=" - + returnStopSeq + ", distanceEndAlongSegment=" + distanceEndAlongSegment + ", detourPath=" + detourPath - + ", stopLocations=" + stopLocations + ", startTime=" + startTime + ", endTime=" + endTime + "]"; - } - } diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java new file mode 100644 index 000000000..0251bf5e5 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java @@ -0,0 +1,77 @@ +package org.transitclock.ipc.data; + +import java.util.ArrayList; +import org.transitclock.core.diversion.model.DiversionStopPath; +import org.transitclock.db.structs.Location; + +public class IpcDiversionStopPath { + private String stopId; + private String stopName; + private Integer stopSequence; + private Location stopLocation; + private String directionId; + private ArrayList path = new ArrayList(); + + public IpcDiversionStopPath(String stopId, String stopName, Integer stopSequence, Location stopLocation, + String directionId, ArrayList path) { + super(); + this.stopId = stopId; + this.stopName = stopName; + this.stopSequence = stopSequence; + this.stopLocation = stopLocation; + this.directionId = directionId; + this.path = path; + } + public IpcDiversionStopPath(DiversionStopPath diversionStopPath) + { + this.stopId=diversionStopPath.getStopId(); + this.stopName=diversionStopPath.getStopName(); + this.stopSequence=diversionStopPath.getStopSequence(); + this.stopLocation=diversionStopPath.getStopLocation(); + this.directionId=diversionStopPath.getDirectionId(); + copyPath(diversionStopPath); + } + private void copyPath(DiversionStopPath diversionStopPath) + { + for(Location point:diversionStopPath.getPath()) { + path.add(new IpcLocation(point)); + } + } + public String getStopId() { + return stopId; + } + public void setStopId(String stopId) { + this.stopId = stopId; + } + public String getStopName() { + return stopName; + } + public void setStopName(String stopName) { + this.stopName = stopName; + } + public Integer getStopSequence() { + return stopSequence; + } + public void setStopSequence(Integer stopSequence) { + this.stopSequence = stopSequence; + } + public Location getStopLocation() { + return stopLocation; + } + public void setStopLocation(Location stopLocation) { + this.stopLocation = stopLocation; + } + public String getDirectionId() { + return directionId; + } + public void setDirectionId(String directionId) { + this.directionId = directionId; + } + public ArrayList getPath() { + return path; + } + public void setPath(ArrayList path) { + this.path = path; + } + +} diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java new file mode 100644 index 000000000..7f3d89458 --- /dev/null +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java @@ -0,0 +1,37 @@ +package org.transitclock.ipc.data; + +import java.io.Serializable; + +import org.transitclock.db.structs.Location; + +public class IpcLocation implements Serializable{ + + private Double lat; + + + private Double lon; + + + public Double getLat() { + return lat; + } + + + public Double getLon() { + return lon; + } + + + public IpcLocation(Double lat, Double lon) { + super(); + this.lat = lat; + this.lon = lon; + } + + public IpcLocation(Location location) + { + this.lat=location.getLat(); + this.lon=location.getLon(); + } + +} diff --git a/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java b/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java index 27311a83d..4ab56a5bd 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java +++ b/transitclock/src/main/java/org/transitclock/ipc/interfaces/DiversionsInterface.java @@ -3,9 +3,12 @@ import java.rmi.Remote; import java.rmi.RemoteException; +import org.transitclock.ipc.data.IpcDiversion; import org.transitclock.ipc.data.IpcDiversions; public interface DiversionsInterface extends Remote { IpcDiversions getDiversionsForTrip(String tripId) throws RemoteException; IpcDiversions getDiversionsForRoute(String routeId) throws RemoteException; + void addDiversion(IpcDiversion diversion) throws RemoteException; + void removeDiversion(IpcDiversion diversion) throws RemoteException; } diff --git a/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java index 1bb2b4459..2543bbaa5 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java +++ b/transitclock/src/main/java/org/transitclock/ipc/servers/DiversionsServer.java @@ -20,13 +20,13 @@ public class DiversionsServer extends AbstractServer implements DiversionsInterface { private static DiversionsServer singleton; - + private static final Logger logger = LoggerFactory.getLogger(DiversionsServer.class); - + protected DiversionsServer(String agencyId) { super(agencyId, DiversionsInterface.class.getSimpleName()); } - + public static DiversionsServer start(String agencyId) { if (singleton == null) { singleton = new DiversionsServer(agencyId); @@ -37,7 +37,7 @@ public static DiversionsServer start(String agencyId) { + "agencyId={} but the singleton was created for agencyId={}", agencyId, singleton.getAgencyId()); return null; - } + } return singleton; } @@ -45,23 +45,20 @@ public static DiversionsServer start(String agencyId) { public IpcDiversions getDiversionsForTrip(String tripId) throws RemoteException { Core core = Core.getInstance(); Trip trip = core.getDbConfig().getTrip(tripId); - - if(trip!=null) - { - DiversionsKey key=new DiversionsKey(tripId, trip.getRouteId()); - + + if (trip != null) { + DiversionsKey key = new DiversionsKey(tripId, trip.getRouteId()); + DiversionsList diversions = DiversionsCacheFactory.getInstance().getDiversions(key); - - List ipcDiversions=new ArrayList(); - - for( Diversion diversion:diversions.getDiversions()) - { + + List ipcDiversions = new ArrayList(); + + for (Diversion diversion : diversions.getDiversions()) { ipcDiversions.add(new IpcDiversion(diversion)); } - + return new IpcDiversions(ipcDiversions); - }else - { + } else { return null; } } @@ -69,8 +66,20 @@ public IpcDiversions getDiversionsForTrip(String tripId) throws RemoteException @Override public IpcDiversions getDiversionsForRoute(String routeId) throws RemoteException { // TODO Auto-generated method stub - DiversionsCacheFactory.getInstance(); return null; } + @Override + public void addDiversion(IpcDiversion diversion) throws RemoteException { + + DiversionsCacheFactory.getInstance().putDiversion(new Diversion(diversion)); + + } + + @Override + public void removeDiversion(IpcDiversion diversion) throws RemoteException { + // TODO Auto-generated method stub + + } + } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java index f6b4e1e4b..c653f9e9d 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java @@ -1,5 +1,6 @@ package org.transitclock.api.data; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -8,6 +9,8 @@ import org.transitclock.db.structs.Location; import org.transitclock.ipc.data.IpcDiversion; +import org.transitclock.ipc.data.IpcDiversionStopPath; +import org.transitclock.ipc.data.IpcLocation; @XmlRootElement(name = "diversion") public class ApiDiversion { @XmlAttribute @@ -24,10 +27,7 @@ public class ApiDiversion { private int returnStopSeq; @XmlAttribute private int distanceEndAlongSegment; - @XmlAttribute - private List detourPath; - @XmlAttribute - private List stopLocations; + private ArrayList diversionStopPaths=new ArrayList(); @XmlAttribute private Date startTime; @XmlAttribute @@ -49,13 +49,20 @@ public ApiDiversion(IpcDiversion diversion) this.shapeId=diversion.getShapeId(); this.tripId=diversion.getTripId(); this.distanceStartAlongSegment=diversion.getDistanceStartAlongSegment(); - this.distanceStartAlongSegment=diversion.getDistanceStartAlongSegment(); - this.detourPath=diversion.getDetourPath(); - this.stopLocations=diversion.getStopLocations(); + this.distanceStartAlongSegment=diversion.getDistanceStartAlongSegment(); + this.startTime=diversion.getStartTime(); this.endTime=diversion.getEndTime(); } + public ArrayList getDiversionStopPaths() { + return diversionStopPaths; + } + + public void setDiversionStopPaths(ArrayList diversionStopPaths) { + this.diversionStopPaths = diversionStopPaths; + } + public String getRouteId() { return routeId; } @@ -112,22 +119,6 @@ public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { this.distanceEndAlongSegment = distanceEndAlongSegment; } - public List getDetourPath() { - return detourPath; - } - - public void setDetourPath(List detourPath) { - this.detourPath = detourPath; - } - - public List getStopLocations() { - return stopLocations; - } - - public void setStopLocations(List stopLocations) { - this.stopLocations = stopLocations; - } - public Date getStartTime() { return startTime; } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java new file mode 100644 index 000000000..87fcc8abc --- /dev/null +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java @@ -0,0 +1,79 @@ +package org.transitclock.api.data; + +import java.util.ArrayList; + +import org.transitclock.ipc.data.IpcDiversionStopPath; +import org.transitclock.ipc.data.IpcLocation; + +public class ApiDiversionStopPath { + private String stopId; + private String stopName; + private Integer stopSequence; + private ApiLocation stopLocation; + private String directionId; + private ArrayList path = new ArrayList(); + + public ApiDiversionStopPath() { + super(); + // TODO Auto-generated constructor stub + } + + public ApiDiversionStopPath(String stopId, String stopName, Integer stopSequence, ApiLocation stopLocation, + String directionId, ArrayList path) { + super(); + this.stopId = stopId; + this.stopName = stopName; + this.stopSequence = stopSequence; + this.stopLocation = stopLocation; + this.directionId = directionId; + this.path = path; + } + public ApiDiversionStopPath(IpcDiversionStopPath diversionStopPath) + { + this.stopId=diversionStopPath.getStopId(); + this.stopName=diversionStopPath.getStopName(); + this.stopSequence=diversionStopPath.getStopSequence(); + this.stopLocation=new ApiLocation(diversionStopPath.getStopLocation()); + this.directionId=diversionStopPath.getDirectionId(); + for(IpcLocation point:diversionStopPath.getPath()) { + path.add(new ApiLocation(point)); + } + } + public String getStopId() { + return stopId; + } + public void setStopId(String stopId) { + this.stopId = stopId; + } + public String getStopName() { + return stopName; + } + public void setStopName(String stopName) { + this.stopName = stopName; + } + public Integer getStopSequence() { + return stopSequence; + } + public void setStopSequence(Integer stopSequence) { + this.stopSequence = stopSequence; + } + public ApiLocation getStopLocation() { + return stopLocation; + } + public void setStopLocation(ApiLocation stopLocation) { + this.stopLocation = stopLocation; + } + public String getDirectionId() { + return directionId; + } + public void setDirectionId(String directionId) { + this.directionId = directionId; + } + public ArrayList getPath() { + return path; + } + public void setPath(ArrayList path) { + this.path = path; + } + +} diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiLocation.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiLocation.java index 4e5fc83cf..f2140af1a 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiLocation.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiLocation.java @@ -18,6 +18,7 @@ package org.transitclock.api.data; import org.transitclock.db.structs.Location; +import org.transitclock.ipc.data.IpcLocation; /** * A simple latitude/longitude. @@ -48,4 +49,7 @@ public ApiLocation(double lat, double lon) { public ApiLocation(Location loc) { super(loc.getLat(), loc.getLon()); } + public ApiLocation(IpcLocation loc) { + super(loc.getLat(), loc.getLon()); + } } diff --git a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java index 7f8c088dc..b903817c3 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java +++ b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java @@ -3,7 +3,9 @@ import java.rmi.RemoteException; import javax.ws.rs.BeanParam; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; @@ -17,6 +19,7 @@ import org.transitclock.api.data.ApiDiversions; import org.transitclock.api.utils.StandardParameters; import org.transitclock.api.utils.WebUtils; +import org.transitclock.core.diversion.model.Diversion; import org.transitclock.ipc.data.IpcDiversions; import org.transitclock.ipc.interfaces.DiversionsInterface; @@ -83,4 +86,11 @@ public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameter throw WebUtils.badRequestException(e); } } + @POST + @Consumes(MediaType.APPLICATION_JSON) + public Response addDiversion(ApiDiversion diversion) + { + String result = "Diversion added : " + diversion; + return Response.status(201).entity(result).build(); + } } From 883b8ab34aad15d73eeafb66a319af93a3b12cee Mon Sep 17 00:00:00 2001 From: scrudden Date: Wed, 15 Apr 2020 15:51:44 +0100 Subject: [PATCH 14/17] Do not generate a predicton after the start of a diversion. --- .../core/PredictionGeneratorDefaultImpl.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java b/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java index b6dd425ad..57b9a5d1b 100755 --- a/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java +++ b/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java @@ -31,6 +31,10 @@ import org.transitclock.core.dataCache.HoldingTimeCache; import org.transitclock.core.dataCache.StopPathPredictionCache; import org.transitclock.core.dataCache.VehicleStateManager; + +import org.transitclock.core.diversion.cache.DiversionsCacheFactory; +import org.transitclock.core.diversion.cache.DiversionsKey; +import org.transitclock.core.diversion.cache.DiversionsList; import org.transitclock.core.holdingmethod.HoldingTimeGeneratorFactory; import org.transitclock.core.predictiongenerator.PredictionComponentElementsGenerator; import org.transitclock.core.predictiongenerator.bias.BiasAdjuster; @@ -332,7 +336,16 @@ protected IpcPrediction generatePredictionForStop(AvlReport avlReport, } } } + + private boolean isDiverted(Indices indices, DiversionsList diversions) { + for( org.transitclock.core.diversion.model.Diversion diversion:diversions.getDiversions()) + { + if(indices.getStopPath().getGtfsStopSeq()>=diversion.getStartStopSeq() && indices.getStopPath().getGtfsStopSeq()<=diversion.getReturnStopSeq()) + return true; + } + return false; + } /** * Generates the predictions for the vehicle. * @@ -401,9 +414,16 @@ public List generate(VehicleState vehicleState) { // Continue through block until end of block or limit on how far // into the future should generate predictions reached. + + // Stop generating predictions if we reach a diversion. + DiversionsList diversions=null; + if(DiversionsCacheFactory.getInstance()!=null) + diversions = DiversionsCacheFactory.getInstance().getDiversions(new DiversionsKey(match.getTrip().getId(), match.getRoute().getId())); + while (schedBasedPreds || predictionTime < - avlTime + maxPredictionsTimeSecs.getValue() * Time.MS_PER_SEC) { + avlTime + maxPredictionsTimeSecs.getValue() * Time.MS_PER_SEC + || !isDiverted(indices, diversions)) { // Keep track of whether prediction is affected by layover // scheduled departure time since those predictions might not // be a accurate. Once a layover encountered then all subsequent @@ -565,6 +585,7 @@ public List generate(VehicleState vehicleState) { } + public long getTravelTimeForPath(Indices indices, AvlReport avlReport, VehicleState vehicleState) { //logger.debug("Using transiTime default algorithm for travel time prediction : " + indices + " Value: "+indices.getTravelTimeForPath()); From 9c247193a8ff62282cb25c9300ea7b27cf0678de Mon Sep 17 00:00:00 2001 From: scrudden Date: Wed, 29 Apr 2020 21:15:43 +0100 Subject: [PATCH 15/17] Can now read refactored Diversions model from API by tripId. --- .../org/transitclock/core/DiversionMatch.java | 54 +++++---- .../core/PredictionGeneratorDefaultImpl.java | 3 +- .../org/transitclock/core/TravelTimes.java | 20 ++++ .../transitclock/ipc/data/IpcDiversion.java | 8 ++ .../ipc/data/IpcDiversionStopPath.java | 12 +- .../transitclock/ipc/data/IpcLocation.java | 6 + transitclockApi/pom.xml | 75 +++++-------- .../org/transitclock/api/ApiApplication.java | 2 + .../transitclock/api/data/ApiDiversion.java | 105 ++++-------------- .../api/data/ApiDiversionStopPath.java | 63 ++++------- .../transitclock/api/data/ApiDiversions.java | 24 ++-- .../api/data/ApiTransientLocation.java | 9 +- .../customwriter/ApiDiversionsBodyWriter.java | 54 +++++++++ .../api/rootResources/DiversionApi.java | 11 +- 14 files changed, 220 insertions(+), 226 deletions(-) create mode 100644 transitclockApi/src/main/java/org/transitclock/api/data/customwriter/ApiDiversionsBodyWriter.java diff --git a/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java index 9c1e5eb0f..34fec5dc3 100644 --- a/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java +++ b/transitclock/src/main/java/org/transitclock/core/DiversionMatch.java @@ -5,36 +5,35 @@ import org.transitclock.db.structs.Location; public class DiversionMatch extends SpatialMatch { - - public DiversionMatch(Diversion diversion, Integer stopPathIndex, Integer vectorIndex, Double distanceToDiversion, Double distanceAlongDiversion, long avlTime, Block block, int tripIndex, String shapeId, String tripId, String routeId) { - super(avlTime, block, tripIndex); - - this.routeId=routeId; - this.tripId=tripId; - this.shapeId=shapeId; - this.distanceAlongDiversion=distanceAlongDiversion; - this.distanceToDiversion=distanceToDiversion; - this.stopPathIndex=stopPathIndex; - this.vectorIndex=vectorIndex; - this.predictedLocation=computeLocation(); - this.diversion=diversion; - } - Diversion diversion; - + Double distanceAlongDiversion; Double distanceToDiversion; - + Location predictedLocation; - + String routeId; - String tripId; - String shapeId; - + String tripId; + String shapeId; + Integer stopPathIndex; Integer vectorIndex; - - + + public DiversionMatch(Diversion diversion, Integer stopPathIndex, Integer vectorIndex, Double distanceToDiversion, + Double distanceAlongDiversion, long avlTime, Block block, int tripIndex, String shapeId, String tripId, + String routeId) { + super(avlTime, block, tripIndex); + + this.routeId = routeId; + this.tripId = tripId; + this.shapeId = shapeId; + this.distanceAlongDiversion = distanceAlongDiversion; + this.distanceToDiversion = distanceToDiversion; + this.stopPathIndex = stopPathIndex; + this.vectorIndex = vectorIndex; + this.predictedLocation = computeLocation(); + this.diversion = diversion; + } public Double getDistanceAlongDiversion() { return distanceAlongDiversion; @@ -59,7 +58,7 @@ public Diversion getDiversion() { public void setDiversion(Diversion diversion) { this.diversion = diversion; } - + public String getRouteId() { return routeId; } @@ -91,7 +90,7 @@ public Location getPredictedLocation() { public void setPredictedLocation(Location predictedLocation) { this.predictedLocation = predictedLocation; } - + public Integer getStopPathIndex() { return stopPathIndex; } @@ -99,7 +98,6 @@ public Integer getStopPathIndex() { public void setStopPathIndex(Integer stopPathIndex) { this.stopPathIndex = stopPathIndex; } - @Override public String toString() { @@ -112,7 +110,7 @@ public String toString() { @Override protected Location computeLocation() { /* TODO figure out location */ - return null; + return null; } - + } diff --git a/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java b/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java index 57b9a5d1b..d51fde4ca 100755 --- a/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java +++ b/transitclock/src/main/java/org/transitclock/core/PredictionGeneratorDefaultImpl.java @@ -338,7 +338,8 @@ protected IpcPrediction generatePredictionForStop(AvlReport avlReport, } private boolean isDiverted(Indices indices, DiversionsList diversions) { - + if(diversions==null) + return false; for( org.transitclock.core.diversion.model.Diversion diversion:diversions.getDiversions()) { if(indices.getStopPath().getGtfsStopSeq()>=diversion.getStartStopSeq() && indices.getStopPath().getGtfsStopSeq()<=diversion.getReturnStopSeq()) diff --git a/transitclock/src/main/java/org/transitclock/core/TravelTimes.java b/transitclock/src/main/java/org/transitclock/core/TravelTimes.java index 3bc6f93d9..8b54848e4 100644 --- a/transitclock/src/main/java/org/transitclock/core/TravelTimes.java +++ b/transitclock/src/main/java/org/transitclock/core/TravelTimes.java @@ -538,4 +538,24 @@ public int expectedTravelTimeBetweenMatches(String vehicleId, return expectedTravelTimeBetweenMatches(vehicleId, timeOfDaySecs, match1, match2); } + public int expectedTravelTimesBetweenMatches(String vehicleId, Date time, DiversionMatch match1, DiversionMatch match2) + { + + /* TODO Check if on same diversion */ + + + + return 0; + } + + public int expectedTravelTimesBetweenMatches(String vehicleId, Date time, RouteMatch match1, DiversionMatch match2) + { + return 0; + } + + public int expectedTravelTimesBetweenMatches(String vehicleId, Date time, DiversionMatch match1, RouteMatch match2) + { + return 0; + } + } diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java index e0ed3de04..4fa5209ec 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java @@ -156,4 +156,12 @@ public void setEndTime(Date endTime) { this.endTime = endTime; } + @Override + public String toString() { + return "IpcDiversion [routeId=" + routeId + ", tripId=" + tripId + ", shapeId=" + shapeId + ", startStopSeq=" + + startStopSeq + ", distanceStartAlongSegment=" + distanceStartAlongSegment + ", returnStopSeq=" + + returnStopSeq + ", distanceEndAlongSegment=" + distanceEndAlongSegment + ", diversionStopPaths=" + + diversionStopPaths + ", startTime=" + startTime + ", endTime=" + endTime + "]"; + } + } diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java index 0251bf5e5..056274a2a 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversionStopPath.java @@ -1,10 +1,15 @@ package org.transitclock.ipc.data; +import java.io.Serializable; import java.util.ArrayList; import org.transitclock.core.diversion.model.DiversionStopPath; import org.transitclock.db.structs.Location; -public class IpcDiversionStopPath { +public class IpcDiversionStopPath implements Serializable{ + /** + * + */ + private static final long serialVersionUID = -5887640144411684439L; private String stopId; private String stopName; private Integer stopSequence; @@ -73,5 +78,10 @@ public ArrayList getPath() { public void setPath(ArrayList path) { this.path = path; } + @Override + public String toString() { + return "IpcDiversionStopPath [stopId=" + stopId + ", stopName=" + stopName + ", stopSequence=" + stopSequence + + ", stopLocation=" + stopLocation + ", directionId=" + directionId + ", path=" + path + "]"; + } } diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java index 7f3d89458..7436fe77f 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcLocation.java @@ -33,5 +33,11 @@ public IpcLocation(Location location) this.lat=location.getLat(); this.lon=location.getLon(); } + + + @Override + public String toString() { + return "IpcLocation [lat=" + lat + ", lon=" + lon + "]"; + } } diff --git a/transitclockApi/pom.xml b/transitclockApi/pom.xml index 3049c8888..fd90665a9 100755 --- a/transitclockApi/pom.xml +++ b/transitclockApi/pom.xml @@ -1,4 +1,6 @@ - + 4.0.0 TheTransitClock @@ -8,10 +10,10 @@ transitclockApi - UTF-8 - 1.8 - 1.8 - + UTF-8 + 1.8 + 1.8 + @@ -32,21 +34,16 @@ org.glassfish.jersey.media jersey-media-moxy - 2.24.1 - - - org.slf4j - slf4j-api - 1.7.2 - + 2.11 org.glassfish.jersey.containers jersey-container-servlet - 2.24.1 + 2.11 + TheTransitClock transitclockCore @@ -58,46 +55,28 @@ TheTransitClock - transitclockBarefootClient + transitclockBarefootClient TheTransitClock - transitclockTraccarClient - + transitclockTraccarClient + - - com.google.guava - guava - 20.0 - - - org.glassfish.jersey.bundles.repackaged - jersey-guava - 2.6 - - - - - - - - - io.swagger.core.v3 - swagger-jaxrs2 - 2.0.2 - - - - - org.webjars - swagger-ui - 3.17.1 - + + + + + + + + + + io.swagger.core.v3 + swagger-jaxrs2 + 2.0.2 + diff --git a/transitclockApi/src/main/java/org/transitclock/api/ApiApplication.java b/transitclockApi/src/main/java/org/transitclock/api/ApiApplication.java index c4cd37373..26a874c88 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/ApiApplication.java +++ b/transitclockApi/src/main/java/org/transitclock/api/ApiApplication.java @@ -38,5 +38,7 @@ public ApiApplication() { // Register all root-resource classes in package that handle @Path // requests packages("org.transitclock.api.rootResources"); + //packages("org.transitclock.api.data.customwriter"); + } } \ No newline at end of file diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java index c653f9e9d..0c343cc2d 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java @@ -1,18 +1,25 @@ package org.transitclock.api.data; +import java.io.Serializable; import java.util.ArrayList; import java.util.Date; import java.util.List; import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; import org.transitclock.db.structs.Location; import org.transitclock.ipc.data.IpcDiversion; import org.transitclock.ipc.data.IpcDiversionStopPath; import org.transitclock.ipc.data.IpcLocation; -@XmlRootElement(name = "diversion") -public class ApiDiversion { +@XmlRootElement +public class ApiDiversion implements Serializable { + /** + * + */ + private static final long serialVersionUID = 2524022174620441284L; @XmlAttribute private String routeId; @XmlAttribute @@ -26,8 +33,9 @@ public class ApiDiversion { @XmlAttribute private int returnStopSeq; @XmlAttribute - private int distanceEndAlongSegment; - private ArrayList diversionStopPaths=new ArrayList(); + private int distanceEndAlongSegment; + @XmlElement(name="stopPaths") + private List diversionStopPaths; @XmlAttribute private Date startTime; @XmlAttribute @@ -37,7 +45,7 @@ public class ApiDiversion { * Need a no-arg constructor for Jersey. Otherwise get really obtuse * "MessageBodyWriter not found for media type=application/json" exception. */ - public ApiDiversion() { + protected ApiDiversion() { } @@ -52,87 +60,14 @@ public ApiDiversion(IpcDiversion diversion) this.distanceStartAlongSegment=diversion.getDistanceStartAlongSegment(); this.startTime=diversion.getStartTime(); - this.endTime=diversion.getEndTime(); - } - - public ArrayList getDiversionStopPaths() { - return diversionStopPaths; - } - - public void setDiversionStopPaths(ArrayList diversionStopPaths) { - this.diversionStopPaths = diversionStopPaths; - } - - public String getRouteId() { - return routeId; - } - - public void setRouteId(String routeId) { - this.routeId = routeId; - } - - public String getTripId() { - return tripId; - } - - public void setTripId(String tripId) { - this.tripId = tripId; - } - - public String getShapeId() { - return shapeId; - } - - public void setShapeId(String shapeId) { - this.shapeId = shapeId; - } - - public int getStartStopSeq() { - return startStopSeq; - } - - public void setStartStopSeq(int startStopSeq) { - this.startStopSeq = startStopSeq; - } - - public int getDistanceStartAlongSegment() { - return distanceStartAlongSegment; - } - - public void setDistanceStartAlongSegment(int distanceStartAlongSegment) { - this.distanceStartAlongSegment = distanceStartAlongSegment; - } - - public int getReturnStopSeq() { - return returnStopSeq; - } - - public void setReturnStopSeq(int returnStopSeq) { - this.returnStopSeq = returnStopSeq; - } - - public int getDistanceEndAlongSegment() { - return distanceEndAlongSegment; - } - - public void setDistanceEndAlongSegment(int distanceEndAlongSegment) { - this.distanceEndAlongSegment = distanceEndAlongSegment; - } - - public Date getStartTime() { - return startTime; - } - - public void setStartTime(Date startTime) { - this.startTime = startTime; - } - - public Date getEndTime() { - return endTime; + this.endTime=diversion.getEndTime(); + + this.diversionStopPaths=new ArrayList(); + for( IpcDiversionStopPath ipcStopPath:diversion.getDiversionStopPaths()) + { + this.diversionStopPaths.add(new ApiDiversionStopPath(ipcStopPath)); + } } - public void setEndTime(Date endTime) { - this.endTime = endTime; - } } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java index 87fcc8abc..00d17e0f6 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java @@ -1,21 +1,36 @@ package org.transitclock.api.data; +import java.io.Serializable; import java.util.ArrayList; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + import org.transitclock.ipc.data.IpcDiversionStopPath; import org.transitclock.ipc.data.IpcLocation; -public class ApiDiversionStopPath { +@XmlRootElement +public class ApiDiversionStopPath implements Serializable{ + /** + * + */ + private static final long serialVersionUID = 3943658440515490430L; + @XmlAttribute private String stopId; + @XmlAttribute private String stopName; + @XmlAttribute private Integer stopSequence; + @XmlAttribute private ApiLocation stopLocation; + @XmlAttribute private String directionId; + @XmlElement(name = "path") private ArrayList path = new ArrayList(); - public ApiDiversionStopPath() { - super(); - // TODO Auto-generated constructor stub + protected ApiDiversionStopPath() { + } public ApiDiversionStopPath(String stopId, String stopName, Integer stopSequence, ApiLocation stopLocation, @@ -33,47 +48,13 @@ public ApiDiversionStopPath(IpcDiversionStopPath diversionStopPath) this.stopId=diversionStopPath.getStopId(); this.stopName=diversionStopPath.getStopName(); this.stopSequence=diversionStopPath.getStopSequence(); - this.stopLocation=new ApiLocation(diversionStopPath.getStopLocation()); + if(diversionStopPath.getStopLocation()!=null) + this.stopLocation=new ApiLocation(diversionStopPath.getStopLocation()); this.directionId=diversionStopPath.getDirectionId(); for(IpcLocation point:diversionStopPath.getPath()) { path.add(new ApiLocation(point)); } } - public String getStopId() { - return stopId; - } - public void setStopId(String stopId) { - this.stopId = stopId; - } - public String getStopName() { - return stopName; - } - public void setStopName(String stopName) { - this.stopName = stopName; - } - public Integer getStopSequence() { - return stopSequence; - } - public void setStopSequence(Integer stopSequence) { - this.stopSequence = stopSequence; - } - public ApiLocation getStopLocation() { - return stopLocation; - } - public void setStopLocation(ApiLocation stopLocation) { - this.stopLocation = stopLocation; - } - public String getDirectionId() { - return directionId; - } - public void setDirectionId(String directionId) { - this.directionId = directionId; - } - public ArrayList getPath() { - return path; - } - public void setPath(ArrayList path) { - this.path = path; - } + } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java index 233ad5206..1f44bf98d 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversions.java @@ -1,17 +1,21 @@ package org.transitclock.api.data; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; - import org.transitclock.ipc.data.IpcDiversion; -@XmlRootElement(name = "diversions") -public class ApiDiversions { +@XmlRootElement +public class ApiDiversions implements Serializable{ - public ApiDiversions() { + /** + * + */ + private static final long serialVersionUID = 8945488673196807736L; + protected ApiDiversions() { } @@ -22,14 +26,6 @@ public ApiDiversions(List ipcDiversions) { diversions.add(new ApiDiversion(ipcDiversion)); } } - @XmlElement(name="diversion") - private List diversions; - public List getDiversions() { - return diversions; - } - - public void setDiversions(List diversions) { - this.diversions = diversions; - } - + @XmlElement(name="diversions") + private List diversions; } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java index 94a066364..2a55026d5 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java @@ -17,6 +17,8 @@ package org.transitclock.api.data; +import java.io.Serializable; + import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlTransient; @@ -36,7 +38,12 @@ * */ @XmlTransient -public class ApiTransientLocation { +public class ApiTransientLocation implements Serializable{ + + /** + * + */ + private static final long serialVersionUID = 1997973510120089077L; @XmlAttribute private double lat; diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/customwriter/ApiDiversionsBodyWriter.java b/transitclockApi/src/main/java/org/transitclock/api/data/customwriter/ApiDiversionsBodyWriter.java new file mode 100644 index 000000000..9cb0d5de7 --- /dev/null +++ b/transitclockApi/src/main/java/org/transitclock/api/data/customwriter/ApiDiversionsBodyWriter.java @@ -0,0 +1,54 @@ +package org.transitclock.api.data.customwriter; + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyWriter; +import javax.ws.rs.ext.Provider; + +import org.transitclock.api.data.ApiDiversions; +@Provider +@Produces(MediaType.APPLICATION_JSON) +public class ApiDiversionsBodyWriter implements MessageBodyWriter { + + public ApiDiversionsBodyWriter() { + super(); + // TODO Auto-generated constructor stub + } + + @Override + public boolean isWriteable(Class type, Type genericType, Annotation[] annotations, MediaType mediaType) { + + return type == ApiDiversions.class; + } + + @Override + public long getSize(ApiDiversions t, Class type, Type genericType, Annotation[] annotations, + MediaType mediaType) { + + return 0; + } + + @Override + public void writeTo(ApiDiversions t, Class type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap httpHeaders, OutputStream entityStream) + throws IOException, WebApplicationException { + Writer writer = new PrintWriter(entityStream); + writer.write(""); + writer.write(""); + writer.write("

JAX-RS Message Body Writer Example

"); + writer.write(""); + writer.write(""); + writer.flush(); + writer.close(); + } + +} diff --git a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java index b903817c3..561a23647 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java +++ b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java @@ -1,25 +1,19 @@ package org.transitclock.api.rootResources; -import java.rmi.RemoteException; - import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; - -import org.transitclock.api.data.ApiCacheDetails; import org.transitclock.api.data.ApiDiversion; import org.transitclock.api.data.ApiDiversions; import org.transitclock.api.utils.StandardParameters; import org.transitclock.api.utils.WebUtils; -import org.transitclock.core.diversion.model.Diversion; import org.transitclock.ipc.data.IpcDiversions; import org.transitclock.ipc.interfaces.DiversionsInterface; @@ -83,9 +77,11 @@ public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameter } catch (Exception e) { // If problem getting data then return a Bad Request - throw WebUtils.badRequestException(e); + e.printStackTrace(); + throw WebUtils.badRequestException(e); } } + @Path("/command/putDiversion") @POST @Consumes(MediaType.APPLICATION_JSON) public Response addDiversion(ApiDiversion diversion) @@ -93,4 +89,5 @@ public Response addDiversion(ApiDiversion diversion) String result = "Diversion added : " + diversion; return Response.status(201).entity(result).build(); } + } From 5864033739b38ce8e7a92a85d2e9fb776cb5e7e8 Mon Sep 17 00:00:00 2001 From: scrudden Date: Thu, 30 Apr 2020 16:44:59 +0100 Subject: [PATCH 16/17] Add diversion api call now working. --- .../core/diversion/model/Diversion.java | 20 +++++- .../transitclock/ipc/data/IpcDiversion.java | 1 + transitclockApi/pom.xml | 7 +- .../transitclock/api/data/ApiDiversion.java | 40 +++++++++++ .../api/data/ApiDiversionStopPath.java | 24 +++++++ .../api/data/ApiTransientLocation.java | 9 +++ .../api/rootResources/DiversionApi.java | 71 ++++++++++++++++++- 7 files changed, 169 insertions(+), 3 deletions(-) diff --git a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java index 2f21af9be..aa7c3a28e 100644 --- a/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java +++ b/transitclock/src/main/java/org/transitclock/core/diversion/model/Diversion.java @@ -12,6 +12,8 @@ import org.transitclock.db.structs.Trip; import org.transitclock.db.structs.VectorWithHeading; import org.transitclock.ipc.data.IpcDiversion; +import org.transitclock.ipc.data.IpcDiversionStopPath; +import org.transitclock.ipc.data.IpcLocation; /** * @author Sean Óg Crudden This is the starting point of modeling a detour. @@ -80,7 +82,23 @@ public Diversion(IpcDiversion diversion) { } void copyStopPaths(IpcDiversion diversion) { - + for(IpcDiversionStopPath ipcStopPath:diversion.getDiversionStopPaths()) + { + DiversionStopPath stopPath=new DiversionStopPath(); + stopPath.setDirectionId(ipcStopPath.getDirectionId()); + stopPath.setStopId(ipcStopPath.getStopId()); + stopPath.setStopName(ipcStopPath.getStopName()); + stopPath.setStopSequence(ipcStopPath.getStopSequence()); + if(ipcStopPath.getStopLocation()!=null) + stopPath.setStopLocation(new Location(ipcStopPath.getStopLocation().getLat(), ipcStopPath.getStopLocation().getLon())); + + for(IpcLocation point:ipcStopPath.getPath()) + { + stopPath.getPath().add(new Location(point.getLat(), point.getLon())); + } + + diversionStopPaths.add(stopPath); + } } public ArrayList getDiversionStopPaths() { diff --git a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java index 4fa5209ec..2a231b244 100644 --- a/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java +++ b/transitclock/src/main/java/org/transitclock/ipc/data/IpcDiversion.java @@ -76,6 +76,7 @@ public IpcDiversion(Diversion diversion) { } + public String getRouteId() { return routeId; } diff --git a/transitclockApi/pom.xml b/transitclockApi/pom.xml index fd90665a9..78dffb36e 100755 --- a/transitclockApi/pom.xml +++ b/transitclockApi/pom.xml @@ -43,7 +43,12 @@ 2.11 - + + commons-beanutils + commons-beanutils + 1.9.3 + + TheTransitClock transitclockCore diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java index 0c343cc2d..0f847c644 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversion.java @@ -69,5 +69,45 @@ public ApiDiversion(IpcDiversion diversion) } } + public String getRouteId() { + return routeId; + } + + public String getTripId() { + return tripId; + } + + public String getShapeId() { + return shapeId; + } + + public int getStartStopSeq() { + return startStopSeq; + } + + public int getDistanceStartAlongSegment() { + return distanceStartAlongSegment; + } + + public int getReturnStopSeq() { + return returnStopSeq; + } + + public int getDistanceEndAlongSegment() { + return distanceEndAlongSegment; + } + + public List getDiversionStopPaths() { + return diversionStopPaths; + } + + public Date getStartTime() { + return startTime; + } + + public Date getEndTime() { + return endTime; + } + } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java index 00d17e0f6..e7baf2af4 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiDiversionStopPath.java @@ -56,5 +56,29 @@ public ApiDiversionStopPath(IpcDiversionStopPath diversionStopPath) } } + public String getStopId() { + return stopId; + } + + public String getStopName() { + return stopName; + } + + public Integer getStopSequence() { + return stopSequence; + } + + public ApiLocation getStopLocation() { + return stopLocation; + } + + public String getDirectionId() { + return directionId; + } + + public ArrayList getPath() { + return path; + } + } diff --git a/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java b/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java index 2a55026d5..084a70dc0 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java +++ b/transitclockApi/src/main/java/org/transitclock/api/data/ApiTransientLocation.java @@ -70,4 +70,13 @@ public ApiTransientLocation(double lat, double lon) { // Output only 5 digits past decimal point this.lon = MathUtils.round(latLon.getLon(), 5); } + + public double getLat() { + return lat; + } + + public double getLon() { + return lon; + } + } diff --git a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java index 561a23647..9f48f5882 100644 --- a/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java +++ b/transitclockApi/src/main/java/org/transitclock/api/rootResources/DiversionApi.java @@ -1,5 +1,7 @@ package org.transitclock.api.rootResources; +import java.util.ArrayList; + import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; import javax.ws.rs.GET; @@ -10,10 +12,19 @@ import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; + +import org.apache.commons.beanutils.BeanUtils; import org.transitclock.api.data.ApiDiversion; +import org.transitclock.api.data.ApiDiversionStopPath; import org.transitclock.api.data.ApiDiversions; +import org.transitclock.api.data.ApiLocation; import org.transitclock.api.utils.StandardParameters; import org.transitclock.api.utils.WebUtils; +import org.transitclock.core.diversion.model.Diversion; +import org.transitclock.core.diversion.model.DiversionStopPath; +import org.transitclock.db.structs.Location; +import org.transitclock.ipc.data.IpcDiversion; +import org.transitclock.ipc.data.IpcDiversionStopPath; import org.transitclock.ipc.data.IpcDiversions; import org.transitclock.ipc.interfaces.DiversionsInterface; @@ -84,10 +95,68 @@ public Response getDiversionsByTripId(@BeanParam StandardParameters stdParameter @Path("/command/putDiversion") @POST @Consumes(MediaType.APPLICATION_JSON) - public Response addDiversion(ApiDiversion diversion) + public Response addDiversion(@BeanParam StandardParameters stdParameters, ApiDiversion diversion) { String result = "Diversion added : " + diversion; + stdParameters.validate(); + + try { + DiversionsInterface diverionsInterface = stdParameters.getDiversionInterface(); + + Diversion detour=new Diversion(); + + copyProperties(detour,diversion); + + diverionsInterface.addDiversion(new IpcDiversion(detour)); + + }catch(Exception e) + { + + throw WebUtils.badRequestException(e); + } + return Response.status(201).entity(result).build(); + } + private void copyProperties(Diversion detour, ApiDiversion diversion) { + detour.setStartStopSeq(diversion.getStartStopSeq()); + detour.setReturnStopSeq(diversion.getReturnStopSeq()); + detour.setRouteId(diversion.getRouteId()); + detour.setTripId(diversion.getTripId()); + detour.setShapeId(diversion.getShapeId()); + detour.setDistanceStartAlongSegment(diversion.getDistanceStartAlongSegment()); + detour.setDistanceEndAlongSegment(diversion.getDistanceEndAlongSegment()); + detour.setStartTime(diversion.getStartTime()); + detour.setEndTime(diversion.getEndTime()); + + ArrayList stopPaths = new ArrayList(); + + for(ApiDiversionStopPath apiStopPath:diversion.getDiversionStopPaths()) + { + DiversionStopPath stopPath = new DiversionStopPath(); + + stopPath.setDirectionId(apiStopPath.getDirectionId()); + stopPath.setStopId(apiStopPath.getStopId()); + + if(apiStopPath.getStopLocation()!=null) + stopPath.setStopLocation(new Location(apiStopPath.getStopLocation().getLat(), apiStopPath.getStopLocation().getLon())); + + stopPath.setStopName(apiStopPath.getStopName()); + stopPath.setStopSequence(apiStopPath.getStopSequence()); + + ArrayList path=new ArrayList(); + + for(ApiLocation point:apiStopPath.getPath()) + { + path.add(new Location(point.getLat(), point.getLon())); + } + stopPath.setPath(path); + stopPaths.add(stopPath); + + } + + detour.setDiversionStopPaths(stopPaths); + } + } From 8174ab16d131875a7ae22be79e532e68c0653a87 Mon Sep 17 00:00:00 2001 From: scrudden Date: Fri, 1 May 2020 12:19:49 +0000 Subject: [PATCH 17/17] Fix compile issue. --- transitclock/pom.xml | 3 ++- .../traveltime/kalman/KalmanPredictionGeneratorImpl.java | 3 ++- .../traveltime/kalman/KalmanPredictionGeneratorImpl.java | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/transitclock/pom.xml b/transitclock/pom.xml index 06d009920..06457e14a 100755 --- a/transitclock/pom.xml +++ b/transitclock/pom.xml @@ -1,4 +1,5 @@ - + + 4.0.0 TheTransitClock diff --git a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/kalman/KalmanPredictionGeneratorImpl.java b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/kalman/KalmanPredictionGeneratorImpl.java index a49bb6ac7..07fdd8415 100755 --- a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/kalman/KalmanPredictionGeneratorImpl.java +++ b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/frequency/traveltime/kalman/KalmanPredictionGeneratorImpl.java @@ -12,6 +12,7 @@ import org.transitclock.config.DoubleConfigValue; import org.transitclock.config.IntegerConfigValue; import org.transitclock.core.Indices; +import org.transitclock.core.RouteMatch; import org.transitclock.core.SpatialMatch; import org.transitclock.core.TravelTimeDetails; import org.transitclock.core.VehicleState; @@ -211,7 +212,7 @@ public long getTravelTimeForPath(Indices indices, AvlReport avlReport, VehicleSt } @Override - public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, SpatialMatch match) { + public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, RouteMatch match) { if(useKalmanForPartialStopPaths.getValue().booleanValue()) { diff --git a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/scheduled/traveltime/kalman/KalmanPredictionGeneratorImpl.java b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/scheduled/traveltime/kalman/KalmanPredictionGeneratorImpl.java index b9dc02d95..01bf69b50 100755 --- a/transitclock/src/main/java/org/transitclock/core/predictiongenerator/scheduled/traveltime/kalman/KalmanPredictionGeneratorImpl.java +++ b/transitclock/src/main/java/org/transitclock/core/predictiongenerator/scheduled/traveltime/kalman/KalmanPredictionGeneratorImpl.java @@ -15,6 +15,7 @@ import org.transitclock.core.HeadwayDetails; import org.transitclock.core.Indices; import org.transitclock.core.PredictionGeneratorDefaultImpl; +import org.transitclock.core.RouteMatch; import org.transitclock.core.SpatialMatch; import org.transitclock.core.TemporalDifference; import org.transitclock.core.TravelTimeDetails; @@ -227,7 +228,7 @@ public long getTravelTimeForPath(Indices indices, AvlReport avlReport, VehicleSt } @Override - public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, SpatialMatch match) { + public long expectedTravelTimeFromMatchToEndOfStopPath(AvlReport avlReport, RouteMatch match) { if(useKalmanForPartialStopPaths.getValue().booleanValue()) {