From 9efc8feb6929d99f73da48a78671cb5f15d15663 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Tue, 20 Aug 2024 14:50:51 +0100 Subject: [PATCH 01/18] refactor(Update to include fares v2 data manager refs and tests): --- pom.xml | 4 +- .../datatools/manager/DataManager.java | 10 + .../validation/FaresV2ValidationTest.java | 98 ++ .../gtfs/fake-agency-with-fares-v2/agency.txt | 2 + .../gtfs/fake-agency-with-fares-v2/areas.txt | 40 + .../fake-agency-with-fares-v2/calendar.txt | 2 + .../calendar_dates.txt | 3 + .../fare_leg_rules.txt | 697 ++++++++++++++ .../fake-agency-with-fares-v2/fare_media.txt | 5 + .../fare_products.txt | 97 ++ .../fare_transfer_rules.txt | 38 + .../fake-agency-with-fares-v2/feed_info.txt | 2 + .../fake-agency-with-fares-v2/networks.txt | 2 + .../route_networks.txt | 2 + .../gtfs/fake-agency-with-fares-v2/routes.txt | 2 + .../gtfs/fake-agency-with-fares-v2/shapes.txt | 8 + .../fake-agency-with-fares-v2/stop_areas.txt | 848 ++++++++++++++++++ .../fake-agency-with-fares-v2/stop_times.txt | 7 + .../gtfs/fake-agency-with-fares-v2/stops.txt | 5 + .../fake-agency-with-fares-v2/timeframes.txt | 8 + .../gtfs/fake-agency-with-fares-v2/trips.txt | 4 + 21 files changed, 1882 insertions(+), 2 deletions(-) create mode 100644 src/test/java/com/conveyal/datatools/manager/jobs/validation/FaresV2ValidationTest.java create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/agency.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/areas.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar_dates.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_leg_rules.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_media.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_products.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_transfer_rules.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/feed_info.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/networks.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/route_networks.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/routes.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/shapes.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_areas.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_times.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stops.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/timeframes.txt create mode 100644 src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/trips.txt diff --git a/pom.xml b/pom.xml index 9c412d876..726d5ff79 100644 --- a/pom.xml +++ b/pom.xml @@ -262,7 +262,7 @@ org.mobilitydata.gtfs-validator gtfs-validator-main - 4.2.0 + 5.0.0 - a8a376c82b + 5dd609bfb5 diff --git a/src/main/java/com/conveyal/datatools/manager/DataManager.java b/src/main/java/com/conveyal/datatools/manager/DataManager.java index ed3031ea2..6738a3ae6 100644 --- a/src/main/java/com/conveyal/datatools/manager/DataManager.java +++ b/src/main/java/com/conveyal/datatools/manager/DataManager.java @@ -204,19 +204,29 @@ static void registerRoutes() throws IOException { SnapshotController.register(EDITOR_API_PREFIX); EditorLockController.register(EDITOR_API_PREFIX); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.AREAS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.AGENCY, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.ATTRIBUTIONS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.CALENDAR, DataManager.GTFS_DATA_SOURCE); // NOTE: fare_attributes controller handles updates to nested table fare_rules. new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_ATTRIBUTES, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_LEG_RULES, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_MEDIAS, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_PRODUCTS, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.FARE_TRANSFER_RULES, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.FEED_INFO, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.NETWORKS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.ROUTES, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.ROUTE_NETWORKS, DataManager.GTFS_DATA_SOURCE); // NOTE: Patterns controller handles updates to nested tables shapes, pattern stops, and frequencies. new EditorControllerImpl(EDITOR_API_PREFIX, Table.PATTERNS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.SCHEDULE_EXCEPTIONS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.STOPS, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.STOP_AREAS, DataManager.GTFS_DATA_SOURCE); + new EditorControllerImpl(EDITOR_API_PREFIX, Table.TIME_FRAMES, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.TRANSLATIONS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.TRIPS, DataManager.GTFS_DATA_SOURCE); + // TODO: Add transfers.txt controller? } diff --git a/src/test/java/com/conveyal/datatools/manager/jobs/validation/FaresV2ValidationTest.java b/src/test/java/com/conveyal/datatools/manager/jobs/validation/FaresV2ValidationTest.java new file mode 100644 index 000000000..74094bfd5 --- /dev/null +++ b/src/test/java/com/conveyal/datatools/manager/jobs/validation/FaresV2ValidationTest.java @@ -0,0 +1,98 @@ +package com.conveyal.datatools.manager.jobs.validation; + +import com.conveyal.datatools.DatatoolsTest; +import com.conveyal.datatools.manager.auth.Auth0Connection; +import com.conveyal.datatools.manager.models.FeedSource; +import com.conveyal.datatools.manager.models.FeedVersion; +import com.conveyal.datatools.manager.models.Project; +import com.conveyal.datatools.manager.persistence.Persistence; +import org.bson.Document; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +import static com.conveyal.datatools.TestUtils.createFeedVersion; +import static com.conveyal.datatools.TestUtils.zipFolderFiles; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class FaresV2ValidationTest { + + private static Project project; + private static FeedVersion faresV2Version; + + @BeforeAll + public static void setUp() throws IOException { + // Start server if it isn't already running. + DatatoolsTest.setUp(); + Auth0Connection.setAuthDisabled(true); + // Create a project, feed sources, and feed versions to merge. + project = new Project(); + project.name = String.format("Test %s", new Date()); + Persistence.projects.create(project); + + FeedSource faresV2FeedSource = new FeedSource("fares-v2"); + faresV2FeedSource.projectId = project.id; + Persistence.feedSources.create(faresV2FeedSource); + faresV2Version = createFeedVersion( + faresV2FeedSource, + zipFolderFiles("fake-agency-with-fares-v2") + ); + Persistence.feedVersions.replace(faresV2Version.id, faresV2Version); + } + + @AfterAll + static void tearDown() { + Auth0Connection.setAuthDisabled(Auth0Connection.getDefaultAuthDisabled()); + project.delete(); + } + + @Test + void canValidateFareV2Files() { + Document summary = (Document) faresV2Version.mobilityDataResult.get("summary"); + List files = summary.getList("files", String.class); + assertTrue(files.contains("areas.txt")); + assertTrue(files.contains("fare_leg_rules.txt")); + assertTrue(files.contains("fare_media.txt")); + assertTrue(files.contains("fare_products.txt")); + assertTrue(files.contains("fare_transfer_rules.txt")); + assertTrue(files.contains("networks.txt")); + assertTrue(files.contains("route_networks.txt")); + assertTrue(files.contains("stop_areas.txt")); + assertTrue(files.contains("timeframes.txt")); + } + + /** + * This is not an exhaustive test, more of a sanity check that MobilityData can detect errors in fares v2 data. + * https://gtfs-validator.mobilitydata.org/rules.html + */ + @ParameterizedTest + @MethodSource("createValidationErrorChecks") + void canDetectValidationErrors(Set codes, String expectedCode) { + assertTrue(codes.contains(expectedCode)); + } + + private static Stream createValidationErrorChecks() { + ArrayList notices = (ArrayList) faresV2Version.mobilityDataResult.get("notices"); + Set codes = new HashSet<>(); + for (Document notice : notices) { + codes.add(notice.getString("code")); + } + return Stream.of( + Arguments.of(codes, "fare_transfer_rule_duration_limit_type_without_duration_limit"), + Arguments.of(codes, "fare_transfer_rule_duration_limit_without_type"), + Arguments.of(codes, "fare_transfer_rule_missing_transfer_count"), + Arguments.of(codes, "fare_transfer_rule_with_forbidden_transfer_count") + ); + } +} \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/agency.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/agency.txt new file mode 100644 index 000000000..5cb6afa42 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/agency.txt @@ -0,0 +1,2 @@ +agency_id,agency_name,agency_url,agency_lang,agency_phone,agency_email,agency_timezone,agency_fare_url,agency_branding_url +1,Fake Transit,http://www.fake-agency.com,,,,America/Los_Angeles,, diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/areas.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/areas.txt new file mode 100644 index 000000000..73b6734b6 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/areas.txt @@ -0,0 +1,40 @@ +area_id,area_name +area_bl,Blue Line +area_bl_airport,Blue Line - Airport Station +area_cf_zone_buzzards,CapeFLYER - Wareham/Buzzards Bay/Bourne +area_cf_zone_hyannis,CapeFLYER - Hyannis +area_commuter_rail_porter_zone_1a,Commuter Rail Zone 1A +area_commuter_rail_sumner_tunnel_zone_1a,Commuter Rail Zone 1A +area_commuter_rail_zone_1,Commuter Rail Zone 1 +area_commuter_rail_zone_10,Commuter Rail Zone 10 +area_commuter_rail_zone_1a,Commuter Rail Zone 1A +area_commuter_rail_zone_2,Commuter Rail Zone 2 +area_commuter_rail_zone_3,Commuter Rail Zone 3 +area_commuter_rail_zone_4,Commuter Rail Zone 4 +area_commuter_rail_zone_5,Commuter Rail Zone 5 +area_commuter_rail_zone_6,Commuter Rail Zone 6 +area_commuter_rail_zone_7,Commuter Rail Zone 7 +area_commuter_rail_zone_8,Commuter Rail Zone 8 +area_commuter_rail_zone_9,Commuter Rail Zone 9 +area_fairmount_line_zone_1a,Commuter Rail Zone 1A - Fairmount Line +area_gl_govt_ctr,Green Line - Government Center +area_green_b_west_of_kenmore,Green Line B - West of Kenmore +area_green_c_west_of_kenmore,Green Line C - West of Kenmore +area_green_e_west_of_symphony,Green Line E - West of Symphony +area_m_ashmont_mattapan,Mattapan Trolley - Ashmont and Mattapan +area_ol_state,Orange Line - State +area_red_south_station,Red Line - South Station +area_route_354_downtown,Route 354 - Downtown +area_route_354_outside_downtown,Route 354 - Outside Downtown +area_route_426_downtown,Route 426 - Downtown +area_route_426_outside_downtown,Route 426 - Outside Downtown +area_route_450_downtown,Route 450 - Downtown +area_route_450_outside_downtown,Route 450 - Outside Downtown +area_sl3_north_of_airport,Silver Line - North of Airport Station +area_sl_airport,Silver Line - Airport Station +area_sl_courthouse,Silver Line - Courthouse +area_sl_logan_terminal,Silver Line - Airport Terminals +area_sl_silver_line_way,Silver Line - Silver Line Way +area_sl_south_station,Silver Line - South Station +area_sl_world_trade_center,Silver Line - World Trade Center +area_ss_commuter_rail_zone_1a,Commuter Rail Zone 1A - South Station diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar.txt new file mode 100644 index 000000000..1bf13678e --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar.txt @@ -0,0 +1,2 @@ +service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date +04100312-8fe1-46a5-a9f2-556f39478f57,1,1,1,1,1,1,1,20170915,20170917 \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar_dates.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar_dates.txt new file mode 100644 index 000000000..5d0a31806 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/calendar_dates.txt @@ -0,0 +1,3 @@ +service_id,date,exception_type +04100312-8fe1-46a5-a9f2-556f39478f57,20170916,2 +calendar-date-service,20170917,1 \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_leg_rules.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_leg_rules.txt new file mode 100644 index 000000000..37b60d472 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_leg_rules.txt @@ -0,0 +1,697 @@ +leg_group_id,network_id,from_area_id,to_area_id,fare_product_id,from_timeframe_group_id,to_timeframe_group_id,transfer_only +leg_airport_rapid_transit_quick_subway,rapid_transit,area_bl_airport,,prod_rapid_transit_quick_subway,timeframe_regular,, +leg_cape_buzzards_hyannis_cash,cape_flyer,area_cf_zone_buzzards,area_cf_zone_hyannis,prod_cape_buzzards_hyannis_fare,,, +leg_cape_buzzards_hyannis_cash,cape_flyer,area_cf_zone_hyannis,area_cf_zone_buzzards,prod_cape_buzzards_hyannis_fare,,, +leg_cape_buzzards_hyannis_cash,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_8,prod_cape_buzzards_hyannis_fare,,, +leg_cape_buzzards_hyannis_cash,cape_flyer,area_commuter_rail_zone_8,area_cf_zone_hyannis,prod_cape_buzzards_hyannis_fare,,, +leg_cape_sbb_buzzards_cash,cape_flyer,area_cf_zone_buzzards,area_commuter_rail_zone_1a,prod_cape_sbb_buzzards_fare,,, +leg_cape_sbb_buzzards_cash,cape_flyer,area_cf_zone_buzzards,area_commuter_rail_zone_2,prod_cape_sbb_buzzards_fare,,, +leg_cape_sbb_buzzards_cash,cape_flyer,area_cf_zone_buzzards,area_commuter_rail_zone_4,prod_cape_sbb_buzzards_fare,,, +leg_cape_sbb_buzzards_cash,cape_flyer,area_commuter_rail_zone_1a,area_cf_zone_buzzards,prod_cape_sbb_buzzards_fare,,, +leg_cape_sbb_buzzards_cash,cape_flyer,area_commuter_rail_zone_2,area_cf_zone_buzzards,prod_cape_sbb_buzzards_fare,,, +leg_cape_sbb_buzzards_cash,cape_flyer,area_commuter_rail_zone_4,area_cf_zone_buzzards,prod_cape_sbb_buzzards_fare,,, +leg_cape_sbb_hyannis_cash,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_1a,prod_cape_sbb_hyannis_fare,,, +leg_cape_sbb_hyannis_cash,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_2,prod_cape_sbb_hyannis_fare,,, +leg_cape_sbb_hyannis_cash,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_4,prod_cape_sbb_hyannis_fare,,, +leg_cape_sbb_hyannis_cash,cape_flyer,area_commuter_rail_zone_1a,area_cf_zone_hyannis,prod_cape_sbb_hyannis_fare,,, +leg_cape_sbb_hyannis_cash,cape_flyer,area_commuter_rail_zone_2,area_cf_zone_hyannis,prod_cape_sbb_hyannis_fare,,, +leg_cape_sbb_hyannis_cash,cape_flyer,area_commuter_rail_zone_4,area_cf_zone_hyannis,prod_cape_sbb_hyannis_fare,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_sumner_tunnel_zone_1a,area_commuter_rail_sumner_tunnel_zone_1a,prod_cr_zone_1a,timeframe_sumner_tunnel_closure,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_sumner_tunnel_zone_1a,area_commuter_rail_zone_1a,prod_cr_zone_1a,timeframe_sumner_tunnel_closure,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_1,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_10,prod_cr_inter_10,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_1a,prod_cr_zone_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_2,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_3,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_4,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_5,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_6,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_7,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_8,prod_cr_inter_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_9,prod_cr_inter_9,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_fairmount_line_zone_1a,prod_cr_zone_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1,area_ss_commuter_rail_zone_1a,prod_cr_zone_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_1,prod_cr_inter_10,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_10,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_1a,prod_cr_zone_10,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_2,prod_cr_inter_9,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_3,prod_cr_inter_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_4,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_5,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_6,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_7,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_8,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_9,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_fairmount_line_zone_1a,prod_cr_zone_10,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_10,area_ss_commuter_rail_zone_1a,prod_cr_zone_10,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_sumner_tunnel_zone_1a,prod_cr_zone_1a,timeframe_sumner_tunnel_closure,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_1,prod_cr_zone_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_10,prod_cr_zone_10,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_1a,prod_cr_zone_1a,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_2,prod_cr_zone_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_3,prod_cr_zone_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_4,prod_cr_zone_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_5,prod_cr_zone_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_6,prod_cr_zone_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_7,prod_cr_zone_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_8,prod_cr_zone_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_9,prod_cr_zone_9,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_fairmount_line_zone_1a,prod_cr_zone_1a,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_1a,area_ss_commuter_rail_zone_1a,prod_cr_zone_1a,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_1,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_10,prod_cr_inter_9,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_1a,prod_cr_zone_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_2,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_3,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_4,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_5,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_6,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_7,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_8,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_9,prod_cr_inter_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_fairmount_line_zone_1a,prod_cr_zone_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_2,area_ss_commuter_rail_zone_1a,prod_cr_zone_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_1,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_10,prod_cr_inter_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_1a,prod_cr_zone_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_2,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_3,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_4,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_5,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_6,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_7,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_8,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_9,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_fairmount_line_zone_1a,prod_cr_zone_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_3,area_ss_commuter_rail_zone_1a,prod_cr_zone_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_1,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_10,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_1a,prod_cr_zone_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_2,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_3,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_4,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_5,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_6,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_7,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_8,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_9,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_fairmount_line_zone_1a,prod_cr_zone_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_4,area_ss_commuter_rail_zone_1a,prod_cr_zone_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_1,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_10,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_1a,prod_cr_zone_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_2,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_3,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_4,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_5,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_6,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_7,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_8,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_9,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_fairmount_line_zone_1a,prod_cr_zone_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_5,area_ss_commuter_rail_zone_1a,prod_cr_zone_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_1,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_10,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_1a,prod_cr_zone_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_2,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_3,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_4,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_5,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_6,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_7,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_8,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_9,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_fairmount_line_zone_1a,prod_cr_zone_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_6,area_ss_commuter_rail_zone_1a,prod_cr_zone_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_1,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_10,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_1a,prod_cr_zone_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_2,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_3,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_4,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_5,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_6,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_7,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_8,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_9,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_fairmount_line_zone_1a,prod_cr_zone_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_7,area_ss_commuter_rail_zone_1a,prod_cr_zone_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_1,prod_cr_inter_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_10,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_1a,prod_cr_zone_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_2,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_3,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_4,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_5,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_6,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_7,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_8,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_9,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_fairmount_line_zone_1a,prod_cr_zone_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_8,area_ss_commuter_rail_zone_1a,prod_cr_zone_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_1,prod_cr_inter_9,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_10,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_1a,prod_cr_zone_9,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_2,prod_cr_inter_8,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_3,prod_cr_inter_7,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_4,prod_cr_inter_6,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_5,prod_cr_inter_5,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_6,prod_cr_inter_4,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_7,prod_cr_inter_3,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_8,prod_cr_inter_2,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_9,prod_cr_inter_1,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_fairmount_line_zone_1a,prod_cr_zone_9,,, +leg_commuter_rail_cash,commuter_rail,area_commuter_rail_zone_9,area_ss_commuter_rail_zone_1a,prod_cr_zone_9,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_1,prod_cr_zone_1,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_10,prod_cr_zone_10,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_1a,prod_cr_zone_1a,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_2,prod_cr_zone_2,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_3,prod_cr_zone_3,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_4,prod_cr_zone_4,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_5,prod_cr_zone_5,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_6,prod_cr_zone_6,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_7,prod_cr_zone_7,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_8,prod_cr_zone_8,,, +leg_commuter_rail_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_9,prod_cr_zone_9,,, +leg_commuter_rail_free,commuter_rail,area_commuter_rail_porter_zone_1a,area_commuter_rail_zone_1a,prod_free_fare,timeframe_alewife_kendall_surge,, +leg_commuter_rail_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_porter_zone_1a,prod_free_fare,timeframe_alewife_kendall_surge,, +leg_express_bus_cash,express_bus,area_route_354_downtown,area_route_354_outside_downtown,prod_express_bus,,, +leg_express_bus_cash,express_bus,area_route_354_outside_downtown,area_route_354_downtown,prod_express_bus,,, +leg_express_bus_cash,express_bus,area_route_426_downtown,area_route_426_outside_downtown,prod_express_bus,,, +leg_express_bus_cash,express_bus,area_route_426_outside_downtown,area_route_426_downtown,prod_express_bus,,, +leg_express_bus_cash,express_bus,area_route_450_downtown,area_route_450_outside_downtown,prod_express_bus,,, +leg_express_bus_cash,express_bus,area_route_450_outside_downtown,area_route_450_downtown,prod_express_bus,,, +leg_express_bus_cash,express_bus_special,,,prod_express_bus,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_1,prod_cr_zone_1,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_10,prod_cr_zone_10,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_1a,prod_cr_zone_1a,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_2,prod_cr_zone_2,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_3,prod_cr_zone_3,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_4,prod_cr_zone_4,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_5,prod_cr_zone_5,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_6,prod_cr_zone_6,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_7,prod_cr_zone_7,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_8,prod_cr_zone_8,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_9,prod_cr_zone_9,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_fairmount_line_zone_1a,prod_cr_zone_1a,,, +leg_fairmount_line_cash,commuter_rail,area_fairmount_line_zone_1a,area_ss_commuter_rail_zone_1a,prod_cr_zone_1a,,, +leg_ferry_east_boston_free,ferry_east_boston,,,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_ferry_east_boston_free,ferry_east_boston,,,prod_boat_zone_1a,timeframe_regular,, +leg_ferry_f1_cash,ferry_f1,,,prod_ferry_f1,,, +leg_ferry_f4_cash,ferry_f4,,,prod_ferry_f4,,, +leg_ferry_f6_cash,ferry_f6,,,prod_boat_zone_1a,timeframe_sumner_tunnel_closure,, +leg_ferry_f6_cash,ferry_f6,,,prod_boat_zone_1,timeframe_regular,, +leg_ferry_lynn_cash,ferry_lynn,,,prod_boat_zone_1a,timeframe_sumner_tunnel_closure,, +leg_ferry_lynn_cash,ferry_lynn,,,prod_boat_zone_2,timeframe_regular,, +leg_foxboro_event_cash,cr_foxboro,,,prod_foxboro_event_fare,,, +leg_local_bus_cash,express_bus,area_route_354_downtown,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,express_bus,area_route_354_outside_downtown,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,express_bus,area_route_426_downtown,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,express_bus,area_route_426_outside_downtown,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,express_bus,area_route_450_downtown,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,express_bus,area_route_450_outside_downtown,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_downtown,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_downtown,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_downtown,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_downtown,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_downtown,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_downtown,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_downtown,,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_outside_downtown,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_outside_downtown,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_outside_downtown,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_outside_downtown,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_outside_downtown,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_outside_downtown,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_354_outside_downtown,,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_downtown,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_downtown,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_downtown,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_downtown,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_downtown,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_downtown,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_downtown,,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_outside_downtown,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_outside_downtown,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_outside_downtown,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_outside_downtown,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_outside_downtown,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_outside_downtown,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_426_outside_downtown,,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_downtown,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_downtown,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_downtown,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_downtown,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_downtown,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_downtown,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_downtown,,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_outside_downtown,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_outside_downtown,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_outside_downtown,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_outside_downtown,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_outside_downtown,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_outside_downtown,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,area_route_450_outside_downtown,,prod_local_bus,,, +leg_local_bus_cash,local_bus,,area_route_354_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,,area_route_354_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,,area_route_426_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,,area_route_426_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,,area_route_450_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,,area_route_450_outside_downtown,prod_local_bus,,, +leg_local_bus_cash,local_bus,,,prod_local_bus,,, +leg_local_bus_free,local_bus_free,area_route_354_downtown,area_route_354_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_downtown,area_route_426_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_downtown,area_route_450_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_downtown,,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_outside_downtown,area_route_354_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_outside_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_outside_downtown,area_route_426_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_outside_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_outside_downtown,area_route_450_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_outside_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_354_outside_downtown,,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_downtown,area_route_354_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_downtown,area_route_426_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_downtown,area_route_450_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_downtown,,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_outside_downtown,area_route_354_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_outside_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_outside_downtown,area_route_426_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_outside_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_outside_downtown,area_route_450_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_outside_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_426_outside_downtown,,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_downtown,area_route_354_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_downtown,area_route_426_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_downtown,area_route_450_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_downtown,,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_outside_downtown,area_route_354_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_outside_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_outside_downtown,area_route_426_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_outside_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_outside_downtown,area_route_450_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_outside_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,area_route_450_outside_downtown,,prod_free_fare,,, +leg_local_bus_free,local_bus_free,,area_route_354_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,,area_route_354_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,,area_route_426_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,,area_route_426_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,,area_route_450_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,,area_route_450_outside_downtown,prod_free_fare,,, +leg_local_bus_free,local_bus_free,,,prod_free_fare,,, +leg_local_bus_quick_subway,express_bus,area_route_354_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,express_bus,area_route_354_outside_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,express_bus,area_route_426_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,express_bus,area_route_426_outside_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,express_bus,area_route_450_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,express_bus,area_route_450_outside_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_downtown,,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_outside_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_outside_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_outside_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_outside_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_outside_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_outside_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_354_outside_downtown,,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_downtown,,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_outside_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_outside_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_outside_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_outside_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_outside_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_outside_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_426_outside_downtown,,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_downtown,,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_outside_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_outside_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_outside_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_outside_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_outside_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_outside_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,area_route_450_outside_downtown,,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,,area_route_354_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,,area_route_426_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,,area_route_450_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,, +leg_local_bus_quick_subway,local_bus,,,prod_rapid_transit_quick_subway,,, +leg_local_bus_restricted_cash,local_bus_restricted,,,prod_local_bus,,, +leg_mattapan_rapid_transit_cash,m_rapid_transit,,,prod_rapid_transit_cash,,, +leg_mattapan_rapid_transit_quick_subway,m_rapid_transit,area_m_ashmont_mattapan,,prod_rapid_transit_quick_subway,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_downtown,area_route_354_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_downtown,area_route_426_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_downtown,area_route_450_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_downtown,,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_outside_downtown,area_route_354_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_outside_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_outside_downtown,area_route_426_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_outside_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_outside_downtown,area_route_450_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_outside_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_354_outside_downtown,,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_downtown,area_route_354_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_downtown,area_route_426_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_downtown,area_route_450_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_downtown,,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_outside_downtown,area_route_354_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_outside_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_outside_downtown,area_route_426_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_outside_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_outside_downtown,area_route_450_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_outside_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_426_outside_downtown,,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_downtown,area_route_354_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_downtown,area_route_426_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_downtown,area_route_450_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_downtown,,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_outside_downtown,area_route_354_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_outside_downtown,area_route_354_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_outside_downtown,area_route_426_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_outside_downtown,area_route_426_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_outside_downtown,area_route_450_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_outside_downtown,area_route_450_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,area_route_450_outside_downtown,,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,,area_route_354_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,,area_route_354_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,,area_route_426_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,,area_route_426_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,,area_route_450_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,,area_route_450_outside_downtown,prod_free_fare,,, +leg_rail_replacement_free,rail_replacement_bus,,,prod_free_fare,,, +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_downtown,,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_outside_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_outside_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_outside_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_outside_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_outside_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_outside_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_354_outside_downtown,,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_downtown,,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_outside_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_outside_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_outside_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_outside_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_outside_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_outside_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_426_outside_downtown,,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_downtown,,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_outside_downtown,area_route_354_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_outside_downtown,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_outside_downtown,area_route_426_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_outside_downtown,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_outside_downtown,area_route_450_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_outside_downtown,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,area_route_450_outside_downtown,,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,,area_route_354_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,,area_route_354_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,,area_route_426_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,,area_route_426_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,,area_route_450_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,,area_route_450_outside_downtown,prod_rapid_transit_quick_subway,,,1 +leg_rail_replacement_quick_subway,rail_replacement_bus,,,prod_rapid_transit_quick_subway,,,1 +leg_rapid_transit_cash,rapid_transit,area_green_b_west_of_kenmore,,prod_rapid_transit_cash,,, +leg_rapid_transit_cash,rapid_transit,area_green_c_west_of_kenmore,,prod_rapid_transit_cash,,, +leg_rapid_transit_cash,rapid_transit,area_green_e_west_of_symphony,,prod_rapid_transit_cash,,, +leg_rapid_transit_cash,rapid_transit,,,prod_rapid_transit_cash,,,1 +leg_rapid_transit_free,rapid_transit,area_bl,,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_rapid_transit_free,rapid_transit,area_bl_airport,,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_rapid_transit_free,rapid_transit,area_gl_govt_ctr,,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_rapid_transit_free,rapid_transit,area_ol_state,,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_rapid_transit_free,rapid_transit,,,prod_free_fare,,,1 +leg_rapid_transit_quick_subway,rapid_transit,area_bl,,prod_rapid_transit_quick_subway,timeframe_regular,, +leg_rapid_transit_quick_subway,rapid_transit,area_gl_govt_ctr,,prod_rapid_transit_quick_subway,timeframe_regular,, +leg_rapid_transit_quick_subway,rapid_transit,area_ol_state,,prod_rapid_transit_quick_subway,timeframe_regular,, +leg_rapid_transit_quick_subway,rapid_transit,,,prod_rapid_transit_quick_subway,timeframe_regular,, +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl3_north_of_airport,area_sl3_north_of_airport,prod_rapid_transit_cash,timeframe_regular,, +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl3_north_of_airport,area_sl_airport,prod_rapid_transit_cash,timeframe_regular,, +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl3_north_of_airport,,prod_rapid_transit_cash,timeframe_regular,, +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl_silver_line_way,area_sl3_north_of_airport,prod_rapid_transit_cash,timeframe_regular,, +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl_silver_line_way,area_sl_airport,prod_rapid_transit_cash,timeframe_regular,, +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl_silver_line_way,,prod_rapid_transit_cash,,, +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl_south_station,area_sl3_north_of_airport,prod_rapid_transit_cash,,,1 +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl_south_station,area_sl_airport,prod_rapid_transit_cash,,,1 +leg_sl_rapid_transit_cash,sl_rapid_transit,area_sl_south_station,,prod_rapid_transit_cash,,,1 +leg_sl_rapid_transit_cash,sl_rapid_transit,,,prod_rapid_transit_cash,,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl3_north_of_airport,area_sl3_north_of_airport,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl3_north_of_airport,area_sl_airport,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl3_north_of_airport,,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl_airport,area_sl3_north_of_airport,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl_airport,,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl_logan_terminal,,prod_free_fare,,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl_silver_line_way,area_sl3_north_of_airport,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_sl_rapid_transit_free,sl_rapid_transit,area_sl_silver_line_way,area_sl_airport,prod_free_fare,timeframe_sumner_tunnel_closure,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_airport,area_sl3_north_of_airport,prod_rapid_transit_quick_subway,timeframe_regular,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_airport,,prod_rapid_transit_quick_subway,timeframe_regular,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_courthouse,area_sl3_north_of_airport,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_courthouse,area_sl_airport,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_courthouse,,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_south_station,area_sl3_north_of_airport,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_south_station,area_sl_airport,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_south_station,,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_world_trade_center,area_sl3_north_of_airport,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_world_trade_center,area_sl_airport,prod_rapid_transit_quick_subway,,, +leg_sl_rapid_transit_quick_subway,sl_rapid_transit,area_sl_world_trade_center,,prod_rapid_transit_quick_subway,,, +leg_ss_fairmount_line_zone_1a_cash,commuter_rail,area_ss_commuter_rail_zone_1a,area_fairmount_line_zone_1a,prod_cr_zone_1a,,, +leg_ss_rapid_transit_cash,rapid_transit,area_red_south_station,,prod_rapid_transit_cash,,,1 +leg_ss_rapid_transit_free,rapid_transit,area_red_south_station,,prod_free_fare,,,1 +leg_ss_rapid_transit_quick_subway,rapid_transit,area_red_south_station,,prod_rapid_transit_quick_subway,,, +leg_systemwide_free,cape_flyer,area_cf_zone_buzzards,area_cf_zone_hyannis,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_buzzards,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_buzzards,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_buzzards,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_hyannis,area_cf_zone_buzzards,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_cf_zone_hyannis,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_commuter_rail_zone_1a,area_cf_zone_buzzards,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_commuter_rail_zone_1a,area_cf_zone_hyannis,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_commuter_rail_zone_2,area_cf_zone_buzzards,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_commuter_rail_zone_2,area_cf_zone_hyannis,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_commuter_rail_zone_4,area_cf_zone_buzzards,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_commuter_rail_zone_4,area_cf_zone_hyannis,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cape_flyer,area_commuter_rail_zone_8,area_cf_zone_hyannis,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_10,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_1a,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_2,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_3,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_4,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_5,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_6,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_7,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_8,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_commuter_rail_zone_9,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_fairmount_line_zone_1a,area_ss_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_1,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_10,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_2,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_3,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_4,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_5,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_6,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_7,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_8,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_commuter_rail_zone_9,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,commuter_rail,area_ss_commuter_rail_zone_1a,area_fairmount_line_zone_1a,prod_free_fare,timeframe_systemwide_free,, +leg_systemwide_free,cr_foxboro,,,prod_free_fare,timeframe_systemwide_free,, diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_media.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_media.txt new file mode 100644 index 000000000..a695de634 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_media.txt @@ -0,0 +1,5 @@ +fare_media_id,fare_media_name,fare_media_type +cash,Cash,0 +credit_debit,Credit/debit card,0 +charlieticket,CharlieTicket,1 +mticket,mTicket app,4 diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_products.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_products.txt new file mode 100644 index 000000000..1138f4591 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_products.txt @@ -0,0 +1,97 @@ +fare_product_id,fare_product_name,fare_media_id,amount,currency +prod_boat_zone_1,Ferry Zone 1 one-way fare,cash,6.50,USD +prod_boat_zone_1,Ferry Zone 1 one-way fare,credit_debit,6.50,USD +prod_boat_zone_1,Ferry Zone 1 one-way fare,mticket,6.50,USD +prod_boat_zone_1a,Ferry Zone 1A one-way fare,cash,2.40,USD +prod_boat_zone_1a,Ferry Zone 1A one-way fare,credit_debit,2.40,USD +prod_boat_zone_1a,Ferry Zone 1A one-way fare,mticket,2.40,USD +prod_boat_zone_2,Ferry Zone 2 one-way fare,cash,7.00,USD +prod_boat_zone_2,Ferry Zone 2 one-way fare,credit_debit,7.00,USD +prod_boat_zone_2,Ferry Zone 2 one-way fare,mticket,7.00,USD +prod_cape_buzzards_hyannis_fare,CapeFLYER Middleborough/Lakeville one-way fare,cash,5.00,USD +prod_cape_buzzards_hyannis_fare,CapeFLYER Middleborough/Lakeville one-way fare,credit_debit,5.00,USD +prod_cape_buzzards_hyannis_fare,CapeFLYER Middleborough/Lakeville one-way fare,mticket,5.00,USD +prod_cape_sbb_buzzards_fare,CapeFLYER Bourne one-way fare,cash,20.00,USD +prod_cape_sbb_buzzards_fare,CapeFLYER Bourne one-way fare,credit_debit,20.00,USD +prod_cape_sbb_buzzards_fare,CapeFLYER Bourne one-way fare,mticket,20.00,USD +prod_cape_sbb_hyannis_fare,CapeFLYER Hyannis one-way fare,cash,22.00,USD +prod_cape_sbb_hyannis_fare,CapeFLYER Hyannis one-way fare,credit_debit,22.00,USD +prod_cape_sbb_hyannis_fare,CapeFLYER Hyannis one-way fare,mticket,22.00,USD +prod_cr_inter_1,Commuter Rail Interzone 1 one-way fare,cash,2.75,USD +prod_cr_inter_1,Commuter Rail Interzone 1 one-way fare,credit_debit,2.75,USD +prod_cr_inter_1,Commuter Rail Interzone 1 one-way fare,mticket,2.75,USD +prod_cr_inter_10,Commuter Rail Interzone 10 one-way fare,cash,7.25,USD +prod_cr_inter_10,Commuter Rail Interzone 10 one-way fare,credit_debit,7.25,USD +prod_cr_inter_10,Commuter Rail Interzone 10 one-way fare,mticket,7.25,USD +prod_cr_inter_2,Commuter Rail Interzone 2 one-way fare,cash,3.25,USD +prod_cr_inter_2,Commuter Rail Interzone 2 one-way fare,credit_debit,3.25,USD +prod_cr_inter_2,Commuter Rail Interzone 2 one-way fare,mticket,3.25,USD +prod_cr_inter_3,Commuter Rail Interzone 3 one-way fare,cash,3.50,USD +prod_cr_inter_3,Commuter Rail Interzone 3 one-way fare,credit_debit,3.50,USD +prod_cr_inter_3,Commuter Rail Interzone 3 one-way fare,mticket,3.50,USD +prod_cr_inter_4,Commuter Rail Interzone 4 one-way fare,cash,4.25,USD +prod_cr_inter_4,Commuter Rail Interzone 4 one-way fare,credit_debit,4.25,USD +prod_cr_inter_4,Commuter Rail Interzone 4 one-way fare,mticket,4.25,USD +prod_cr_inter_5,Commuter Rail Interzone 5 one-way fare,cash,4.75,USD +prod_cr_inter_5,Commuter Rail Interzone 5 one-way fare,credit_debit,4.75,USD +prod_cr_inter_5,Commuter Rail Interzone 5 one-way fare,mticket,4.75,USD +prod_cr_inter_6,Commuter Rail Interzone 6 one-way fare,cash,5.25,USD +prod_cr_inter_6,Commuter Rail Interzone 6 one-way fare,credit_debit,5.25,USD +prod_cr_inter_6,Commuter Rail Interzone 6 one-way fare,mticket,5.25,USD +prod_cr_inter_7,Commuter Rail Interzone 7 one-way fare,cash,5.75,USD +prod_cr_inter_7,Commuter Rail Interzone 7 one-way fare,credit_debit,5.75,USD +prod_cr_inter_7,Commuter Rail Interzone 7 one-way fare,mticket,5.75,USD +prod_cr_inter_8,Commuter Rail Interzone 8 one-way fare,cash,6.25,USD +prod_cr_inter_8,Commuter Rail Interzone 8 one-way fare,credit_debit,6.25,USD +prod_cr_inter_8,Commuter Rail Interzone 8 one-way fare,mticket,6.25,USD +prod_cr_inter_9,Commuter Rail Interzone 9 one-way fare,cash,6.75,USD +prod_cr_inter_9,Commuter Rail Interzone 9 one-way fare,credit_debit,6.75,USD +prod_cr_inter_9,Commuter Rail Interzone 9 one-way fare,mticket,6.75,USD +prod_cr_zone_1,Commuter Rail Zone 1 one-way fare,cash,6.50,USD +prod_cr_zone_1,Commuter Rail Zone 1 one-way fare,credit_debit,6.50,USD +prod_cr_zone_1,Commuter Rail Zone 1 one-way fare,mticket,6.50,USD +prod_cr_zone_10,Commuter Rail Zone 10 one-way fare,cash,13.25,USD +prod_cr_zone_10,Commuter Rail Zone 10 one-way fare,credit_debit,13.25,USD +prod_cr_zone_10,Commuter Rail Zone 10 one-way fare,mticket,13.25,USD +prod_cr_zone_1a,Commuter Rail Zone 1A one-way fare,cash,2.40,USD +prod_cr_zone_1a,Commuter Rail Zone 1A one-way fare,credit_debit,2.40,USD +prod_cr_zone_1a,Commuter Rail Zone 1A one-way fare,mticket,2.40,USD +prod_cr_zone_2,Commuter Rail Zone 2 one-way fare,cash,7.00,USD +prod_cr_zone_2,Commuter Rail Zone 2 one-way fare,credit_debit,7.00,USD +prod_cr_zone_2,Commuter Rail Zone 2 one-way fare,mticket,7.00,USD +prod_cr_zone_3,Commuter Rail Zone 3 one-way fare,cash,8.00,USD +prod_cr_zone_3,Commuter Rail Zone 3 one-way fare,credit_debit,8.00,USD +prod_cr_zone_3,Commuter Rail Zone 3 one-way fare,mticket,8.00,USD +prod_cr_zone_4,Commuter Rail Zone 4 one-way fare,cash,8.75,USD +prod_cr_zone_4,Commuter Rail Zone 4 one-way fare,credit_debit,8.75,USD +prod_cr_zone_4,Commuter Rail Zone 4 one-way fare,mticket,8.75,USD +prod_cr_zone_5,Commuter Rail Zone 5 one-way fare,cash,9.75,USD +prod_cr_zone_5,Commuter Rail Zone 5 one-way fare,credit_debit,9.75,USD +prod_cr_zone_5,Commuter Rail Zone 5 one-way fare,mticket,9.75,USD +prod_cr_zone_6,Commuter Rail Zone 6 one-way fare,cash,10.50,USD +prod_cr_zone_6,Commuter Rail Zone 6 one-way fare,credit_debit,10.50,USD +prod_cr_zone_6,Commuter Rail Zone 6 one-way fare,mticket,10.50,USD +prod_cr_zone_7,Commuter Rail Zone 7 one-way fare,cash,11.00,USD +prod_cr_zone_7,Commuter Rail Zone 7 one-way fare,credit_debit,11.00,USD +prod_cr_zone_7,Commuter Rail Zone 7 one-way fare,mticket,11.00,USD +prod_cr_zone_8,Commuter Rail Zone 8 one-way fare,cash,12.25,USD +prod_cr_zone_8,Commuter Rail Zone 8 one-way fare,credit_debit,12.25,USD +prod_cr_zone_8,Commuter Rail Zone 8 one-way fare,mticket,12.25,USD +prod_cr_zone_9,Commuter Rail Zone 9 one-way fare,cash,12.75,USD +prod_cr_zone_9,Commuter Rail Zone 9 one-way fare,credit_debit,12.75,USD +prod_cr_zone_9,Commuter Rail Zone 9 one-way fare,mticket,12.75,USD +prod_express_bus,Express Bus cash fare,cash,4.25,USD +prod_ferry_east_boston,East Boston Ferry one-way fare,mticket,2.40,USD +prod_ferry_f1,Hingham/Hull Ferry one-way fare,cash,9.75,USD +prod_ferry_f1,Hingham/Hull Ferry one-way fare,credit_debit,9.75,USD +prod_ferry_f1,Hingham/Hull Ferry one-way fare,mticket,9.75,USD +prod_ferry_f4,Charlestown Ferry one-way fare,cash,3.70,USD +prod_ferry_f4,Charlestown Ferry one-way fare,credit_debit,3.70,USD +prod_ferry_f4,Charlestown Ferry one-way fare,mticket,3.70,USD +prod_foxboro_event_fare,Foxboro Event Service round-trip fare,cash,20.00,USD +prod_foxboro_event_fare,Foxboro Event Service round-trip fare,credit_debit,20.00,USD +prod_foxboro_event_fare,Foxboro Event Service round-trip fare,mticket,20.00,USD +prod_free_fare,Free fare,,0.00,USD +prod_local_bus,Local Bus cash fare,cash,1.70,USD +prod_rapid_transit_cash,Subway cash fare,cash,2.40,USD +prod_rapid_transit_quick_subway,Subway Quick Ticket,charlieticket,2.40,USD diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_transfer_rules.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_transfer_rules.txt new file mode 100644 index 000000000..bccb48b0f --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/fare_transfer_rules.txt @@ -0,0 +1,38 @@ +from_leg_group_id,to_leg_group_id,transfer_count,duration_limit,duration_limit_type,fare_transfer_type,fare_product_id,filter_fare_product_id,fare_media_behavior,fare_product_behavior +leg_airport_rapid_transit_quick_subway,leg_local_bus_quick_subway,99,7200,1,0,prod_rapid_transit_quick_subway,prod_rapid_transit_quick_subway,0,1 +leg_airport_rapid_transit_quick_subway,leg_rapid_transit_quick_subway,,,1,0,prod_rapid_transit_quick_subway,prod_rapid_transit_quick_subway,0,1 +leg_mattapan_rapid_transit_quick_subway,leg_local_bus_quick_subway,,7200,1,0,prod_rapid_transit_quick_subway,prod_rapid_transit_quick_subway,0,1 +leg_mattapan_rapid_transit_quick_subway,leg_rail_replacement_quick_subway,,99,,0,,prod_rapid_transit_quick_subway,0,1 +leg_mattapan_rapid_transit_quick_subway,leg_rapid_transit_quick_subway,99999,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_mattapan_rapid_transit_quick_subway,leg_mattapan_rapid_transit_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_rail_replacement_quick_subway,leg_airport_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rail_replacement_quick_subway,leg_local_bus_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_rail_replacement_quick_subway,leg_mattapan_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rail_replacement_quick_subway,leg_rail_replacement_quick_subway,-1,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rail_replacement_quick_subway,leg_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rail_replacement_quick_subway,leg_sl_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rail_replacement_quick_subway,leg_ss_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rapid_transit_cash,leg_rapid_transit_cash,-1,,,0,,prod_rapid_transit_cash,0,1 +leg_rapid_transit_cash,leg_sl_rapid_transit_cash,,,,0,,prod_rapid_transit_cash,0,1 +leg_rapid_transit_free,leg_rapid_transit_free,-1,,,0,,prod_free_fare,0,1 +leg_rapid_transit_free,leg_sl_rapid_transit_free,,,,0,,prod_free_fare,0,1 +leg_rapid_transit_quick_subway,leg_airport_rapid_transit_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_rapid_transit_quick_subway,leg_local_bus_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_rapid_transit_quick_subway,leg_mattapan_rapid_transit_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_rapid_transit_quick_subway,leg_rail_replacement_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rapid_transit_quick_subway,leg_rapid_transit_quick_subway,-1,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rapid_transit_quick_subway,leg_sl_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_rapid_transit_quick_subway,leg_ss_rapid_transit_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_sl_rapid_transit_cash,leg_ss_rapid_transit_cash,,,,0,,prod_rapid_transit_cash,0,1 +leg_sl_rapid_transit_free,leg_ss_rapid_transit_free,,,,0,,prod_free_fare,0,1 +leg_sl_rapid_transit_quick_subway,leg_airport_rapid_transit_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_sl_rapid_transit_quick_subway,leg_local_bus_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_sl_rapid_transit_quick_subway,leg_mattapan_rapid_transit_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_sl_rapid_transit_quick_subway,leg_rail_replacement_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_sl_rapid_transit_quick_subway,leg_ss_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_ss_rapid_transit_cash,leg_rapid_transit_cash,,,,0,,prod_rapid_transit_cash,0,1 +leg_ss_rapid_transit_free,leg_rapid_transit_free,,,,0,,prod_free_fare,0,1 +leg_ss_rapid_transit_quick_subway,leg_local_bus_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_ss_rapid_transit_quick_subway,leg_mattapan_rapid_transit_quick_subway,,7200,1,0,,prod_rapid_transit_quick_subway,0,1 +leg_ss_rapid_transit_quick_subway,leg_rail_replacement_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 +leg_ss_rapid_transit_quick_subway,leg_rapid_transit_quick_subway,,,,0,,prod_rapid_transit_quick_subway,0,1 diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/feed_info.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/feed_info.txt new file mode 100644 index 000000000..ceac60810 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/feed_info.txt @@ -0,0 +1,2 @@ +feed_id,feed_publisher_name,feed_publisher_url,feed_lang,feed_version +fake_transit,Conveyal,http://www.conveyal.com,en,1.0 \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/networks.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/networks.txt new file mode 100644 index 000000000..47a67eaad --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/networks.txt @@ -0,0 +1,2 @@ +network_id,network_name +1,Forbidden because network id is defined in routes \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/route_networks.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/route_networks.txt new file mode 100644 index 000000000..d2f8f9a9d --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/route_networks.txt @@ -0,0 +1,2 @@ +network_id,route_id +1,1 \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/routes.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/routes.txt new file mode 100644 index 000000000..dd6a30eaf --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/routes.txt @@ -0,0 +1,2 @@ +route_id,agency_id,route_short_name,route_long_name,route_desc,route_type,route_url,route_color,route_text_color,route_sort_order,route_fare_class,line_id,listed_route,network_id +1,1,,RL,RT,1,https://www.mbta.com/schedules/Red,DA291C,FFFFFF,10010,Rapid Transit,line-Red,,rapid_transit \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/shapes.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/shapes.txt new file mode 100644 index 000000000..3f2e3fd13 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/shapes.txt @@ -0,0 +1,8 @@ +shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence,shape_dist_traveled +5820f377-f947-4728-ac29-ac0102cbc34e,37.0612132,-122.0074332,1,0.0000000 +5820f377-f947-4728-ac29-ac0102cbc34e,37.0611720,-122.0075000,2,7.4997067 +5820f377-f947-4728-ac29-ac0102cbc34e,37.0613590,-122.0076830,3,33.8739075 +5820f377-f947-4728-ac29-ac0102cbc34e,37.0608780,-122.0082780,4,109.0402932 +5820f377-f947-4728-ac29-ac0102cbc34e,37.0603590,-122.0088280,5,184.6078298 +5820f377-f947-4728-ac29-ac0102cbc34e,37.0597610,-122.0093540,6,265.8053023 +5820f377-f947-4728-ac29-ac0102cbc34e,37.0590660,-122.0099190,7,357.8617018 diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_areas.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_areas.txt new file mode 100644 index 000000000..85cbda304 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_areas.txt @@ -0,0 +1,848 @@ +stop_id,area_id +4u6g,area_route_426_downtown +4u6g,area_route_450_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_sl_logan_terminal +4u6g,area_sl_logan_terminal +4u6g,area_sl_logan_terminal +4u6g,area_sl_logan_terminal +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_sl_logan_terminal +4u6g,area_route_426_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_downtown +4u6g,area_route_354_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_ol_state +4u6g,area_ol_state +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl_airport +4u6g,area_bl_airport +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_bl +4u6g,area_red_south_station +4u6g,area_red_south_station +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_green_b_west_of_kenmore +4u6g,area_gl_govt_ctr +4u6g,area_gl_govt_ctr +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_c_west_of_kenmore +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_green_e_west_of_symphony +4u6g,area_m_ashmont_mattapan +4u6g,area_m_ashmont_mattapan +4u6g,area_m_ashmont_mattapan +4u6g,area_bl +4u6g,area_sl_airport +4u6g,area_sl_airport +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_450_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_route_426_outside_downtown +4u6g,area_sl_south_station +4u6g,area_sl_courthouse +4u6g,area_sl_world_trade_center +4u6g,area_sl_silver_line_way +4u6g,area_sl_world_trade_center +4u6g,area_sl_courthouse +4u6g,area_sl_south_station +4u6g,area_sl_silver_line_way +4u6g,area_sl3_north_of_airport +4u6g,area_sl3_north_of_airport +4u6g,area_sl3_north_of_airport +4u6g,area_sl3_north_of_airport +4u6g,area_sl3_north_of_airport +4u6g,area_sl3_north_of_airport +4u6g,area_sl3_north_of_airport +4u6g,area_sl3_north_of_airport +4u6g,area_route_426_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_route_426_downtown +4u6g,area_route_450_downtown +4u6g,area_route_354_outside_downtown +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_cf_zone_buzzards +4u6g,area_cf_zone_buzzards +4u6g,area_cf_zone_buzzards +4u6g,area_cf_zone_hyannis +4u6g,area_commuter_rail_zone_2 +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_fairmount_line_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_porter_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_porter_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_porter_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_sumner_tunnel_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_10 +4u6g,area_commuter_rail_zone_9 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_ss_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_8 +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1a +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_1 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_2 +4u6g,area_commuter_rail_zone_3 +4u6g,area_commuter_rail_zone_4 +4u6g,area_commuter_rail_zone_5 +4u6g,area_commuter_rail_zone_6 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 +4u6g,area_commuter_rail_zone_7 \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_times.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_times.txt new file mode 100644 index 000000000..1cfefaa49 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stop_times.txt @@ -0,0 +1,7 @@ +trip_id,arrival_time,departure_time,stop_id,stop_sequence,stop_headsign,pickup_type,drop_off_type,shape_dist_traveled,timepoint +a30277f8-e50a-4a85-9141-b1e0da9d429d,07:00:00,07:00:00,4u6g,1,Test stop headsign,0,0,0.0000000, +a30277f8-e50a-4a85-9141-b1e0da9d429d,07:01:00,07:01:00,johv,2,Test stop headsign 2,0,0,341.4491961, +frequency-trip,08:00:00,08:00:00,4u6g,1,Test stop headsign frequency trip,0,0,0.0000000, +frequency-trip,08:29:00,08:29:00,1234,2,Test stop headsign frequency trip 2,0,0,341.4491961, +calendar-date-trip,08:00:00,08:00:00,4u6g,1,Test stop headsign calendar date trip,0,0,0.0000000, +calendar-date-trip,08:29:00,08:29:00,1234,2,Test stop headsign calendar date trip 2,0,0,341.4491961, \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stops.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stops.txt new file mode 100644 index 000000000..ba368047e --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/stops.txt @@ -0,0 +1,5 @@ +stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,zone_id,stop_url,location_type,parent_station,stop_timezone,wheelchair_boarding +4u6g,,Butler Ln,,37.0612132,-122.0074332,,,0,,, +johv,,Scotts Valley Dr & Victor Sq,,37.0590172,-122.0096058,,,0,,, +123,,Parent Station,,37.0666,-122.0777,,,1,,, +1234,,Child Stop,,37.06662,-122.07772,,,0,123,, \ No newline at end of file diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/timeframes.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/timeframes.txt new file mode 100644 index 000000000..52667abe1 --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/timeframes.txt @@ -0,0 +1,8 @@ +timeframe_group_id,start_time,end_time,service_id +timeframe_regular,,,04100312-8fe1-46a5-a9f2-556f39478f57 +timeframe_systemwide_free,,,04100312-8fe1-46a5-a9f2-556f39478f57 +timeframe_sumner_tunnel_closure,,,04100312-8fe1-46a5-a9f2-556f39478f57 +timeframe_sumner_tunnel_closure,00:00:00,02:30:00,04100312-8fe1-46a5-a9f2-556f39478f57 +timeframe_regular,02:30:00,24:00:00,04100312-8fe1-46a5-a9f2-556f39478f57 +timeframe_alewife_kendall_surge,,,04100312-8fe1-46a5-a9f2-556f39478f57 +timeframe_alewife_kendall_surge,00:00:00,02:30:00,04100312-8fe1-46a5-a9f2-556f39478f57 diff --git a/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/trips.txt b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/trips.txt new file mode 100644 index 000000000..982c01e0f --- /dev/null +++ b/src/test/resources/com/conveyal/datatools/gtfs/fake-agency-with-fares-v2/trips.txt @@ -0,0 +1,4 @@ +route_id,trip_id,trip_headsign,trip_short_name,direction_id,block_id,shape_id,bikes_allowed,wheelchair_accessible,service_id +1,a30277f8-e50a-4a85-9141-b1e0da9d429d,,,0,,5820f377-f947-4728-ac29-ac0102cbc34e,0,0,04100312-8fe1-46a5-a9f2-556f39478f57 +1,frequency-trip,,,0,,5820f377-f947-4728-ac29-ac0102cbc34e,0,0,04100312-8fe1-46a5-a9f2-556f39478f57 +1,calendar-date-trip,,,0,,5820f377-f947-4728-ac29-ac0102cbc34e,0,0,calendar-date-service \ No newline at end of file From 8e42038f766d7fbb9db192f21540525cc5794375 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Fri, 18 Oct 2024 07:44:40 +0100 Subject: [PATCH 02/18] refactor(Bumped GTFS-Lib version): --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 726d5ff79..3e4eab144 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 5dd609bfb5 + 1d95cf5dc5eb2907ccf2abd4ede5b55963807195 From 468a586cbcdedcd093620d0abcb7f98515d4b5d5 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Tue, 28 Jan 2025 10:49:20 +0000 Subject: [PATCH 03/18] improvement(pom.xml): Bumped GTFS-lib version to lastest fares v2 dev work --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 87c8bebed..cf4021b24 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 1d95cf5dc5eb2907ccf2abd4ede5b55963807195 + fbf52822497ff58f572ea96c2d1fc26b8a4a9c7e From 8f0474f1e83d9b5590ffbbf4ad89b8d9841ee386 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Fri, 31 Jan 2025 15:54:47 +0000 Subject: [PATCH 04/18] improvement(pom.xml): Bumped GTFS lib version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index cf4021b24..2df4c33d9 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - fbf52822497ff58f572ea96c2d1fc26b8a4a9c7e + 62a7ed2efba69abfdf9bd08db03f3fe029e2b0a8 From b4deec9ebd369b41e64a7c346eb2dfad1c266d2e Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Wed, 5 Feb 2025 14:01:53 +0000 Subject: [PATCH 05/18] improvement(pom.xml): Bumped GTFS-Lib version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2df4c33d9..aa7c7a676 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 62a7ed2efba69abfdf9bd08db03f3fe029e2b0a8 + 239013046f75becc955f0729fe01ee93d4f74c48 From df16b7eedbbe9148a8e3cbcf3c89b83df63e5140 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Thu, 6 Feb 2025 13:41:27 +0000 Subject: [PATCH 06/18] improvement(Unit test): Added a simple test to update a fare product --- pom.xml | 8 +++- .../controllers/api/EditorControllerTest.java | 38 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index aa7c7a676..7d3906a5f 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 239013046f75becc955f0729fe01ee93d4f74c48 + 518fcc2f494e89ee378d5c5a5f691208d53f7f2d @@ -455,6 +455,12 @@ gson 2.8.9 + + com.conveyal + gtfs-lib + 7.0.2 + compile + diff --git a/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java b/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java index 45a658b3f..f152a9b4b 100644 --- a/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java +++ b/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java @@ -30,7 +30,9 @@ import java.util.stream.Stream; import static com.conveyal.datatools.TestUtils.assertThatSqlCountQueryYieldsExpectedCount; +import static com.conveyal.datatools.TestUtils.createFeedVersion; import static com.conveyal.datatools.TestUtils.createFeedVersionFromGtfsZip; +import static com.conveyal.datatools.TestUtils.zipFolderFiles; import static com.conveyal.datatools.manager.auth.Auth0Users.USERS_API_PATH; import static com.conveyal.datatools.manager.controllers.api.UserController.TEST_AUTH0_DOMAIN; import static io.restassured.RestAssured.given; @@ -47,6 +49,7 @@ public class EditorControllerTest extends UnitTest { private static FeedSource feedSourceCascadeDelete; private static FeedVersion feedVersion; private static FeedVersion feedVersionCascadeDelete; + private static FeedVersion faresV2Version; private static final ObjectMapper mapper = new ObjectMapper(); /** @@ -72,12 +75,19 @@ public static void setUp() throws Exception { feedSourceCascadeDelete.projectId = project.id; Persistence.feedSources.create(feedSourceCascadeDelete); + FeedSource faresV2FeedSource = new FeedSource("FaresV2"); + faresV2FeedSource.projectId = project.id; + Persistence.feedSources.create(faresV2FeedSource); + feedVersion = createFeedVersionFromGtfsZip(feedSource, "bart_old.zip"); feedVersionCascadeDelete = createFeedVersionFromGtfsZip(feedSourceCascadeDelete, "bart_old.zip"); + faresV2Version = createFeedVersion(faresV2FeedSource, zipFolderFiles("fake-agency-with-fares-v2")); + // Create and run snapshot jobs - crateAndRunSnapshotJob(feedVersion.name, feedSource.id, feedVersion.namespace); - crateAndRunSnapshotJob(feedVersionCascadeDelete.name, feedSourceCascadeDelete.id, feedVersionCascadeDelete.namespace); + createAndRunSnapshotJob(feedVersion.name, feedSource.id, feedVersion.namespace); + createAndRunSnapshotJob(feedVersionCascadeDelete.name, feedSourceCascadeDelete.id, feedVersionCascadeDelete.namespace); + createAndRunSnapshotJob(faresV2Version.name, faresV2FeedSource.id, faresV2Version.namespace); LOG.info("{} setup completed in {} ms", EditorControllerTest.class.getSimpleName(), System.currentTimeMillis() - startTime); } @@ -91,7 +101,7 @@ public static void tearDown() { /** * Create and run a snapshot job in the current thread (so tests do not run until this is complete). */ - private static void crateAndRunSnapshotJob(String feedVersionName, String feedSourceId, String namespace) { + private static void createAndRunSnapshotJob(String feedVersionName, String feedSourceId, String namespace) { Snapshot snapshot = new Snapshot("Snapshot of " + feedVersionName, feedSourceId, namespace); CreateSnapshotJob createSnapshotJob = new CreateSnapshotJob(Auth0UserProfile.createTestAdminUser(), snapshot, true, false, false); @@ -203,6 +213,28 @@ void canCascadeDeleteStop() throws IOException, SQLException { assertThatSqlCountQueryYieldsExpectedCount(patternStopsCountSql, 0); } + /** + * Confirm that an existing fare product can be updated. + */ + @Test + void canUpdateFareProduct() throws IOException { + String path = String.format( + "/api/editor/secure/fareproduct/%s?feedId=%s&sessionId=test", + 2, + faresV2Version.feedSourceId + ); + String response = given() + .port(DataManager.PORT) + .body("{\"id\":2,\"fare_product_id\":\"AERIAL_TRAM_ROUND_TRIP\",\"fare_product_name\":\"Portland Aerial Tram Single Round Trip\",\"fare_media_id\":\"1\",\"amount\":\"13.5\",\"currency\":\"USD\"}") + .put(path) + .then() + .extract() + .response() + .asString(); + JsonNode json = mapper.readTree(response); + assertEquals("AERIAL_TRAM_ROUND_TRIP", json.get("fare_product_id").asText()); + } + /** * Perform patch table request on the feed source ID with the requested query and patch JSON. A null query will * apply the patch JSON to the entire table. From 7b446d11357ea2cc5f54a67fc6c997f00ef12985 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Thu, 6 Feb 2025 13:54:00 +0000 Subject: [PATCH 07/18] fix(pom.xml): Removed unwanted GTFS lib dependency. --- pom.xml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pom.xml b/pom.xml index 7d3906a5f..a1f78d7f4 100644 --- a/pom.xml +++ b/pom.xml @@ -455,12 +455,6 @@ gson 2.8.9 - - com.conveyal - gtfs-lib - 7.0.2 - compile - From fe4e278e6f62e14663c087bfe0131cec0f80fa1c Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Fri, 7 Feb 2025 11:38:08 +0000 Subject: [PATCH 08/18] improvement(EditorControllerTest.java): Updated fare product test to include create and delete reque --- .../controllers/api/EditorControllerTest.java | 108 ++++++++++-------- 1 file changed, 59 insertions(+), 49 deletions(-) diff --git a/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java b/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java index f152a9b4b..f8a8127dd 100644 --- a/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java +++ b/src/test/java/com/conveyal/datatools/editor/controllers/api/EditorControllerTest.java @@ -14,6 +14,7 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; +import io.restassured.http.Method; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -27,6 +28,7 @@ import java.io.IOException; import java.sql.SQLException; import java.util.Date; +import java.util.Objects; import java.util.stream.Stream; import static com.conveyal.datatools.TestUtils.assertThatSqlCountQueryYieldsExpectedCount; @@ -47,6 +49,7 @@ public class EditorControllerTest extends UnitTest { private static Project project; private static FeedSource feedSource; private static FeedSource feedSourceCascadeDelete; + private static FeedSource faresV2FeedSource; private static FeedVersion feedVersion; private static FeedVersion feedVersionCascadeDelete; private static FeedVersion faresV2Version; @@ -75,13 +78,12 @@ public static void setUp() throws Exception { feedSourceCascadeDelete.projectId = project.id; Persistence.feedSources.create(feedSourceCascadeDelete); - FeedSource faresV2FeedSource = new FeedSource("FaresV2"); + faresV2FeedSource = new FeedSource("FaresV2"); faresV2FeedSource.projectId = project.id; Persistence.feedSources.create(faresV2FeedSource); feedVersion = createFeedVersionFromGtfsZip(feedSource, "bart_old.zip"); feedVersionCascadeDelete = createFeedVersionFromGtfsZip(feedSourceCascadeDelete, "bart_old.zip"); - faresV2Version = createFeedVersion(faresV2FeedSource, zipFolderFiles("fake-agency-with-fares-v2")); // Create and run snapshot jobs @@ -96,6 +98,7 @@ public static void tearDown() { project.delete(); feedSource.delete(); feedSourceCascadeDelete.delete(); + faresV2FeedSource.delete(); } /** @@ -104,7 +107,13 @@ public static void tearDown() { private static void createAndRunSnapshotJob(String feedVersionName, String feedSourceId, String namespace) { Snapshot snapshot = new Snapshot("Snapshot of " + feedVersionName, feedSourceId, namespace); CreateSnapshotJob createSnapshotJob = - new CreateSnapshotJob(Auth0UserProfile.createTestAdminUser(), snapshot, true, false, false); + new CreateSnapshotJob( + Auth0UserProfile.createTestAdminUser(), + snapshot, + true, + false, + false + ); createSnapshotJob.run(); } @@ -121,14 +130,7 @@ private static Stream createPatchTableTests() { */ @ParameterizedTest @MethodSource("createPatchTableTests") - public void canPatchTableTests( - String field, - String entity, - int expectedCount, - String graphQLQueryFile, - String table - ) throws IOException { - + void canPatchTableTests(String field, String entity, int expectedCount, String graphQLQueryFile, String table) throws IOException { LOG.info("Making patch {} request", table); String value = "NEW"; ObjectNode jsonBody = mapper.createObjectNode(); @@ -148,7 +150,7 @@ public void canPatchTableTests( * Make sure the patch table endpoint can patch stops conditionally with query. */ @Test - public void canPatchStopsConditionally() throws IOException { + void canPatchStopsConditionally() throws IOException { LOG.info("Making conditional patch stops request"); ObjectNode jsonBody = mapper.createObjectNode(); String field = "stop_desc"; @@ -197,13 +199,7 @@ void canCascadeDeleteStop() throws IOException, SQLException { stopId, feedVersionCascadeDelete.feedSourceId ); - String response = given() - .port(DataManager.PORT) - .delete(path) - .then() - .extract() - .response() - .asString(); + String response = makeRequest(Method.DELETE, path, ""); JsonNode json = mapper.readTree(response); assertEquals(OK_200, json.get("code").asInt()); @@ -214,42 +210,63 @@ void canCascadeDeleteStop() throws IOException, SQLException { } /** - * Confirm that an existing fare product can be updated. + * Confirm that a fare product can be created, updated and deleted. */ @Test - void canUpdateFareProduct() throws IOException { - String path = String.format( - "/api/editor/secure/fareproduct/%s?feedId=%s&sessionId=test", - 2, - faresV2Version.feedSourceId - ); - String response = given() + void canCreateUpdateAndDeleteFareProduct() throws IOException { + String fareProductId = "AERIAL_TRAM_ROUND_TRIP"; + String fareProductIdUpdated = "AERIAL_TRAM_ROUND_TRIP_UPDATED"; + String urlPrefix = "/api/editor/secure/fareproduct"; + String urlSuffix = String.format("?feedId=%s&sessionId=test", faresV2Version.feedSourceId); + String payload = + "{" + + "\"fare_product_id\":\"" + fareProductId + "\"," + + "\"fare_product_name\":\"Portland Aerial Tram Single Round Trip\"," + + "\"fare_media_id\":\"1\"," + + "\"amount\":\"13.5\"," + + "\"currency\":\"USD\"" + + "}"; + + // Create. + String response = makeRequest(Method.POST, String.format("%s%s", urlPrefix, urlSuffix), payload); + JsonNode json = mapper.readTree(response); + String id = json.get("id").asText(); + assertEquals(fareProductId, json.get("fare_product_id").asText()); + + // Update. + payload = payload.replace(fareProductId, fareProductIdUpdated); + response = makeRequest(Method.PUT, String.format("%s/%s%s", urlPrefix, id, urlSuffix), payload); + json = mapper.readTree(response); + assertEquals(fareProductIdUpdated, json.get("fare_product_id").asText()); + + // Delete. + response = makeRequest(Method.DELETE, String.format("%s/%s%s", urlPrefix, id, urlSuffix), ""); + json = mapper.readTree(response); + assertEquals(200, json.get("code").asInt()); + } + + /** + * Make request and return the response. + */ + private static String makeRequest(Method method, String path, Object payload) { + return given() .port(DataManager.PORT) - .body("{\"id\":2,\"fare_product_id\":\"AERIAL_TRAM_ROUND_TRIP\",\"fare_product_name\":\"Portland Aerial Tram Single Round Trip\",\"fare_media_id\":\"1\",\"amount\":\"13.5\",\"currency\":\"USD\"}") - .put(path) + .body(payload) + .request(method, path) .then() .extract() .response() .asString(); - JsonNode json = mapper.readTree(response); - assertEquals("AERIAL_TRAM_ROUND_TRIP", json.get("fare_product_id").asText()); } /** * Perform patch table request on the feed source ID with the requested query and patch JSON. A null query will * apply the patch JSON to the entire table. */ - private static int patchTableRequest(String entity, String feedId, String query, JsonNode oatchJSON) throws IOException { + private static int patchTableRequest(String entity, String feedId, String query, JsonNode patchJSON) throws IOException { String path = String.format("/api/editor/secure/%s?feedId=%s", entity, feedId); if (query != null) path += "&" + query; - String response = given() - .port(DataManager.PORT) - .body(oatchJSON) - .patch(path) - .then() - .extract() - .response() - .asString(); + String response = makeRequest(Method.PATCH, path, patchJSON); JsonNode json = mapper.readTree(response); return json.get("count").asInt(); } @@ -262,16 +279,9 @@ private static JsonNode graphqlQuery (String namespace, String graphQLQueryFile) ObjectNode variables = mapper.createObjectNode(); variables.put("namespace", namespace); graphQLBody.set("variables", variables); - String query = IOUtils.toString(EditorControllerTest.class.getClassLoader().getResourceAsStream(graphQLQueryFile)); + String query = IOUtils.toString(Objects.requireNonNull(EditorControllerTest.class.getClassLoader().getResourceAsStream(graphQLQueryFile))); graphQLBody.put("query", query); - String graphQLString = given() - .port(DataManager.PORT) - .body(graphQLBody) - .post("api/manager/secure/gtfs/graphql") - .then() - .extract() - .response() - .asString(); + String graphQLString = makeRequest(Method.POST, "api/manager/secure/gtfs/graphql", graphQLBody); return mapper.readTree(graphQLString); } From e9bc7938fbbd21a3dd6df5839a4332d08b0f4561 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Tue, 17 Jun 2025 12:32:30 +0100 Subject: [PATCH 09/18] improvement(pom.xml): Updated the GTFS lib version --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1511dcb5c..d0c6ca91e 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 518fcc2f494e89ee378d5c5a5f691208d53f7f2d + 1cac51219ec1fe93bfcd6b97a9fcf2f1b392b179 From 6f6e617c2061bf620e35d62de883dc20d34dfda8 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Thu, 31 Jul 2025 15:33:52 +0100 Subject: [PATCH 10/18] improvement(Bumped GTFS-Lib version): --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 4f39a64e3..6d8a6edf8 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 1cac51219ec1fe93bfcd6b97a9fcf2f1b392b179 + a3481b0660acf998c6179be89033e6d45b94583f From bc3426f799e9cf374ab7a82b7d4c637369c413ca Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Fri, 1 Aug 2025 08:10:46 +0100 Subject: [PATCH 11/18] improvement(Reverted gtfs-lib version): Newer version had breaking changes which will be addressed i --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6d8a6edf8..4f39a64e3 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - a3481b0660acf998c6179be89033e6d45b94583f + 1cac51219ec1fe93bfcd6b97a9fcf2f1b392b179 From 14e116d4b211dc8fb57882c630aba7d709dffde6 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Fri, 1 Aug 2025 08:37:10 +0100 Subject: [PATCH 12/18] feat(Address changes in gtfs-lib): Merge stop areas into stops update --- pom.xml | 2 +- .../com/conveyal/datatools/manager/DataManager.java | 1 - .../manager/jobs/feedmerge/MergeLineContext.java | 3 ++- .../jobs/feedmerge/StopsMergeLineContext.java | 3 ++- .../transform/NormalizeFieldTransformation.java | 7 ++++++- .../RemoveNonRevenueTripsTransformation.java | 13 +++++++++++-- .../datatools/manager/utils/MergeFeedUtils.java | 5 +++-- 7 files changed, 25 insertions(+), 9 deletions(-) diff --git a/pom.xml b/pom.xml index 4f39a64e3..6d8a6edf8 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 1cac51219ec1fe93bfcd6b97a9fcf2f1b392b179 + a3481b0660acf998c6179be89033e6d45b94583f diff --git a/src/main/java/com/conveyal/datatools/manager/DataManager.java b/src/main/java/com/conveyal/datatools/manager/DataManager.java index a0aaec2dd..7bdcd5d9b 100644 --- a/src/main/java/com/conveyal/datatools/manager/DataManager.java +++ b/src/main/java/com/conveyal/datatools/manager/DataManager.java @@ -225,7 +225,6 @@ static void registerRoutes() throws IOException { new EditorControllerImpl(EDITOR_API_PREFIX, Table.PATTERNS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.SCHEDULE_EXCEPTIONS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.STOPS, DataManager.GTFS_DATA_SOURCE); - new EditorControllerImpl(EDITOR_API_PREFIX, Table.STOP_AREAS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.TIME_FRAMES, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.TRANSLATIONS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.TRIPS, DataManager.GTFS_DATA_SOURCE); diff --git a/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/MergeLineContext.java b/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/MergeLineContext.java index 320ba54dd..dedae2168 100644 --- a/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/MergeLineContext.java +++ b/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/MergeLineContext.java @@ -7,6 +7,7 @@ import com.conveyal.gtfs.loader.Field; import com.conveyal.gtfs.loader.ReferenceTracker; import com.conveyal.gtfs.loader.Table; +import com.conveyal.gtfs.util.CsvReaderUtil; import com.csvreader.CsvReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -131,7 +132,7 @@ public void startNewFeed(int feedIndex) throws IOException { keyFieldMissing = false; idScope = makeIdScope(version); - csvReader = table.getCsvReader(feed.zipFile, null); + csvReader = CsvReaderUtil.getCsvReaderAccordingToFileName(table, feed.zipFile, null); // If csv reader is null, the table was not found in the zip file. There is no need // to handle merging this table for this zip file. // No need to iterate over second (active) file if strategy is to simply extend the future GTFS diff --git a/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/StopsMergeLineContext.java b/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/StopsMergeLineContext.java index 4644c8c3a..c1d69f604 100644 --- a/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/StopsMergeLineContext.java +++ b/src/main/java/com/conveyal/datatools/manager/jobs/feedmerge/StopsMergeLineContext.java @@ -4,6 +4,7 @@ import com.conveyal.gtfs.error.NewGTFSError; import com.conveyal.gtfs.loader.Field; import com.conveyal.gtfs.loader.Table; +import com.conveyal.gtfs.util.CsvReaderUtil; import com.csvreader.CsvReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,7 +75,7 @@ private void checkThatStopCodesArePopulatedWhereRequired() throws IOException { int stopCodeIndex = getFieldIndex("stop_code"); // Get special stops reader to iterate over every stop and determine if stop_code values // are present. - CsvReader stopsReader = table.getCsvReader(feed.zipFile, null); + CsvReader stopsReader = CsvReaderUtil.getCsvReaderAccordingToFileName(table, feed.zipFile, null); while (stopsReader.readRecord()) { stopsCount++; // Special stop records (i.e., a station, entrance, or anything with diff --git a/src/main/java/com/conveyal/datatools/manager/models/transform/NormalizeFieldTransformation.java b/src/main/java/com/conveyal/datatools/manager/models/transform/NormalizeFieldTransformation.java index 92b1ac77a..fd3bb6266 100644 --- a/src/main/java/com/conveyal/datatools/manager/models/transform/NormalizeFieldTransformation.java +++ b/src/main/java/com/conveyal/datatools/manager/models/transform/NormalizeFieldTransformation.java @@ -6,6 +6,7 @@ import com.conveyal.datatools.manager.utils.json.JsonUtil; import com.conveyal.gtfs.loader.Field; import com.conveyal.gtfs.loader.Table; +import com.conveyal.gtfs.util.CsvReaderUtil; import com.csvreader.CsvReader; import org.apache.commons.lang3.StringUtils; import org.apache.commons.text.WordUtils; @@ -199,7 +200,11 @@ public void transform(FeedTransformZipTarget zipTarget, MonitorableJob.Status st status.fail(String.format("Unsupported GTFS file '%s'", tableName)); return; } - CsvReader csvReader = gtfsTable.getCsvReader(new ZipFile(tempZipPath.toAbsolutePath().toString()), null); + CsvReader csvReader = CsvReaderUtil.getCsvReaderAccordingToFileName( + gtfsTable, + new ZipFile(tempZipPath.toAbsolutePath().toString()), + null + ); if (csvReader == null) { status.fail(String.format("'Normalize Field' failed because file '%s' was not found in the GTFS archive", tableName)); return; diff --git a/src/main/java/com/conveyal/datatools/manager/models/transform/RemoveNonRevenueTripsTransformation.java b/src/main/java/com/conveyal/datatools/manager/models/transform/RemoveNonRevenueTripsTransformation.java index 065646512..a4269860d 100644 --- a/src/main/java/com/conveyal/datatools/manager/models/transform/RemoveNonRevenueTripsTransformation.java +++ b/src/main/java/com/conveyal/datatools/manager/models/transform/RemoveNonRevenueTripsTransformation.java @@ -5,6 +5,7 @@ import com.conveyal.datatools.manager.utils.GtfsUtils; import com.conveyal.gtfs.loader.Field; import com.conveyal.gtfs.loader.Table; +import com.conveyal.gtfs.util.CsvReaderUtil; import com.csvreader.CsvReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -58,7 +59,11 @@ public void transform(FeedTransformZipTarget zipTarget, MonitorableJob.Status st Files.copy(originalZipPath, tempZipPath, StandardCopyOption.REPLACE_EXISTING); Table gtfsTable = GtfsUtils.getGtfsTable("stop_times"); - CsvReader csvReaderForStopTimes = gtfsTable.getCsvReader(new ZipFile(tempZipPath.toAbsolutePath().toString()), null); + CsvReader csvReaderForStopTimes = CsvReaderUtil.getCsvReaderAccordingToFileName( + gtfsTable, + new ZipFile(tempZipPath.toAbsolutePath().toString()), + null + ); final String[] headersForStopTime = csvReaderForStopTimes.getHeaders(); Field[] fieldsFoundInStopTimes = gtfsTable.getFieldsFromFieldHeaders(headersForStopTime, null); Map fieldIndexes = getFieldIndexes(fieldsFoundInStopTimes); @@ -73,7 +78,11 @@ public void transform(FeedTransformZipTarget zipTarget, MonitorableJob.Status st ); gtfsTable = GtfsUtils.getGtfsTable("trips"); - CsvReader csvReaderForTrips = gtfsTable.getCsvReader(new ZipFile(tempZipPath.toAbsolutePath().toString()), null); + CsvReader csvReaderForTrips = CsvReaderUtil.getCsvReaderAccordingToFileName( + gtfsTable, + new ZipFile(tempZipPath.toAbsolutePath().toString()), + null + ); final String[] headersForTrips = csvReaderForTrips.getHeaders(); Field[] fieldsFoundInStopTrips = gtfsTable.getFieldsFromFieldHeaders(headersForTrips, null); int tripIdFieldIndex = getFieldIndex(fieldsFoundInStopTrips, TRIP_ID_FIELD_NAME); diff --git a/src/main/java/com/conveyal/datatools/manager/utils/MergeFeedUtils.java b/src/main/java/com/conveyal/datatools/manager/utils/MergeFeedUtils.java index 0205ef003..606c39a4d 100644 --- a/src/main/java/com/conveyal/datatools/manager/utils/MergeFeedUtils.java +++ b/src/main/java/com/conveyal/datatools/manager/utils/MergeFeedUtils.java @@ -15,6 +15,7 @@ import com.conveyal.gtfs.loader.Field; import com.conveyal.gtfs.loader.Table; import com.conveyal.gtfs.model.StopTime; +import com.conveyal.gtfs.util.CsvReaderUtil; import com.csvreader.CsvReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +46,7 @@ public class MergeFeedUtils { public static Set getIdsForTable(ZipFile zipFile, Table table) throws IOException { Set ids = new HashSet<>(); String keyField = table.getKeyFieldName(); - CsvReader csvReader = table.getCsvReader(zipFile, null); + CsvReader csvReader = CsvReaderUtil.getCsvReaderAccordingToFileName(table, zipFile, null); if (csvReader == null) { LOG.warn("Table {} not found in zip file: {}", table.name, zipFile.getName()); return ids; @@ -117,7 +118,7 @@ public static Set getAllFields(List feedsToMerge, Table tabl Set sharedFields = new HashSet<>(); // First, iterate over each feed to collect the shared fields that need to be output in the merged table. for (FeedToMerge feed : feedsToMerge) { - CsvReader csvReader = table.getCsvReader(feed.zipFile, null); + CsvReader csvReader = CsvReaderUtil.getCsvReaderAccordingToFileName(table, feed.zipFile, null); // If csv reader is null, the table was not found in the zip file. if (csvReader == null) { continue; From 3f867f94d533ad161bb6c2192b2a1db7ff0a70d1 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Tue, 5 Aug 2025 09:06:09 +0100 Subject: [PATCH 13/18] improvement(GTFS-Lib version): Bumped to latest for merge stop areas --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 6d8a6edf8..adc62e79e 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - a3481b0660acf998c6179be89033e6d45b94583f + 2b1302c799344ecb95ece57f407a15dad4f3d286 From f36adff8fc9a940763cfc127c2d131748f8ff652 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Mon, 11 Aug 2025 15:25:06 +0100 Subject: [PATCH 14/18] improvement(pom.xml): Bumped GTFS-Lib version to include entry in zip sub dir --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index adc62e79e..f43aba61e 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 2b1302c799344ecb95ece57f407a15dad4f3d286 + f3ef2c4270ecc2c47fc1a16df75eec85aa147828 From adb8ebd6ebbe616a5dee541a76b6672fa2e2a732 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Thu, 14 Aug 2025 15:52:45 +0100 Subject: [PATCH 15/18] improvement(GTFS-Lib): Bumped version to include export for stop areas --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f43aba61e..ccad968bf 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - f3ef2c4270ecc2c47fc1a16df75eec85aa147828 + 83533349ed58a8ea043439dabae36b9d0bf2cb3c From 8c9091f1f6ed1caab393808770a1669240abde41 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Fri, 22 Aug 2025 13:51:22 +0100 Subject: [PATCH 16/18] improvement(Bumped GTFS-Lib version): --- pom.xml | 2 +- src/main/java/com/conveyal/datatools/manager/DataManager.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index ccad968bf..1b56d764b 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 83533349ed58a8ea043439dabae36b9d0bf2cb3c + 6739bc6f50295f930b8f0d0c2ee999066c6f4cc5 diff --git a/src/main/java/com/conveyal/datatools/manager/DataManager.java b/src/main/java/com/conveyal/datatools/manager/DataManager.java index 7bdcd5d9b..5e3f5e0a9 100644 --- a/src/main/java/com/conveyal/datatools/manager/DataManager.java +++ b/src/main/java/com/conveyal/datatools/manager/DataManager.java @@ -220,7 +220,6 @@ static void registerRoutes() throws IOException { new EditorControllerImpl(EDITOR_API_PREFIX, Table.FEED_INFO, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.NETWORKS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.ROUTES, DataManager.GTFS_DATA_SOURCE); - new EditorControllerImpl(EDITOR_API_PREFIX, Table.ROUTE_NETWORKS, DataManager.GTFS_DATA_SOURCE); // NOTE: Patterns controller handles updates to nested tables shapes, pattern stops, and frequencies. new EditorControllerImpl(EDITOR_API_PREFIX, Table.PATTERNS, DataManager.GTFS_DATA_SOURCE); new EditorControllerImpl(EDITOR_API_PREFIX, Table.SCHEDULE_EXCEPTIONS, DataManager.GTFS_DATA_SOURCE); From bb5b3fb003561c1a77f451c293fd8ccf844d16d4 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Tue, 26 Aug 2025 17:10:47 +0100 Subject: [PATCH 17/18] improvement(Bumped GTFS-Lib version): --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 1b56d764b..86b84b32f 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - 6739bc6f50295f930b8f0d0c2ee999066c6f4cc5 + a65a86a30d60276c82d1de7f6c8791cb94eeaa62 From 30f3fbfa3c23bceec98ce3dad82e8a4a0dc91df5 Mon Sep 17 00:00:00 2001 From: Robin Beer Date: Wed, 27 Aug 2025 09:39:24 +0100 Subject: [PATCH 18/18] improvement(Bumped GTFS-Lib version): --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 86b84b32f..57c1d93c2 100644 --- a/pom.xml +++ b/pom.xml @@ -272,7 +272,7 @@ com.github.ibi-group gtfs-lib - a65a86a30d60276c82d1de7f6c8791cb94eeaa62 + bf7aaa904bbc0a8705295914baebc0675253e487