|
| 1 | +package org.hisrc.gtfs.graph.builder.jgrapht; |
| 2 | + |
| 3 | +import java.util.HashSet; |
| 4 | +import java.util.Set; |
| 5 | + |
| 6 | +import org.hisrc.gtfs.graph.model.TemporalStopNode; |
| 7 | +import org.hisrc.gtfs.graph.model.TransitionEdge; |
| 8 | +import org.hisrc.gtfs.graph.model.TransitionType; |
| 9 | +import org.jgrapht.DirectedGraph; |
| 10 | +import org.jgrapht.EdgeFactory; |
| 11 | +import org.jgrapht.graph.DirectedMultigraph; |
| 12 | +import org.joda.time.LocalDate; |
| 13 | +import org.onebusaway.gtfs.impl.GtfsDaoImpl; |
| 14 | +import org.onebusaway.gtfs.model.AgencyAndId; |
| 15 | +import org.onebusaway.gtfs.model.ServiceCalendar; |
| 16 | +import org.onebusaway.gtfs.model.ServiceCalendarDate; |
| 17 | +import org.onebusaway.gtfs.model.Stop; |
| 18 | +import org.onebusaway.gtfs.model.StopTime; |
| 19 | +import org.onebusaway.gtfs.model.Trip; |
| 20 | +import org.onebusaway.gtfs.model.calendar.ServiceDate; |
| 21 | +import org.onebusaway.gtfs.services.GtfsMutableDao; |
| 22 | +import org.slf4j.Logger; |
| 23 | +import org.slf4j.LoggerFactory; |
| 24 | + |
| 25 | +public class GtfsDirectedGraphBuilder { |
| 26 | + |
| 27 | + private final ServiceDate serviceDate; |
| 28 | + private final int dayOfWeek; |
| 29 | + private final Set<AgencyAndId> availableServiceIds = new HashSet<AgencyAndId>(); |
| 30 | + |
| 31 | + public GtfsDirectedGraphBuilder(int year, int month, int day) { |
| 32 | + this.serviceDate = new ServiceDate(year, month, day); |
| 33 | + final LocalDate localDate = new LocalDate(year, month, day); |
| 34 | + this.dayOfWeek = localDate.getDayOfWeek(); |
| 35 | + } |
| 36 | + |
| 37 | + private DirectedGraph<TemporalStopNode, TransitionEdge> graph = new DirectedMultigraph<TemporalStopNode, TransitionEdge>( |
| 38 | + new EdgeFactory<TemporalStopNode, TransitionEdge>() { |
| 39 | + @Override |
| 40 | + public TransitionEdge createEdge(TemporalStopNode start, |
| 41 | + TemporalStopNode stop) { |
| 42 | + throw new UnsupportedOperationException(); |
| 43 | + } |
| 44 | + }); |
| 45 | + |
| 46 | + private Logger logger = LoggerFactory |
| 47 | + .getLogger(GtfsDirectedGraphBuilder.class); |
| 48 | + |
| 49 | + private final GtfsMutableDao gtfsDao = new GtfsDaoImpl() { |
| 50 | + public void saveEntity(Object entity) { |
| 51 | + super.saveEntity(entity); |
| 52 | + if (entity instanceof ServiceCalendarDate) { |
| 53 | + addServiceCalendarDate((ServiceCalendarDate) entity); |
| 54 | + } |
| 55 | + if (entity instanceof ServiceCalendar) { |
| 56 | + addServiceCalendar((ServiceCalendar) entity); |
| 57 | + } |
| 58 | + if (entity instanceof StopTime) { |
| 59 | + addStopTime((StopTime) entity); |
| 60 | + } |
| 61 | + } |
| 62 | + |
| 63 | + }; |
| 64 | + |
| 65 | + private Set<Trip> processedTrips = new HashSet<Trip>(); |
| 66 | + private Trip lastTrip = null; |
| 67 | + private TemporalStopNode lastNode = null; |
| 68 | + private int lastStopSequence = -1; |
| 69 | + |
| 70 | + int count = 0; |
| 71 | + |
| 72 | + public void addStopTime(StopTime stopTime) { |
| 73 | + |
| 74 | + final Trip trip = stopTime.getTrip(); |
| 75 | + if (!availableServiceIds.contains(trip.getServiceId())) { |
| 76 | + return; |
| 77 | + } |
| 78 | + |
| 79 | + final int stopSequence = stopTime.getStopSequence(); |
| 80 | + // logger.info("Stop sequence [" + stopSequence + "]."); |
| 81 | + final TemporalStopNode previousDepartureNode; |
| 82 | + if (trip == lastTrip) { |
| 83 | + if (stopSequence <= lastStopSequence) { |
| 84 | + throw new IllegalStateException( |
| 85 | + "Stop sequence must be greater than the last stop sequence."); |
| 86 | + } else { |
| 87 | + previousDepartureNode = lastNode; |
| 88 | + } |
| 89 | + } else { |
| 90 | + if (processedTrips.contains(trip)) { |
| 91 | + throw new IllegalStateException( |
| 92 | + "Trip was already processed and now appears again."); |
| 93 | + } else { |
| 94 | + processedTrips.add(lastTrip); |
| 95 | + previousDepartureNode = null; |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + final Stop stop = stopTime.getStop(); |
| 100 | + final int arrivalTime = stopTime.getArrivalTime(); |
| 101 | + final int departureTime = stopTime.getDepartureTime(); |
| 102 | + |
| 103 | + final TemporalStopNode arrivalNode = new TemporalStopNode(stop, |
| 104 | + arrivalTime, false); |
| 105 | + final TemporalStopNode departureNode = new TemporalStopNode(stop, |
| 106 | + departureTime, true); |
| 107 | + graph.addVertex(arrivalNode); |
| 108 | + graph.addVertex(departureNode); |
| 109 | + |
| 110 | + if (previousDepartureNode != null) { |
| 111 | + final int previousDepartureTime = previousDepartureNode.getTime(); |
| 112 | + final TransitionEdge departureArrivalTransitionEdge = new TransitionEdge( |
| 113 | + TransitionType.DEPARTURE_ARRIVAL, arrivalTime |
| 114 | + - previousDepartureTime); |
| 115 | + |
| 116 | + // logger.info("Adding [" + previousDepartureNode + "--->" |
| 117 | + // + arrivalNode + "]"); |
| 118 | + graph.addEdge(previousDepartureNode, arrivalNode, |
| 119 | + departureArrivalTransitionEdge); |
| 120 | + } |
| 121 | + // logger.info("Adding [" + arrivalNode + "-" + departureNode + "]"); |
| 122 | + final TransitionEdge arrivalDepartureTransitionEdge = new TransitionEdge( |
| 123 | + TransitionType.ARRIVAL_DEPARTURE, departureTime - arrivalTime); |
| 124 | + graph.addEdge(arrivalNode, departureNode, |
| 125 | + arrivalDepartureTransitionEdge); |
| 126 | + |
| 127 | + lastTrip = trip; |
| 128 | + lastNode = departureNode; |
| 129 | + lastStopSequence = stopTime.getStopSequence(); |
| 130 | + if (count % 10000 == 0) { |
| 131 | + logger.info("" + count); |
| 132 | + } |
| 133 | + count++; |
| 134 | + } |
| 135 | + |
| 136 | + private void addServiceCalendar(ServiceCalendar serviceCalendar) { |
| 137 | + if (serviceCalendar.getStartDate().compareTo(this.serviceDate) <= 0 |
| 138 | + && serviceCalendar.getEndDate().compareTo(this.serviceDate) >= 0 |
| 139 | + && (this.dayOfWeek == 1 && serviceCalendar.getMonday() == 1) |
| 140 | + || (this.dayOfWeek == 2 && serviceCalendar.getTuesday() == 1) |
| 141 | + || (this.dayOfWeek == 3 && serviceCalendar.getWednesday() == 1) |
| 142 | + || (this.dayOfWeek == 4 && serviceCalendar.getThursday() == 1) |
| 143 | + || (this.dayOfWeek == 5 && serviceCalendar.getFriday() == 1) |
| 144 | + || (this.dayOfWeek == 6 && serviceCalendar.getSaturday() == 1) |
| 145 | + || (this.dayOfWeek == 7 && serviceCalendar.getSunday() == 1)) { |
| 146 | + availableServiceIds.add(serviceCalendar.getServiceId()); |
| 147 | + } |
| 148 | + } |
| 149 | + |
| 150 | + private void addServiceCalendarDate(ServiceCalendarDate serviceCalendarDate) { |
| 151 | + if (serviceCalendarDate.getExceptionType() == 1 |
| 152 | + && serviceCalendarDate.getDate().equals(this.serviceDate)) { |
| 153 | + availableServiceIds.add(serviceCalendarDate.getServiceId()); |
| 154 | + } |
| 155 | + } |
| 156 | + |
| 157 | + public GtfsMutableDao getGtfsMutableDao() { |
| 158 | + return gtfsDao; |
| 159 | + } |
| 160 | + |
| 161 | + public DirectedGraph<TemporalStopNode, TransitionEdge> build() { |
| 162 | + return graph; |
| 163 | + } |
| 164 | +} |
0 commit comments