Skip to content

Commit

Permalink
refactor(Addressed PR feedback part 1):
Browse files Browse the repository at this point in the history
  • Loading branch information
br648 committed Aug 22, 2024
1 parent 69d8140 commit cf15ca1
Show file tree
Hide file tree
Showing 25 changed files with 1,582 additions and 1,612 deletions.
49 changes: 16 additions & 33 deletions src/main/java/com/conveyal/gtfs/PatternBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public class PatternBuilder {

private Table patternStopsTable;

private PreparedStatement insertPatternStopStatement;

public PatternBuilder(Feed feed) throws SQLException {
patternsTableName = feed.getTableNameWithSchemaPrefix("patterns");
tripsTableName = feed.getTableNameWithSchemaPrefix("trips");
Expand All @@ -62,6 +64,11 @@ public PatternBuilder(Feed feed) throws SQLException {
Table.PATTERN_STOP.fields
);
connection = feed.getConnection();

insertPatternStopStatement = connection.prepareStatement(
patternStopsTable.generateInsertSql(true)
);

}

public PatternBuilder() {
Expand Down Expand Up @@ -222,26 +229,19 @@ private void createPatternStops(
TripPatternKey key,
String patternId
) throws SQLException {
PreparedStatement insertPatternStopStatement = connection.prepareStatement(
patternStopsTable.generateInsertSql(true)
);
BatchTracker patternStopTracker = new BatchTracker("pattern stop", insertPatternStopStatement);

// Determine departure times based on the stop type.
List<Integer> previousDepartureTimes = calculatePreviousDepartureTimes(key);
// Construct pattern stops based on values in trip pattern key.
for (int stopSequence = 0; stopSequence < key.orderedHalts.size(); stopSequence++) {
boolean prevIsFlexStop = stopSequence > 0 && key.isFlexStop.get(stopSequence - 1);
int lastValidDepartureTime = previousDepartureTimes.get(stopSequence);
insertPatternType(
stopSequence,
key,
lastValidDepartureTime,
patternId,
insertPatternStopStatement,
patternStopTracker,
key.isFlexStop.get(stopSequence),
prevIsFlexStop
patternStopTracker
);
}
patternStopTracker.executeRemaining();
Expand All @@ -254,7 +254,8 @@ private void createPatternStops(
public List<Integer> calculatePreviousDepartureTimes(TripPatternKey key) {
List<Integer> previousDepartureTimes = new ArrayList<>();
// Determine initial departure time based on the stop type.
int lastValidDepartureTime = Boolean.TRUE.equals(key.isFlexStop.get(0))
boolean isFirstStopFlex = key.isFlexStop.get(0);
int lastValidDepartureTime = isFirstStopFlex
? key.end_pickup_drop_off_window.get(0)
: key.departureTimes.get(0);
// Set the previous departure time for the first stop, which will always be zero.
Expand Down Expand Up @@ -291,11 +292,11 @@ private void insertPatternType(
TripPatternKey tripPattern,
int lastValidDeparture,
String patternId,
PreparedStatement statement,
BatchTracker batchTracker,
boolean isFlexStop,
boolean prevIsFlexStop
BatchTracker batchTracker
) throws SQLException {
boolean isFlexStop = tripPattern.isFlexStop.get(stopSequence);
boolean prevIsFlexStop = stopSequence > 0 && tripPattern.isFlexStop.get(stopSequence - 1);

int travelTime = 0;
if (!isFlexStop) {
travelTime = getTravelTime(travelTime, stopSequence, tripPattern.arrivalTimes.get(stopSequence), lastValidDeparture);
Expand All @@ -308,26 +309,8 @@ private void insertPatternType(
? getTimeInLocation(tripPattern.arrivalTimes.get(stopSequence), tripPattern.departureTimes.get(stopSequence))
: getTimeInLocation(tripPattern.start_pickup_drop_off_window.get(stopSequence), tripPattern.end_pickup_drop_off_window.get(stopSequence));

PatternStop patternStop = new PatternStop();
patternStop.pattern_id = patternId;
patternStop.stop_sequence = stopSequence;
patternStop.stop_id = tripPattern.stops.get(stopSequence);
patternStop.location_group_id = tripPattern.locationGroupIds.get(stopSequence);
patternStop.location_id = tripPattern.locationIds.get(stopSequence);
patternStop.stop_headsign = tripPattern.stopHeadsigns.get(stopSequence);
patternStop.default_travel_time = travelTime;
patternStop.default_dwell_time = timeInLocation;
patternStop.drop_off_type = tripPattern.dropoffTypes.get(stopSequence);
patternStop.pickup_type = tripPattern.pickupTypes.get(stopSequence);
patternStop.shape_dist_traveled = tripPattern.shapeDistances.get(stopSequence);
patternStop.timepoint = tripPattern.timepoints.get(stopSequence);
patternStop.continuous_pickup = tripPattern.continuous_pickup.get(stopSequence);
patternStop.continuous_drop_off = tripPattern.continuous_drop_off.get(stopSequence);
patternStop.pickup_booking_rule_id = tripPattern.pickup_booking_rule_id.get(stopSequence);
patternStop.drop_off_booking_rule_id = tripPattern.drop_off_booking_rule_id.get(stopSequence);
patternStop.start_pickup_drop_off_window = tripPattern.start_pickup_drop_off_window.get(stopSequence);
patternStop.end_pickup_drop_off_window = tripPattern.end_pickup_drop_off_window.get(stopSequence);
patternStop.setStatementParameters(statement, true);
PatternStop patternStop = new PatternStop(patternId, stopSequence, tripPattern, travelTime, timeInLocation);
patternStop.setStatementParameters(insertPatternStopStatement, true);
batchTracker.addBatch();
}

Expand Down
38 changes: 19 additions & 19 deletions src/main/java/com/conveyal/gtfs/PatternFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -191,17 +191,16 @@ public static void renamePatterns(
}

// check for unique via stop
pattern.orderedHalts.stream().map(
orderedStopOrLocationId -> getStopType(orderedStopOrLocationId, stopById, locationById, locationGroupStopById)
).forEach(entity -> {
Set<Pattern> viaIntersection = new HashSet<>(intersection);
String stopName = getStopName(entity, locationGroupById);
viaIntersection.retainAll(info.vias.get(stopName));

if (viaIntersection.size() == 1) {
pattern.name = String.format(Locale.US, "from %s to %s via %s", fromName, toName, stopName);
}
});
pattern.orderedHalts.stream()
.map(haltId -> getStopType(haltId, stopById, locationById, locationGroupStopById))
.forEach(entity -> {
Set<Pattern> viaIntersection = new HashSet<>(intersection);
String stopName = getStopName(entity, locationGroupById);
viaIntersection.retainAll(info.vias.get(stopName));
if (viaIntersection.size() == 1) {
pattern.name = String.format(Locale.US, "from %s to %s via %s", fromName, toName, stopName);
}
});

if (pattern.name == null) {
// no unique via, one pattern is subset of other.
Expand Down Expand Up @@ -238,19 +237,20 @@ public static void renamePatterns(
* stop, location or location group stop, this method decides which.
*/
private static Object getStopType(
String orderedStopOrLocationId,
String orderedHaltId,
Map<String, Stop> stopById,
Map<String, Location> locationById,
Map<String, LocationGroupStop> locationGroupStopById
) {
if (stopById.get(orderedStopOrLocationId) != null) {
return stopById.get(orderedStopOrLocationId);
} else if (locationById.get(orderedStopOrLocationId) != null) {
return locationById.get(orderedStopOrLocationId);
} else if (locationGroupStopById.get(orderedStopOrLocationId) != null) {
return locationGroupStopById.get(orderedStopOrLocationId);
Object stop = stopById.get(orderedHaltId);
Object location = locationById.get(orderedHaltId);
Object locationGroupStop = locationGroupStopById.get(orderedHaltId);
if (stop != null) {
return stop;
} else if (location != null) {
return location;
} else {
return null;
return locationGroupStop;
}
}

Expand Down
61 changes: 30 additions & 31 deletions src/main/java/com/conveyal/gtfs/error/NewGTFSErrorType.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,37 +24,36 @@ public enum NewGTFSErrorType {
DUPLICATE_TRIP(Priority.MEDIUM, "More than one trip had an identical schedule and stops."),
FARE_TRANSFER_MISMATCH(Priority.MEDIUM, "A fare that does not permit transfers has a non-zero transfer duration."),
FEED_TRAVEL_TIMES_ROUNDED(Priority.LOW, "All travel times in the feed are rounded to the minute, which may cause unexpected results in routing applications where travel times are zero."),
FLEX_FORBIDDEN_ARRIVAL_TIME(Priority.HIGH, "It is forbidden to define an arrival time when either start pickup drop off window or end pickup drop off windows are defined."),
FLEX_FORBIDDEN_CONTINUOUS_DROP_OFF(Priority.HIGH, "It is forbidden to define a continuous drop off if start/end pick up drop off windows are defined."),
FLEX_FORBIDDEN_CONTINUOUS_PICKUP(Priority.HIGH, "It is forbidden to define a continuous pickup if start/end pick up drop off windows are defined."),
FLEX_FORBIDDEN_DEPARTURE_TIME(Priority.HIGH, "It is forbidden to define a departure time when either start pickup drop off window or end pickup drop off windows are defined."),
FLEX_FORBIDDEN_DROP_OFF_TYPE(Priority.HIGH, "It is forbidden to define a drop off type of 0 (Regularly scheduled pickup) if start/end pick up drop off windows are defined."),
FLEX_FORBIDDEN_DUPLICATE_LOCATION_GROUP_ID(Priority.HIGH, "It is forbidden to define a location group id that matches a stop id or location id."),
FLEX_FORBIDDEN_LOCATION_GROUP_ID(Priority.HIGH, "It is forbidden to define a location group id if a stop id or location id are defined."),
FLEX_FORBIDDEN_DUPLICATE_LOCATION_ID(Priority.HIGH, "It is forbidden to define a location id that matches a stop id or location group id."),
FLEX_FORBIDDEN_LOCATION_ID(Priority.HIGH, "It is forbidden to define a location id if a stop id or location group id are defined."),
FLEX_FORBIDDEN_START_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "It is forbidden to define a start pickup drop off window when either an arrive time or departure time are defined."),
FLEX_FORBIDDEN_END_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "It is forbidden to define a end pickup drop off window when either an arrive time or departure time are defined."),
FLEX_FORBIDDEN_PICKUP_TYPE(Priority.HIGH, "It is forbidden to define a pickup type of 0 (Regularly scheduled pickup) or 3 (Must coordinate with driver to arrange pickup) are forbidden if start/end pick up drop off window are defined."),
FLEX_FORBIDDEN_PICKUP_TYPE_FOR_LOCATION(Priority.HIGH, "It is forbidden to define a pickup type of 3 (Must coordinate with driver to arrange pickup) when a stop id refers to a location."),
FLEX_FORBIDDEN_PICKUP_TYPE_FOR_STOP_AREA(Priority.HIGH, "It is forbidden to define a pickup type of 3 (Must coordinate with driver to arrange pickup) when a stop id refers to a stop area."),
FLEX_FORBIDDEN_PRIOR_NOTICE_DURATION_MIN(Priority.HIGH, "It is forbidden to define a prior notice duration min unless booking type is 1 (Up to same-day booking with advance notice)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_DURATION_MAX(Priority.HIGH, "It is forbidden to define a prior notice duration max for booking type 0 (Real time booking) & 2 (Up to prior day(s) booking)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_LAST_DAY(Priority.HIGH, "It is forbidden to define a prior notice last day for booking type 2 (Up to prior day(s) booking)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_SERVICE_ID(Priority.HIGH, "It is forbidden to define a prior notice service id if prior notice start day is not defined."),
FLEX_FORBIDDEN_PRIOR_NOTICE_START_DAY_FOR_BOOKING_TYPE(Priority.HIGH, "It is forbidden to define a prior notice start day for booking type 0 (Real time booking)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_START_DAY(Priority.HIGH, "It is forbidden to define a prior notice start day for booking type 1 (Up to same-day booking with advance notice) and if prior notice duration max is defined."),
FLEX_FORBIDDEN_PRIOR_START_TIME(Priority.HIGH, "It is forbidden to define a prior notice start time if prior notice start day is not defined."),
FLEX_FORBIDDEN_STOP_ID(Priority.HIGH, "It is forbidden to define a stop id if a location group id or location id are defined."),
FLEX_FORBIDDEN_ROUTE_CONTINUOUS_DROP_OFF(Priority.HIGH, "It is forbidden to define a continuous drop off if start/end pick up drop off windows are defined for any trip of this route."),
FLEX_FORBIDDEN_ROUTE_CONTINUOUS_PICKUP(Priority.HIGH, "It is forbidden to define a continuous pick up if start/end pick up drop off windows are defined for any trip of this route."),
FLEX_REQUIRED_END_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "End pickup drop off window is required if a location group id, location id or start pickup drop off window is defined."),
FLEX_REQUIRED_PRIOR_NOTICE_DURATION_MIN(Priority.HIGH, "Prior notice duration min is required for booking type 1 (Up to same-day booking with advance notice)."),
FLEX_REQUIRED_PRIOR_NOTICE_LAST_DAY(Priority.HIGH, "Prior notice last day is required if a stop id refers to a stop area or location."),
FLEX_REQUIRED_PRIOR_NOTICE_START_TIME(Priority.HIGH, "Prior notice start time is required if prior notice start day is defined."),
FLEX_REQUIRED_STOP_ID(Priority.HIGH, "A stop id is required if both location group id and location id are not defined."),
FLEX_REQUIRED_START_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "Start pickup drop off window is required if a location group id, location id or end pickup drop off window is defined."),
FLEX_MISSING_FARE_RULE(Priority.HIGH, "A location zone id must reference a fare rule. One of contains id, destination id or origin id."),
FLEX_FORBIDDEN_ARRIVAL_TIME(Priority.HIGH, "arrival_time is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined."),
FLEX_FORBIDDEN_CONTINUOUS_DROP_OFF(Priority.HIGH, "continuous_drop_off is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined."),
FLEX_FORBIDDEN_CONTINUOUS_PICKUP(Priority.HIGH, "continuous_pickup is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined."),
FLEX_FORBIDDEN_DEPARTURE_TIME(Priority.HIGH, "departure_time is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined."),
FLEX_FORBIDDEN_DROP_OFF_TYPE(Priority.HIGH, "drop_off_type of 0 (Regularly scheduled pickup) is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined."),
FLEX_FORBIDDEN_DUPLICATE_LOCATION_GROUP_ID(Priority.HIGH, "location_group_id that matches a stop_id or location_id is not allow."),
FLEX_FORBIDDEN_LOCATION_GROUP_ID(Priority.HIGH, "location_group_id is not allow if a stop_id or location_id is defined."),
FLEX_FORBIDDEN_DUPLICATE_LOCATION_ID(Priority.HIGH, "location_id that matches a stop_id or location_group_id is not allow."),
FLEX_FORBIDDEN_LOCATION_ID(Priority.HIGH, "location_id is not allow if a stop_id or location_group_id is defined."),
FLEX_FORBIDDEN_START_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "start_pickup_drop_off_window is not allow when either an arrive_time or departure_time is defined."),
FLEX_FORBIDDEN_END_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "end_pickup_drop_off_window is not allow when either an arrive_time or departure_time is defined."),
FLEX_FORBIDDEN_PICKUP_TYPE(Priority.HIGH, "pickup_type of 0 (Regularly scheduled pickup) or 3 (Must coordinate with driver to arrange pickup) is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined."),
FLEX_FORBIDDEN_PICKUP_TYPE_FOR_LOCATION(Priority.HIGH, "pickup_type of 3 (Must coordinate with driver to arrange pickup) is not allow when a stop_id refers to a location."),
FLEX_FORBIDDEN_PRIOR_NOTICE_DURATION_MIN(Priority.HIGH, "prior_notice_duration_min is not allow unless booking_type is 1 (Up to same-day booking with advance notice)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_DURATION_MAX(Priority.HIGH, "prior_notice_duration_max is not allow for booking_type 0 (Real time booking) or 2 (Up to prior day(s) booking)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_LAST_DAY(Priority.HIGH, "prior_notice_last_day is not allow for booking_type 2 (Up to prior day(s) booking)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_SERVICE_ID(Priority.HIGH, "prior_notice_service_id is not allow if prior_notice_start_day is not defined."),
FLEX_FORBIDDEN_PRIOR_NOTICE_START_DAY_FOR_BOOKING_TYPE(Priority.HIGH, "prior_notice_start_day is not allow for booking_type 0 (Real time booking)."),
FLEX_FORBIDDEN_PRIOR_NOTICE_START_DAY(Priority.HIGH, "prior_notice_start_day is not allow for booking_type 1 (Up to same-day booking with advance notice) if prior_notice_duration_max is defined."),
FLEX_FORBIDDEN_PRIOR_START_TIME(Priority.HIGH, "prior_notice_start_time is not allow if prior_notice_start_day is not defined."),
FLEX_FORBIDDEN_STOP_ID(Priority.HIGH, "stop_id is not allow if a location_group_id or location_id is defined."),
FLEX_FORBIDDEN_ROUTE_CONTINUOUS_DROP_OFF(Priority.HIGH, "continuous_drop_off is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined for any trip on this route."),
FLEX_FORBIDDEN_ROUTE_CONTINUOUS_PICKUP(Priority.HIGH, "continuous_pick_up is not allow when either start_pickup_drop_off_window or end_pickup_drop_off_window is defined for any trip on this route."),
FLEX_REQUIRED_END_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "end_pickup_drop_off_window is required if a location_group_id, location_id or start_pickup_drop_off_window is defined."),
FLEX_REQUIRED_PRIOR_NOTICE_DURATION_MIN(Priority.HIGH, "prior_notice_duration_min is required for booking_type 1 (Up to same-day booking with advance notice)."),
FLEX_REQUIRED_PRIOR_NOTICE_LAST_DAY(Priority.HIGH, "prior_notice_last_day is required if a stop_id refers to a location group or location."),
FLEX_REQUIRED_PRIOR_NOTICE_START_TIME(Priority.HIGH, "prior_notice_start_time is required if prior_notice_start_day is defined."),
FLEX_REQUIRED_STOP_ID(Priority.HIGH, "A stop_id is required if both location_group_id and location_id are not defined."),
FLEX_REQUIRED_START_PICKUP_DROP_OFF_WINDOW(Priority.HIGH, "start_pickup_drop_off_window is required if a location_group_id, location_id or end_pickup_drop_off_window is defined."),
FLEX_MISSING_FARE_RULE(Priority.HIGH, "A location zone_id must reference a fare rule (contains_id, destination_id or origin_id)."),
FLOATING_FORMAT(Priority.MEDIUM, "Incorrect floating point number format."),
FREQUENCY_PERIOD_OVERLAP(Priority.MEDIUM, "A frequency for a trip overlaps with another frequency defined for the same trip."),
GEO_JSON_PARSING(Priority.HIGH, "Unable to parse the locations.geojson file. Make sure the file conforms to the GeoJSON standard and supported geometry types are used."),
Expand Down
Loading

0 comments on commit cf15ca1

Please sign in to comment.