use of uk.org.siri.siri20.MonitoredCallStructure in project OpenTripPlanner by opentripplanner.
the class TimetableHelper method createUpdatedTripTimes.
/**
* Apply the TripUpdate to the appropriate TripTimes from this Timetable. The existing TripTimes
* must not be modified directly because they may be shared with the underlying
* scheduledTimetable, or other updated Timetables. The {@link TimetableSnapshot} performs the
* protective copying of this Timetable. It is not done in this update method to avoid
* repeatedly cloning the same Timetable when several updates are applied to it at once. We
* assume here that all trips in a timetable are from the same feed, which should always be the
* case.
*
* @param activity SIRI-VM VehicleActivity
* @param timeZone time zone of trip update
* @param tripId
* @return new copy of updated TripTimes after TripUpdate has been applied on TripTimes of trip
* with the id specified in the trip descriptor of the TripUpdate; null if something
* went wrong
*/
public static TripTimes createUpdatedTripTimes(Timetable timetable, Graph graph, VehicleActivityStructure activity, TimeZone timeZone, FeedScopedId tripId) {
if (activity == null) {
return null;
}
MonitoredVehicleJourneyStructure mvj = activity.getMonitoredVehicleJourney();
int tripIndex = timetable.getTripIndex(tripId);
if (tripIndex == -1) {
LOG.trace("tripId {} not found in pattern.", tripId);
return null;
}
final TripTimes existingTripTimes = timetable.getTripTimes(tripIndex);
TripTimes newTimes = new TripTimes(existingTripTimes);
MonitoredCallStructure update = mvj.getMonitoredCall();
if (update == null) {
return null;
}
final List<Stop> stops = timetable.pattern.getStops();
VehicleActivityStructure.MonitoredVehicleJourney monitoredVehicleJourney = activity.getMonitoredVehicleJourney();
Duration delay = null;
if (monitoredVehicleJourney != null) {
delay = monitoredVehicleJourney.getDelay();
int updatedDelay = 0;
if (delay != null) {
updatedDelay = delay.getSign() * (delay.getHours() * 3600 + delay.getMinutes() * 60 + delay.getSeconds());
}
MonitoredCallStructure monitoredCall = monitoredVehicleJourney.getMonitoredCall();
if (monitoredCall != null && monitoredCall.getStopPointRef() != null) {
boolean matchFound = false;
int arrivalDelay = 0;
int departureDelay = 0;
for (int index = 0; index < newTimes.getNumStops(); ++index) {
if (!matchFound) {
// Delay is set on a single stop at a time. When match is found - propagate delay on all following stops
final Stop stop = stops.get(index);
matchFound = stop.getId().getId().equals(monitoredCall.getStopPointRef().getValue());
if (!matchFound && stop.isPartOfStation()) {
FeedScopedId alternativeId = new FeedScopedId(stop.getId().getFeedId(), monitoredCall.getStopPointRef().getValue());
Stop alternativeStop = graph.index.getStopForId(alternativeId);
if (alternativeStop != null && alternativeStop.isPartOfStation()) {
matchFound = stop.isPartOfSameStationAs(alternativeStop);
}
}
if (matchFound) {
arrivalDelay = departureDelay = updatedDelay;
} else {
/*
* If updated delay is less than previously set delay, the existing delay needs to be adjusted to avoid
* non-increasing times causing updates to be rejected. Will only affect historical data.
*/
arrivalDelay = Math.min(existingTripTimes.getArrivalDelay(index), updatedDelay);
departureDelay = Math.min(existingTripTimes.getDepartureDelay(index), updatedDelay);
}
}
newTimes.updateArrivalDelay(index, arrivalDelay);
newTimes.updateDepartureDelay(index, departureDelay);
}
}
}
if (!newTimes.timesIncreasing()) {
LOG.info("TripTimes are non-increasing after applying SIRI delay propagation - delay: {}", delay);
return null;
}
// If state is already MODIFIED - keep existing state
if (newTimes.getRealTimeState() != RealTimeState.MODIFIED) {
// Make sure that updated trip times have the correct real time state
newTimes.setRealTimeState(RealTimeState.UPDATED);
}
return newTimes;
}
use of uk.org.siri.siri20.MonitoredCallStructure in project onebusaway-application-modules by camsys.
the class SiriSupportV2 method fillMonitoredCall.
private static void fillMonitoredCall(MonitoredVehicleJourneyStructure monitoredVehicleJourney, BlockInstanceBean blockInstance, TripStatusBean tripStatus, StopBean monitoredCallStopBean, PresentationService presentationService, TransitDataService transitDataService, Map<String, TimepointPredictionRecord> stopLevelPredictions, boolean hasRealtimeData, DetailLevel detailLevel, long responseTimestamp) {
List<BlockTripBean> blockTrips = blockInstance.getBlockConfiguration().getTrips();
double distanceOfVehicleAlongBlock = 0;
int blockTripStopsAfterTheVehicle = 0;
boolean foundActiveTrip = false;
for (int i = 0; i < blockTrips.size(); i++) {
BlockTripBean blockTrip = blockTrips.get(i);
if (!foundActiveTrip) {
if (tripStatus.getActiveTrip().getId().equals(blockTrip.getTrip().getId())) {
double distanceAlongTrip = tripStatus.getDistanceAlongTrip();
if (!hasRealtimeData) {
distanceAlongTrip = tripStatus.getScheduledDistanceAlongTrip();
}
distanceOfVehicleAlongBlock += distanceAlongTrip;
foundActiveTrip = true;
} else {
// next.
if (i + 1 < blockTrips.size()) {
distanceOfVehicleAlongBlock = blockTrips.get(i + 1).getDistanceAlongBlock();
}
// further
continue;
}
}
HashMap<String, Integer> visitNumberForStopMap = new HashMap<String, Integer>();
for (BlockStopTimeBean stopTime : blockTrip.getBlockStopTimes()) {
int visitNumber = getVisitNumber(visitNumberForStopMap, stopTime.getStopTime().getStop());
// on future trips, count always.
if (tripStatus.getActiveTrip().getId().equals(blockTrip.getTrip().getId())) {
if (stopTime.getDistanceAlongBlock() >= distanceOfVehicleAlongBlock) {
blockTripStopsAfterTheVehicle++;
} else {
// further
continue;
}
// future trip--bus hasn't reached this trip yet, so count
// all stops
} else {
blockTripStopsAfterTheVehicle++;
}
// monitored call
if (stopTime.getStopTime().getStop().getId().equals(monitoredCallStopBean.getId())) {
if (!presentationService.isOnDetour(tripStatus)) {
MonitoredCallStructure mcs = getMonitoredCallStructure(stopTime.getStopTime().getStop(), presentationService, stopTime.getDistanceAlongBlock() - blockTrip.getDistanceAlongBlock(), stopTime.getDistanceAlongBlock() - distanceOfVehicleAlongBlock, visitNumber, blockTripStopsAfterTheVehicle - 1, stopLevelPredictions.get(stopTime.getStopTime().getStop().getId()), detailLevel, responseTimestamp);
if (mcs != null) {
monitoredVehicleJourney.setMonitoredCall(mcs);
}
}
// we found our monitored call--stop
return;
}
}
}
}
use of uk.org.siri.siri20.MonitoredCallStructure in project onebusaway-application-modules by camsys.
the class SiriSupportV2 method getMonitoredCallStructure.
private static MonitoredCallStructure getMonitoredCallStructure(StopBean stopBean, PresentationService presentationService, double distanceOfCallAlongTrip, double distanceOfVehicleFromCall, int visitNumber, int index, TimepointPredictionRecord prediction, DetailLevel detailLevel, long responseTimestamp) {
if (prediction.getScheduleRelationship() != null && prediction.isSkipped()) {
_log.info("SKIPPED STOP: " + stopBean.getId());
return null;
}
MonitoredCallStructure monitoredCallStructure = new MonitoredCallStructure();
monitoredCallStructure.setVisitNumber(BigInteger.valueOf(visitNumber));
StopPointRefStructure stopPointRef = new StopPointRefStructure();
stopPointRef.setValue(stopBean.getId());
NaturalLanguageStringStructure stopPoint = new NaturalLanguageStringStructure();
stopPoint.setValue(stopBean.getName());
if (prediction != null) {
// do not allow predicted times to be less than ResponseTimestamp
if (prediction.getTimepointPredictedArrivalTime() < responseTimestamp) {
/*
* monitoredCall has less precision than onwardCall (date vs.
* timestamp) which results in a small amount of error when
* converting back to timestamp. Add a second here to prevent
* negative values from showing up in the UI (actual precision
* of the value is 1 minute, so a second has little influence)
*/
monitoredCallStructure.setExpectedArrivalTime(DateUtil.toXmlGregorianCalendar(responseTimestamp + 1000));
monitoredCallStructure.setExpectedDepartureTime(DateUtil.toXmlGregorianCalendar(responseTimestamp + 1000));
} else {
monitoredCallStructure.setExpectedArrivalTime(DateUtil.toXmlGregorianCalendar(prediction.getTimepointPredictedArrivalTime()));
monitoredCallStructure.setExpectedDepartureTime(DateUtil.toXmlGregorianCalendar(prediction.getTimepointPredictedArrivalTime()));
}
}
// siri extensions
// TODO - LCARABALLO - Distance Along Route Might Still need Extension
/*SiriExtensionWrapper wrapper = new SiriExtensionWrapper();
ExtensionsStructure distancesExtensions = new ExtensionsStructure();
SiriDistanceExtension distances = new SiriDistanceExtension();
DecimalFormat df = new DecimalFormat();
df.setMaximumFractionDigits(2);
df.setGroupingUsed(false);
distances.setCallDistanceAlongRoute(Double.valueOf(df
.format(distanceOfCallAlongTrip)));
wrapper.setDistances(distances);
distancesExtensions.setAny(wrapper);
monitoredCallStructure.setExtensions(distancesExtensions);*/
// distances
NaturalLanguageStringStructure presentableDistance = new NaturalLanguageStringStructure();
presentableDistance.setValue(presentationService.getPresentableDistance(distanceOfVehicleFromCall, index));
monitoredCallStructure.setNumberOfStopsAway(BigInteger.valueOf(index));
monitoredCallStructure.setDistanceFromStop(new BigDecimal(distanceOfVehicleFromCall).toBigInteger());
monitoredCallStructure.setArrivalProximityText(presentableDistance);
// basic
if (detailLevel.equals(DetailLevel.BASIC) || detailLevel.equals(DetailLevel.NORMAL) || detailLevel.equals(DetailLevel.CALLS)) {
monitoredCallStructure.getStopPointName().add(stopPoint);
}
// normal
if (detailLevel.equals(DetailLevel.NORMAL) || detailLevel.equals(DetailLevel.CALLS)) {
monitoredCallStructure.setStopPointRef(stopPointRef);
}
return monitoredCallStructure;
}
Aggregations