use of org.opentripplanner.model.Stop in project OpenTripPlanner by opentripplanner.
the class TimetableSnapshotSource method checkNewStopTimeUpdatesAndFindStops.
/**
* Check stop time updates of trip update that results in a new trip (ADDED or MODIFIED) and
* find all stops of that trip.
*
* @param feedId feed id this trip update is intented for
* @param tripUpdate trip update
* @return stops when stop time updates are correct; null if there are errors
*/
private List<Stop> checkNewStopTimeUpdatesAndFindStops(final String feedId, final TripUpdate tripUpdate) {
Integer previousStopSequence = null;
Long previousTime = null;
final List<StopTimeUpdate> stopTimeUpdates = tripUpdate.getStopTimeUpdateList();
final List<Stop> stops = new ArrayList<>(stopTimeUpdates.size());
for (int index = 0; index < stopTimeUpdates.size(); ++index) {
final StopTimeUpdate stopTimeUpdate = stopTimeUpdates.get(index);
// Determine whether stop is skipped
final boolean skippedStop = isStopSkipped(stopTimeUpdate);
// Check stop sequence
if (stopTimeUpdate.hasStopSequence()) {
final Integer stopSequence = stopTimeUpdate.getStopSequence();
// Check non-negative
if (stopSequence < 0) {
LOG.warn("Trip update contains negative stop sequence, skipping.");
return null;
}
// Check whether sequence is increasing
if (previousStopSequence != null && previousStopSequence > stopSequence) {
LOG.warn("Trip update contains decreasing stop sequence, skipping.");
return null;
}
previousStopSequence = stopSequence;
} else {
// Allow missing stop sequences for ADDED and MODIFIED trips
}
// Find stops
if (stopTimeUpdate.hasStopId()) {
// Find stop
final Stop stop = getStopForStopId(feedId, stopTimeUpdate.getStopId());
if (stop != null) {
// Remember stop
stops.add(stop);
} else if (skippedStop) {
// Set a null value for a skipped stop
stops.add(null);
} else {
LOG.warn("Graph doesn't contain stop id \"{}\" of trip update, skipping.", stopTimeUpdate.getStopId());
return null;
}
} else {
LOG.warn("Trip update misses some stop ids, skipping.");
return null;
}
// Only check arrival and departure times for non-skipped stops
if (!skippedStop) {
// Check arrival time
if (stopTimeUpdate.hasArrival() && stopTimeUpdate.getArrival().hasTime()) {
// Check for increasing time
final Long time = stopTimeUpdate.getArrival().getTime();
if (previousTime != null && previousTime > time) {
LOG.warn("Trip update contains decreasing times, skipping.");
return null;
}
previousTime = time;
} else {
// TODO: should we support only requiring an arrival time on the last stop and interpolate?
for (int earlierIndex = 0; earlierIndex < index; earlierIndex++) {
final StopTimeUpdate earlierStopTimeUpdate = stopTimeUpdates.get(earlierIndex);
// Determine whether earlier stop is skipped
final boolean earlierSkippedStop = isStopSkipped(earlierStopTimeUpdate);
if (!earlierSkippedStop) {
LOG.warn("Trip update misses arrival time, skipping.");
return null;
}
}
}
// Check departure time
if (stopTimeUpdate.hasDeparture() && stopTimeUpdate.getDeparture().hasTime()) {
// Check for increasing time
final Long time = stopTimeUpdate.getDeparture().getTime();
if (previousTime != null && previousTime > time) {
LOG.warn("Trip update contains decreasing times, skipping.");
return null;
}
previousTime = time;
} else {
// TODO: should we support only requiring a departure time on the first stop and interpolate?
for (int laterIndex = stopTimeUpdates.size() - 1; laterIndex > index; laterIndex--) {
final StopTimeUpdate laterStopTimeUpdate = stopTimeUpdates.get(laterIndex);
// Determine whether later stop is skipped
final boolean laterSkippedStop = isStopSkipped(laterStopTimeUpdate);
if (!laterSkippedStop) {
LOG.warn("Trip update misses departure time, skipping.");
return null;
}
}
}
}
}
return stops;
}
use of org.opentripplanner.model.Stop in project OpenTripPlanner by opentripplanner.
the class TimetableSnapshotSource method addTripToGraphAndBuffer.
/**
* Add a (new) trip to the graph and the buffer
*
* @param graph graph
* @param trip trip
* @param tripUpdate trip update containing stop time updates
* @param stops list of stops corresponding to stop time updates
* @param serviceDate service date of trip
* @param realTimeState real-time state of new trip
* @return true iff successful
*/
private boolean addTripToGraphAndBuffer(final String feedId, final Graph graph, final Trip trip, final TripUpdate tripUpdate, final List<Stop> stops, final ServiceDate serviceDate, final RealTimeState realTimeState) {
// Preconditions
Preconditions.checkNotNull(stops);
Preconditions.checkArgument(tripUpdate.getStopTimeUpdateCount() == stops.size(), "number of stop should match the number of stop time updates");
// Calculate seconds since epoch on GTFS midnight (noon minus 12h) of service date
final Calendar serviceCalendar = serviceDate.getAsCalendar(timeZone);
final long midnightSecondsSinceEpoch = serviceCalendar.getTimeInMillis() / MILLIS_PER_SECOND;
// Create StopTimes
final List<StopTime> stopTimes = new ArrayList<>(tripUpdate.getStopTimeUpdateCount());
for (int index = 0; index < tripUpdate.getStopTimeUpdateCount(); ++index) {
final StopTimeUpdate stopTimeUpdate = tripUpdate.getStopTimeUpdate(index);
final Stop stop = stops.get(index);
// Determine whether stop is skipped
final boolean skippedStop = isStopSkipped(stopTimeUpdate);
// Only create stop time for non-skipped stops
if (!skippedStop) {
// Create stop time
final StopTime stopTime = new StopTime();
stopTime.setTrip(trip);
stopTime.setStop(stop);
// Set arrival time
if (stopTimeUpdate.hasArrival() && stopTimeUpdate.getArrival().hasTime()) {
final long arrivalTime = stopTimeUpdate.getArrival().getTime() - midnightSecondsSinceEpoch;
if (arrivalTime < 0 || arrivalTime > MAX_ARRIVAL_DEPARTURE_TIME) {
LOG.warn("ADDED trip has invalid arrival time (compared to start date in " + "TripDescriptor), skipping.");
return false;
}
stopTime.setArrivalTime((int) arrivalTime);
}
// Set departure time
if (stopTimeUpdate.hasDeparture() && stopTimeUpdate.getDeparture().hasTime()) {
final long departureTime = stopTimeUpdate.getDeparture().getTime() - midnightSecondsSinceEpoch;
if (departureTime < 0 || departureTime > MAX_ARRIVAL_DEPARTURE_TIME) {
LOG.warn("ADDED trip has invalid departure time (compared to start date in " + "TripDescriptor), skipping.");
return false;
}
stopTime.setDepartureTime((int) departureTime);
}
// Exact time
stopTime.setTimepoint(1);
if (stopTimeUpdate.hasStopSequence()) {
stopTime.setStopSequence(stopTimeUpdate.getStopSequence());
}
// Set different pickup type for last stop
if (index == tripUpdate.getStopTimeUpdateCount() - 1) {
// No pickup available
stopTime.setPickupType(1);
} else {
// Regularly scheduled pickup
stopTime.setPickupType(0);
}
// Set different drop off type for first stop
if (index == 0) {
// No drop off available
stopTime.setDropOffType(1);
} else {
// Regularly scheduled drop off
stopTime.setDropOffType(0);
}
// Add stop time to list
stopTimes.add(stopTime);
}
}
// TODO: filter/interpolate stop times like in PatternHopFactory?
// Create StopPattern
final StopPattern stopPattern = new StopPattern(stopTimes);
// Get cached trip pattern or create one if it doesn't exist yet
final TripPattern pattern = tripPatternCache.getOrCreateTripPattern(stopPattern, trip, graph);
// Add service code to bitset of pattern if needed (using copy on write)
final int serviceCode = graph.getServiceCodes().get(trip.getServiceId());
if (!pattern.getServices().get(serviceCode)) {
final BitSet services = (BitSet) pattern.getServices().clone();
services.set(serviceCode);
pattern.setServices(services);
}
// Create new trip times
final TripTimes newTripTimes = new TripTimes(trip, stopTimes, graph.deduplicator);
// TODO: should we incorporate the delay field if present?
for (int stopIndex = 0; stopIndex < newTripTimes.getNumStops(); stopIndex++) {
newTripTimes.updateArrivalTime(stopIndex, newTripTimes.getScheduledArrivalTime(stopIndex));
newTripTimes.updateDepartureTime(stopIndex, newTripTimes.getScheduledDepartureTime(stopIndex));
}
// Set service code of new trip times
newTripTimes.serviceCode = serviceCode;
// Make sure that updated trip times have the correct real time state
newTripTimes.setRealTimeState(realTimeState);
// Add new trip times to the buffer
final boolean success = buffer.update(pattern, newTripTimes, serviceDate);
return success;
}
use of org.opentripplanner.model.Stop in project OpenTripPlanner by opentripplanner.
the class TimetableSnapshotSource method validateAndHandleAddedTrip.
/**
* Validate and handle GTFS-RT TripUpdate message containing an ADDED trip.
*
* @param graph graph to update
* @param tripUpdate GTFS-RT TripUpdate message
* @param feedId
* @param serviceDate
* @return true iff successful
*/
private boolean validateAndHandleAddedTrip(final Graph graph, final TripUpdate tripUpdate, final String feedId, final ServiceDate serviceDate) {
// Preconditions
Preconditions.checkNotNull(graph);
Preconditions.checkNotNull(tripUpdate);
Preconditions.checkNotNull(serviceDate);
//
// Validate added trip
//
// Check whether trip id of ADDED trip is available
final TripDescriptor tripDescriptor = tripUpdate.getTrip();
if (!tripDescriptor.hasTripId()) {
LOG.warn("No trip id found for ADDED trip, skipping.");
return false;
}
// Check whether trip id already exists in graph
final String tripId = tripDescriptor.getTripId();
final Trip trip = getTripForTripId(feedId, tripId);
if (trip != null) {
// TODO: should we support this and add a new instantiation of this trip (making it
// frequency based)?
LOG.warn("Graph already contains trip id of ADDED trip, skipping.");
return false;
}
// Check whether a start date exists
if (!tripDescriptor.hasStartDate()) {
// TODO: should we support this and apply update to all days?
LOG.warn("ADDED trip doesn't have a start date in TripDescriptor, skipping.");
return false;
}
// Check whether at least two stop updates exist
if (tripUpdate.getStopTimeUpdateCount() < 2) {
LOG.warn("ADDED trip has less then two stops, skipping.");
return false;
}
// Check whether all stop times are available and all stops exist
final List<Stop> stops = checkNewStopTimeUpdatesAndFindStops(feedId, tripUpdate);
if (stops == null) {
return false;
}
//
// Handle added trip
//
final boolean success = handleAddedTrip(graph, tripUpdate, stops, feedId, serviceDate);
return success;
}
Aggregations