├── .github └── workflows │ └── gradle.yml ├── .gitignore ├── LICENSE ├── README.md ├── analysis.properties.template ├── analysis.properties.test ├── build.gradle ├── census ├── downloadData.py ├── geobuf.proto ├── randomizeCsv.py └── seamless-census.md ├── docs ├── README.r5.md ├── advanced-usage.md ├── debug-interface.png ├── fares │ ├── fareto.png │ ├── index.md │ └── newyork.md ├── index.md ├── mkdocs.yml └── static-output.md ├── pom.xml ├── settings.gradle └── src ├── main ├── java │ ├── com │ │ └── conveyal │ │ │ ├── analysis │ │ │ ├── AnalysisServerException.java │ │ │ ├── BackendConfig.java │ │ │ ├── BackendMain.java │ │ │ ├── BackendVersion.java │ │ │ ├── RegionalAnalysisStatus.java │ │ │ ├── SelectingGridReducer.java │ │ │ ├── UserPermissions.java │ │ │ ├── components │ │ │ │ ├── Authentication.java │ │ │ │ ├── Component.java │ │ │ │ ├── Components.java │ │ │ │ ├── Compute.java │ │ │ │ ├── HttpApi.java │ │ │ │ ├── LocalAuthentication.java │ │ │ │ ├── LocalComponents.java │ │ │ │ ├── LocalWorkerLauncher.java │ │ │ │ ├── TaskScheduler.java │ │ │ │ ├── WorkerLauncher.java │ │ │ │ ├── broker │ │ │ │ │ ├── Broker.java │ │ │ │ │ ├── Job.java │ │ │ │ │ ├── JobStatus.java │ │ │ │ │ ├── RedeliveryTest.java │ │ │ │ │ ├── WorkerCatalog.java │ │ │ │ │ ├── WorkerObservation.java │ │ │ │ │ ├── WorkerStartupScriptTestHook.java │ │ │ │ │ └── WorkerTags.java │ │ │ │ └── eventbus │ │ │ │ │ ├── CrudEvent.java │ │ │ │ │ ├── Event.java │ │ │ │ │ ├── EventBus.java │ │ │ │ │ ├── FileUploadEvent.java │ │ │ │ │ ├── RegionalAnalysisEvent.java │ │ │ │ │ ├── SinglePointEvent.java │ │ │ │ │ └── WorkerEvent.java │ │ │ ├── controllers │ │ │ │ ├── AggregationAreaController.java │ │ │ │ ├── BrokerController.java │ │ │ │ ├── BundleController.java │ │ │ │ ├── FileStorageController.java │ │ │ │ ├── GTFSGraphQLController.java │ │ │ │ ├── HttpController.java │ │ │ │ ├── ModificationController.java │ │ │ │ ├── OpportunityDatasetController.java │ │ │ │ ├── ProjectController.java │ │ │ │ ├── RegionalAnalysisController.java │ │ │ │ ├── TimetableController.java │ │ │ │ ├── WrappedFeedInfo.java │ │ │ │ └── package-info.java │ │ │ ├── grids │ │ │ │ └── SeamlessCensusGridExtractor.java │ │ │ ├── models │ │ │ │ ├── AbstractTimetable.java │ │ │ │ ├── AddStreets.java │ │ │ │ ├── AddTripPattern.java │ │ │ │ ├── AdjustDwellTime.java │ │ │ │ ├── AdjustSpeed.java │ │ │ │ ├── AggregationArea.java │ │ │ │ ├── AnalysisRequest.java │ │ │ │ ├── BaseModel.java │ │ │ │ ├── Bounds.java │ │ │ │ ├── Bundle.java │ │ │ │ ├── ConvertToFrequency.java │ │ │ │ ├── CustomModificationHolder.java │ │ │ │ ├── FileInfo.java │ │ │ │ ├── JsonViews.java │ │ │ │ ├── Model.java │ │ │ │ ├── Modification.java │ │ │ │ ├── ModificationStop.java │ │ │ │ ├── ModifyStreets.java │ │ │ │ ├── OpportunityDataset.java │ │ │ │ ├── Project.java │ │ │ │ ├── Region.java │ │ │ │ ├── RegionalAnalysis.java │ │ │ │ ├── RemoveStops.java │ │ │ │ ├── RemoveTrips.java │ │ │ │ ├── Reroute.java │ │ │ │ └── Segment.java │ │ │ ├── persistence │ │ │ │ ├── AnalysisCollection.java │ │ │ │ ├── AnalysisDB.java │ │ │ │ ├── MongoMap.java │ │ │ │ └── Persistence.java │ │ │ ├── results │ │ │ │ ├── CsvResultWriter.java │ │ │ │ ├── GridResultWriter.java │ │ │ │ ├── MultiOriginAssembler.java │ │ │ │ └── ResultWriter.java │ │ │ └── util │ │ │ │ ├── BsonObjectIdModule.java │ │ │ │ ├── FileItemInputStreamProvider.java │ │ │ │ ├── HttpStatus.java │ │ │ │ ├── HttpUtils.java │ │ │ │ ├── Jobs.java │ │ │ │ └── JsonUtil.java │ │ │ ├── data │ │ │ ├── census │ │ │ │ ├── CensusExtractor.java │ │ │ │ ├── CensusLoader.java │ │ │ │ ├── FileSeamlessSource.java │ │ │ │ ├── LodesSource.java │ │ │ │ ├── S3SeamlessSource.java │ │ │ │ ├── SeamlessSource.java │ │ │ │ ├── ShapeDataStore.java │ │ │ │ └── TigerLineSource.java │ │ │ └── geobuf │ │ │ │ ├── GeobufDecoder.java │ │ │ │ ├── GeobufEncoder.java │ │ │ │ ├── GeobufFeature.java │ │ │ │ └── ShapefileToGeobuf.java │ │ │ ├── file │ │ │ ├── FileStorage.java │ │ │ ├── FileStorageFormat.java │ │ │ ├── FileStorageKey.java │ │ │ ├── FileUtils.java │ │ │ ├── LocalFileStorage.java │ │ │ └── S3FileStorage.java │ │ │ ├── gtfs │ │ │ ├── CropGTFS.java │ │ │ ├── GTFSCache.java │ │ │ ├── GTFSFeed.java │ │ │ ├── Geometries.java │ │ │ ├── TripPatternKey.java │ │ │ ├── api │ │ │ │ ├── ApiMain.java │ │ │ │ ├── graphql │ │ │ │ │ ├── GeoJsonCoercing.java │ │ │ │ │ ├── GraphQLGtfsSchema.java │ │ │ │ │ ├── WrappedEntityFieldFetcher.java │ │ │ │ │ ├── WrappedGTFSEntity.java │ │ │ │ │ ├── fetchers │ │ │ │ │ │ ├── FeedFetcher.java │ │ │ │ │ │ ├── PatternFetcher.java │ │ │ │ │ │ ├── RouteFetcher.java │ │ │ │ │ │ ├── StopFetcher.java │ │ │ │ │ │ ├── StopTimeFetcher.java │ │ │ │ │ │ └── TripDataFetcher.java │ │ │ │ │ └── types │ │ │ │ │ │ ├── FeedType.java │ │ │ │ │ │ ├── PatternType.java │ │ │ │ │ │ ├── RouteType.java │ │ │ │ │ │ ├── StopTimeType.java │ │ │ │ │ │ ├── StopType.java │ │ │ │ │ │ └── TripType.java │ │ │ │ └── util │ │ │ │ │ ├── GeomUtil.java │ │ │ │ │ └── GraphQLUtil.java │ │ │ ├── error │ │ │ │ ├── DateParseError.java │ │ │ │ ├── DuplicateKeyError.java │ │ │ │ ├── DuplicateStopError.java │ │ │ │ ├── DuplicateTripError.java │ │ │ │ ├── EmptyFieldError.java │ │ │ │ ├── EmptyTableError.java │ │ │ │ ├── GTFSError.java │ │ │ │ ├── GeneralError.java │ │ │ │ ├── MisplacedStopError.java │ │ │ │ ├── MissingColumnError.java │ │ │ │ ├── MissingShapeError.java │ │ │ │ ├── MissingTableError.java │ │ │ │ ├── NewGTFSError.java │ │ │ │ ├── NewGTFSErrorType.java │ │ │ │ ├── NoAgencyInFeedError.java │ │ │ │ ├── NoTripsForRouteError.java │ │ │ │ ├── NumberParseError.java │ │ │ │ ├── OverlappingTripsInBlockError.java │ │ │ │ ├── RangeError.java │ │ │ │ ├── ReferentialIntegrityError.java │ │ │ │ ├── ReversedTripShapeError.java │ │ │ │ ├── SQLErrorStorage.java │ │ │ │ ├── ShapeMissingCoordinatesError.java │ │ │ │ ├── TableInSubdirectoryError.java │ │ │ │ ├── TimeParseError.java │ │ │ │ ├── TimeZoneError.java │ │ │ │ ├── URLParseError.java │ │ │ │ ├── UnusedStopError.java │ │ │ │ └── package-info.java │ │ │ ├── loader │ │ │ │ ├── BooleanField.java │ │ │ │ ├── CSVResultSetAdapter.java │ │ │ │ ├── ColorField.java │ │ │ │ ├── CurrencyField.java │ │ │ │ ├── DateField.java │ │ │ │ ├── DoubleField.java │ │ │ │ ├── EntityPopulator.java │ │ │ │ ├── Field.java │ │ │ │ ├── IntegerField.java │ │ │ │ ├── LanguageField.java │ │ │ │ ├── Requirement.java │ │ │ │ ├── SQLEntityFetcher.java │ │ │ │ ├── ShortField.java │ │ │ │ ├── StringField.java │ │ │ │ ├── Table.java │ │ │ │ ├── TableReader.java │ │ │ │ ├── TimeField.java │ │ │ │ └── URLField.java │ │ │ ├── model │ │ │ │ ├── Agency.java │ │ │ │ ├── Calendar.java │ │ │ │ ├── CalendarDate.java │ │ │ │ ├── Entity.java │ │ │ │ ├── Fare.java │ │ │ │ ├── FareAttribute.java │ │ │ │ ├── FareRule.java │ │ │ │ ├── FeedInfo.java │ │ │ │ ├── Frequency.java │ │ │ │ ├── Pattern.java │ │ │ │ ├── Route.java │ │ │ │ ├── Service.java │ │ │ │ ├── Shape.java │ │ │ │ ├── ShapeMap.java │ │ │ │ ├── ShapePoint.java │ │ │ │ ├── Stop.java │ │ │ │ ├── StopTime.java │ │ │ │ ├── Transfer.java │ │ │ │ ├── Trip.java │ │ │ │ └── package-info.java │ │ │ ├── storage │ │ │ │ ├── BooleanAsciiGrid.java │ │ │ │ └── StorageException.java │ │ │ ├── util │ │ │ │ ├── Deduplicator.java │ │ │ │ ├── GeometryUtil.java │ │ │ │ ├── Renamer.java │ │ │ │ ├── Util.java │ │ │ │ └── json │ │ │ │ │ ├── JacksonSerializers.java │ │ │ │ │ ├── JsonManager.java │ │ │ │ │ ├── Rectangle2DDeserializer.java │ │ │ │ │ └── Rectangle2DMixIn.java │ │ │ └── validator │ │ │ │ ├── model │ │ │ │ ├── DuplicateStops.java │ │ │ │ └── Priority.java │ │ │ │ └── service │ │ │ │ ├── GeoUtils.java │ │ │ │ └── ProjectedCoordinate.java │ │ │ ├── osmlib │ │ │ ├── DeflatedBlockReader.java │ │ │ ├── DeflatedBlockWriter.java │ │ │ ├── Node.java │ │ │ ├── NodeTracker.java │ │ │ ├── OSM.java │ │ │ ├── OSMChangeParser.java │ │ │ ├── OSMEntity.java │ │ │ ├── OSMEntitySink.java │ │ │ ├── OSMEntitySource.java │ │ │ ├── PBFInput.java │ │ │ ├── PBFOutput.java │ │ │ ├── Relation.java │ │ │ ├── StringTable.java │ │ │ ├── TagCounter.java │ │ │ ├── TextOutput.java │ │ │ ├── TileOSMSource.java │ │ │ ├── Updater.java │ │ │ ├── VEXBlock.java │ │ │ ├── VarIntInputStream.java │ │ │ ├── VarIntOutputStream.java │ │ │ ├── VexFormat.java │ │ │ ├── VexInput.java │ │ │ ├── VexOutput.java │ │ │ ├── Way.java │ │ │ ├── WebMercatorTile.java │ │ │ ├── display │ │ │ │ ├── Display.java │ │ │ │ ├── GraphicsSink.java │ │ │ │ └── WebMercatorTile.java │ │ │ ├── main │ │ │ │ ├── Converter.java │ │ │ │ └── SpeedSetter.java │ │ │ ├── package-info.java │ │ │ └── serializer │ │ │ │ ├── NodeSerializer.java │ │ │ │ ├── VarInt.java │ │ │ │ ├── WaySerializer.java │ │ │ │ └── package-info.java │ │ │ └── r5 │ │ │ ├── OneOriginResult.java │ │ │ ├── R5Main.java │ │ │ ├── analyst │ │ │ ├── AccessibilityResult.java │ │ │ ├── BootstrappingTravelTimeReducer.java │ │ │ ├── ByteArrayOutputInputStream.java │ │ │ ├── FileCategory.java │ │ │ ├── FilePersistence.java │ │ │ ├── FreeFormPointSet.java │ │ │ ├── Grid.java │ │ │ ├── GridTransformWrapper.java │ │ │ ├── IsochroneFeature.java │ │ │ ├── LinkageCache.java │ │ │ ├── LittleEndianIntOutputStream.java │ │ │ ├── MakeFreeFormTestCSV.java │ │ │ ├── NetworkPreloader.java │ │ │ ├── PathScorer.java │ │ │ ├── PersistenceBuffer.java │ │ │ ├── PointSet.java │ │ │ ├── PointSetCache.java │ │ │ ├── S3FilePersistence.java │ │ │ ├── SelectingGridReducer.java │ │ │ ├── TravelTimeComputer.java │ │ │ ├── TravelTimeReducer.java │ │ │ ├── WebMercatorExtents.java │ │ │ ├── WebMercatorGridPointSet.java │ │ │ ├── WebMercatorGridPointSetCache.java │ │ │ ├── WorkerCategory.java │ │ │ ├── cluster │ │ │ │ ├── AnalysisWorker.java │ │ │ │ ├── AnalysisWorkerController.java │ │ │ │ ├── AnalysisWorkerTask.java │ │ │ │ ├── BundleManifest.java │ │ │ │ ├── EC2Info.java │ │ │ │ ├── GridResultAssembler.java │ │ │ │ ├── JobSimulator.java │ │ │ │ ├── PathWriter.java │ │ │ │ ├── RegionalTask.java │ │ │ │ ├── RegionalWorkResult.java │ │ │ │ ├── ScenarioCache.java │ │ │ │ ├── ThroughputTracker.java │ │ │ │ ├── TimeGridWriter.java │ │ │ │ ├── TravelTimeResult.java │ │ │ │ ├── TravelTimeSurfaceTask.java │ │ │ │ ├── WorkerNotReadyException.java │ │ │ │ └── WorkerStatus.java │ │ │ ├── decay │ │ │ │ ├── DecayFunction.java │ │ │ │ ├── ExponentialDecayFunction.java │ │ │ │ ├── FixedExponentialDecayFunction.java │ │ │ │ ├── LinearDecayFunction.java │ │ │ │ ├── LogisticDecayFunction.java │ │ │ │ └── StepDecayFunction.java │ │ │ ├── error │ │ │ │ ├── ScenarioApplicationException.java │ │ │ │ ├── TaskError.java │ │ │ │ └── UnsupportedGeometryException.java │ │ │ ├── fare │ │ │ │ ├── BogotaInRoutingFareCalculator.java │ │ │ │ ├── BogotaMixedInRoutingFareCalculator.java │ │ │ │ ├── BostonInRoutingFareCalculator.java │ │ │ │ ├── ChicagoInRoutingFareCalculator.java │ │ │ │ ├── FareBounds.java │ │ │ │ ├── InRoutingFareCalculator.java │ │ │ │ ├── ParetoServer.java │ │ │ │ ├── RouteBasedFareRules.java │ │ │ │ ├── SimpleInRoutingFareCalculator.java │ │ │ │ ├── TransferAllowance.java │ │ │ │ ├── ZoneBasedFareSystem.java │ │ │ │ ├── nyc │ │ │ │ │ ├── LIRRStop.java │ │ │ │ │ ├── LIRRTransferAllowance.java │ │ │ │ │ ├── NYCFareDataCache.java │ │ │ │ │ ├── NYCInRoutingFareCalculator.java │ │ │ │ │ ├── NYCPatternType.java │ │ │ │ │ ├── NYCStaticFareData.java │ │ │ │ │ └── NYCTransferAllowance.java │ │ │ │ └── package-info.java │ │ │ ├── progress │ │ │ │ ├── NetworkPreloaderProgressListener.java │ │ │ │ ├── NoopProgressListener.java │ │ │ │ ├── ProgressListener.java │ │ │ │ ├── Task.java │ │ │ │ ├── TaskAction.java │ │ │ │ └── TaskExecutor.java │ │ │ └── scenario │ │ │ │ ├── AddStreets.java │ │ │ │ ├── AddTrips.java │ │ │ │ ├── AdjustDwellTime.java │ │ │ │ ├── AdjustFrequency.java │ │ │ │ ├── AdjustSpeed.java │ │ │ │ ├── CustomModificationHolder.java │ │ │ │ ├── IndexedPolygonCollection.java │ │ │ │ ├── Modification.java │ │ │ │ ├── ModificationPolygon.java │ │ │ │ ├── ModificationTypeResolver.java │ │ │ │ ├── ModifyStreets.java │ │ │ │ ├── PickupDelay.java │ │ │ │ ├── PickupWaitTimes.java │ │ │ │ ├── RemoveStops.java │ │ │ │ ├── RemoveTrips.java │ │ │ │ ├── Reroute.java │ │ │ │ ├── RoadCongestion.java │ │ │ │ ├── Scenario.java │ │ │ │ ├── SetFareCalculator.java │ │ │ │ ├── StopSpec.java │ │ │ │ └── package-info.java │ │ │ ├── api │ │ │ ├── GraphQlRequest.java │ │ │ ├── ProfileResponse.java │ │ │ └── util │ │ │ │ ├── AbsoluteDirection.java │ │ │ │ ├── Alert.java │ │ │ │ ├── BikeRentalStation.java │ │ │ │ ├── Coordinate.java │ │ │ │ ├── Elevation.java │ │ │ │ ├── Fare.java │ │ │ │ ├── Itinerary.java │ │ │ │ ├── LegMode.java │ │ │ │ ├── ModeStopIndex.java │ │ │ │ ├── NonTransitMode.java │ │ │ │ ├── ParkRideParking.java │ │ │ │ ├── PointToPointConnection.java │ │ │ │ ├── PolylineGeometry.java │ │ │ │ ├── ProfileOption.java │ │ │ │ ├── RelativeDirection.java │ │ │ │ ├── Route.java │ │ │ │ ├── SearchType.java │ │ │ │ ├── SegmentPattern.java │ │ │ │ ├── Stats.java │ │ │ │ ├── Stop.java │ │ │ │ ├── StopCluster.java │ │ │ │ ├── StreetEdgeInfo.java │ │ │ │ ├── StreetSegment.java │ │ │ │ ├── Transfer.java │ │ │ │ ├── TransitJourneyID.java │ │ │ │ ├── TransitModes.java │ │ │ │ ├── TransitSegment.java │ │ │ │ ├── Trip.java │ │ │ │ └── TripPattern.java │ │ │ ├── common │ │ │ ├── DirectionUtils.java │ │ │ ├── GeoJsonFeature.java │ │ │ ├── GeometryUtils.java │ │ │ ├── JsonUtilities.java │ │ │ ├── SphericalDistanceLibrary.java │ │ │ └── Util.java │ │ │ ├── kryo │ │ │ └── KryoNetworkSerializer.java │ │ │ ├── labeling │ │ │ ├── LevelOfTrafficStressLabeler.java │ │ │ ├── RoadPermission.java │ │ │ ├── SpeedLabeler.java │ │ │ ├── TraversalPermissionLabeler.java │ │ │ ├── TypeOfEdgeLabeler.java │ │ │ ├── USTraversalPermissionLabeler.java │ │ │ └── package-info.java │ │ │ ├── model │ │ │ └── json_serialization │ │ │ │ ├── BitSetDeserializer.java │ │ │ │ ├── BitSetSerializer.java │ │ │ │ ├── JavaLocalDateDeserializer.java │ │ │ │ ├── JavaLocalDateSerializer.java │ │ │ │ ├── LegModeSetDeserializer.java │ │ │ │ ├── LegModeSetSerializer.java │ │ │ │ ├── LineStringDeserializer.java │ │ │ │ ├── LineStringSerializer.java │ │ │ │ ├── ModeSetDeserializer.java │ │ │ │ ├── ModeSetSerializer.java │ │ │ │ ├── PolyUtil.java │ │ │ │ ├── TransitModeSetDeserializer.java │ │ │ │ ├── TransitModeSetSerializer.java │ │ │ │ ├── ZoneIdDeserializer.java │ │ │ │ └── ZoneIdSerializer.java │ │ │ ├── point_to_point │ │ │ ├── PointToPointRouterServer.java │ │ │ └── builder │ │ │ │ ├── PointToPointQuery.java │ │ │ │ ├── RouterInfo.java │ │ │ │ ├── SpeedConfig.java │ │ │ │ ├── SpeedUnit.java │ │ │ │ └── TNBuilderConfig.java │ │ │ ├── profile │ │ │ ├── DominatingList.java │ │ │ ├── ExecutionTimer.java │ │ │ ├── FareDominatingList.java │ │ │ ├── FastRaptorWorker.java │ │ │ ├── FrequencyRandomOffsets.java │ │ │ ├── HashPath.java │ │ │ ├── McRaptorSuboptimalPathProfileRouter.java │ │ │ ├── Path.java │ │ │ ├── PathWithTimes.java │ │ │ ├── PerTargetPropagater.java │ │ │ ├── ProfileRequest.java │ │ │ ├── PropagationTimer.java │ │ │ ├── RaptorState.java │ │ │ ├── RaptorTimer.java │ │ │ ├── StatsCalculator.java │ │ │ ├── StreetMode.java │ │ │ ├── StreetPath.java │ │ │ └── SuboptimalDominatingList.java │ │ │ ├── shapefile │ │ │ └── ShapefileMain.java │ │ │ ├── streets │ │ │ ├── BasicTraversalTimeCalculator.java │ │ │ ├── BikeRentalBuilder.java │ │ │ ├── DebugRoutingVisitor.java │ │ │ ├── EdgeStore.java │ │ │ ├── EdgeTraversalTimes.java │ │ │ ├── EgressCostTable.java │ │ │ ├── IntHashGrid.java │ │ │ ├── LaDotBikeCostSupplier.java │ │ │ ├── LaDotCostTags.java │ │ │ ├── LaDotWalkCostSupplier.java │ │ │ ├── LinkedPointSet.java │ │ │ ├── OSMCache.java │ │ │ ├── ParkRideRouter.java │ │ │ ├── PointSetTimes.java │ │ │ ├── RoutingVisitor.java │ │ │ ├── SingleModeTraversalTimes.java │ │ │ ├── Split.java │ │ │ ├── StreetLayer.java │ │ │ ├── StreetRouter.java │ │ │ ├── TarjanIslandPruner.java │ │ │ ├── TraversalTimeCalculator.java │ │ │ ├── TurnRestriction.java │ │ │ ├── VertexStore.java │ │ │ └── package-info.java │ │ │ ├── transit │ │ │ ├── DuplicateFeedException.java │ │ │ ├── PickDropType.java │ │ │ ├── RouteInfo.java │ │ │ ├── RouteTopology.java │ │ │ ├── TransferFinder.java │ │ │ ├── TransitLayer.java │ │ │ ├── TransportNetwork.java │ │ │ ├── TransportNetworkCache.java │ │ │ ├── TripFlag.java │ │ │ ├── TripPattern.java │ │ │ ├── TripSchedule.java │ │ │ ├── fare │ │ │ │ ├── DCFareCalculator.java │ │ │ │ ├── FareTable.java │ │ │ │ ├── RideType.java │ │ │ │ └── package-info.java │ │ │ └── package-info.java │ │ │ ├── transitive │ │ │ ├── TransitiveNetwork.java │ │ │ ├── TransitivePattern.java │ │ │ ├── TransitiveRoute.java │ │ │ ├── TransitiveStop.java │ │ │ └── package-info.java │ │ │ ├── trove │ │ │ ├── AugmentedList.java │ │ │ ├── TDoubleAugmentedList.java │ │ │ ├── TIntAugmentedList.java │ │ │ └── TLongAugmentedList.java │ │ │ └── util │ │ │ ├── AsyncLoader.java │ │ │ ├── EmptyTIntCollection.java │ │ │ ├── EncodedPolylineSerializer.java │ │ │ ├── ExceptionUtils.java │ │ │ ├── Histogram.java │ │ │ ├── InputStreamProvider.java │ │ │ ├── LambdaCounter.java │ │ │ ├── LocationIndexedLineInLocalCoordinateSystem.java │ │ │ ├── P2.java │ │ │ ├── ProgressListener.java │ │ │ ├── S3Util.java │ │ │ ├── ShapefileReader.java │ │ │ ├── TIntIntHashMultimap.java │ │ │ ├── TIntIntMultimap.java │ │ │ ├── TIntObjectHashMultimap.java │ │ │ └── TIntObjectMultimap.java │ └── geobuf │ │ └── Geobuf.java └── resources │ ├── com │ └── conveyal │ │ └── gtfs │ │ └── storage │ │ └── gpwv3-quarter-boolean.asc │ ├── debug-plan │ ├── debug.html │ ├── images │ │ ├── marker-flag-end-shadowed.png │ │ └── marker-flag-start-shadowed.png │ ├── index.html │ ├── leaflet-sidebar.css │ ├── leaflet_context │ │ ├── leaflet.contextmenu.css │ │ └── leaflet.contextmenu.js │ ├── new.html │ ├── oneway.json │ ├── oneway.png │ ├── oneway@2x.json │ ├── oneway@2x.png │ └── scripts │ │ ├── config.js │ │ ├── debug.js │ │ ├── graphql_plan.js │ │ ├── gui.js │ │ ├── lib │ │ └── leaflet-sidebar.js │ │ ├── plan.js │ │ ├── request_query.json │ │ └── utils.js │ ├── fares │ ├── dc │ │ ├── marc.csv │ │ ├── metrorail.csv │ │ └── vre.csv │ └── nyc │ │ ├── lirr │ │ ├── README.txt │ │ ├── descendants.csv │ │ ├── lirr_stops_fare_zones.csv │ │ ├── lirr_zonal_fares.csv │ │ └── via_fares.csv │ │ ├── mnr │ │ └── mnr_fares.csv │ │ └── mta │ │ ├── express_bus_routes.csv │ │ └── subway_transfers.csv │ └── logback.xml └── test ├── java └── com │ └── conveyal │ ├── analysis │ ├── AnalysisServerTest.java │ ├── TestComponents.java │ ├── TestUtils.java │ └── controllers │ │ ├── BundleControllerTest.java │ │ └── TimetableControllerTest.java │ ├── data │ ├── census │ │ └── IntegrationTest.java │ └── geobuf │ │ ├── IntegrationTest.java │ │ └── MapDBTest.java │ ├── gtfs │ ├── GTFSFeedTest.java │ ├── GeometriesTest.java │ ├── TestUtils.java │ ├── loader │ │ └── FieldTests.java │ ├── storage │ │ └── BooleanAsciiGridTest.java │ └── util │ │ └── UtilTest.java │ ├── osmlib │ ├── NodeTest.java │ ├── NodeTrackerTest.java │ ├── OSMEntityTest.java │ ├── OSMTest.java │ ├── RelationTest.java │ ├── RoundTripTest.java │ └── WayTest.java │ └── r5 │ ├── analyst │ ├── GridTest.java │ ├── InitialStopsTest.java │ ├── WebMercatorGridPointSetTest.java │ ├── core │ │ └── LocalDateSerialization.java │ ├── decay │ │ └── TestDecayFunctions.java │ └── scenario │ │ ├── AddTripsTest.java │ │ ├── AdjustDwellTest.java │ │ ├── AdjustFrequencyTest.java │ │ ├── AdjustSpeedTest.java │ │ ├── ChecksumTest.java │ │ ├── FakeGraph.java │ │ ├── RelinkingTest.java │ │ ├── RemoveStopsTest.java │ │ ├── RemoveTripsTest.java │ │ └── RerouteTest.java │ ├── api │ └── util │ │ ├── AnglesTest.java │ │ ├── RoadAnglesTest.java │ │ └── StreetSegmentTest.java │ ├── kryo │ └── KryoNetworkSerializerTest.java │ ├── labeling │ ├── TestPermissionsLabeler.java │ ├── TraversalPermissionLabelerTest.java │ └── TypeOfEdgeLabelerTest.java │ ├── profile │ ├── ProfileRequestTest.java │ └── PropagatedTimesStoreTest.java │ ├── streets │ ├── BasicTraversalTimeCalculatorTest.java │ ├── ReverseRoutingTest.java │ ├── StreetLayerTest.java │ ├── TimeDependentRoutingTest.java │ ├── TurnRestrictionTest.java │ └── TurnTest.java │ └── transit │ └── FrequencyRandomOffsetsTest.java └── resources ├── bangor_maine.osm.pbf ├── com └── conveyal │ ├── data │ └── census │ │ └── integrationTest.zip │ ├── gtfs │ └── null-island-ferry │ │ ├── agency.txt │ │ ├── calendar.txt │ │ ├── feed_info.txt │ │ ├── routes.txt │ │ ├── stop_times.txt │ │ ├── stops.txt │ │ └── trips.txt │ └── r5 │ ├── analyst │ └── scenario │ │ └── columbus.osm.pbf │ ├── api │ └── util │ │ ├── streetSegmentCAR_ROUNDABOUT.json │ │ └── streetSegmentWALK.json │ └── streets │ ├── cathedral-no-left.pbf │ ├── reisterstown-via-restriction.pbf │ ├── snake-rd.pbf │ ├── speedFlagsTest.pbf │ └── subgraph.pbf ├── fake-agency.zip ├── fake-agency ├── agency.txt ├── calendar.txt ├── calendar_dates.txt ├── fare_attributes.txt ├── fare_rules.txt ├── feed_info.txt ├── frequencies.txt ├── routes.txt ├── shapes.txt ├── stop_times.txt ├── stops.txt ├── transfers.txt └── trips.txt ├── felton.pbf ├── logback-test.xml └── porto_portugal.osm.pbf /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | /build/ 3 | /out/ 4 | 5 | # Ignore Gradle GUI config 6 | gradle-app.setting 7 | 8 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 9 | !gradle-wrapper.jar 10 | 11 | # Cache of project 12 | .gradletasknamecache 13 | 14 | # Other gradle build objects 15 | gradle 16 | gradlew.bat 17 | gradlew 18 | 19 | # IntelliJ IDEA 20 | .idea/ 21 | 22 | logs 23 | project/project 24 | project/target 25 | .target 26 | target 27 | .DS_Store 28 | tmp 29 | .history 30 | dist 31 | /.idea 32 | /*.iml 33 | /out 34 | /.idea_modules 35 | /.classpath 36 | /.project 37 | /RUNNING_PID 38 | /.settings 39 | /data 40 | s3credentials 41 | *.class 42 | /bin 43 | /cache/ 44 | *~ 45 | nbproject 46 | logentries.xml 47 | src/main/resources/git.properties 48 | pom.xml.versionsBackup 49 | analysis.properties 50 | /src/test/resources/snapshots/com/conveyal/analysis/controllers/ 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Conveyal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Conveyal Analysis Backend 2 | 3 | ## This repository is deprecated. It has been merged into Conveyal's main routing component R5. 4 | Development of the Conveyal Analysis backend is continuing in [the r5 repository](https://github.com/conveyal/r5), and existing issues are being migrated there. Please create any new issues or pull requests against that repository. 5 | -------------------------------------------------------------------------------- /census/randomizeCsv.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # Take a CSV from LODES and make all values unique so we can be sure that our tests 3 | # are working. Some columns are all zeros or are (almost) collinear, so accidentally 4 | # switching them might not make the tests fail. 5 | 6 | from csv import DictReader, DictWriter 7 | from sys import argv 8 | 9 | ct = 0 10 | def nextVal(): 11 | global ct 12 | ct += 1 13 | return ct 14 | 15 | with open(argv[1]) as infile: 16 | reader = DictReader(infile) 17 | 18 | with open(argv[2], 'w') as outfile: 19 | writer = DictWriter(outfile, reader.fieldnames) 20 | writer.writeheader() 21 | 22 | for row in reader: 23 | writer.writerow({k: nextVal() if k.startswith('C') else v for k, v in row.iteritems()}) 24 | -------------------------------------------------------------------------------- /docs/advanced-usage.md: -------------------------------------------------------------------------------- 1 | 2 | # Advanced Usage 3 | 4 | ## Debug Interface 5 | 6 | When running R5 as a point to point router (with the `--point` parameter), a debug web interface is available to visualize the details of the street graph. 7 | It is available at [http://localhost:8080/debug.html]. 8 | 9 | ![Debug interface screenshot](debug-interface.png) 10 | -------------------------------------------------------------------------------- /docs/debug-interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/docs/debug-interface.png -------------------------------------------------------------------------------- /docs/fares/fareto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/docs/fares/fareto.png -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # R5 2 | 3 | Selected documentation for the Conveyal routing engine (r5). 4 | 5 | More thorough documentation of Conveyal Analysis is available in the analysis-ui repo. -------------------------------------------------------------------------------- /docs/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: r5 2 | site_url: https://r5.readthedocs.org 3 | repo_url: https://github.com/conveyal/analysis-internal 4 | site_dir: ../target/mkdocs 5 | docs_dir: ../docs 6 | theme: readthedocs 7 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'analysis-backend' 2 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/RegionalAnalysisStatus.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis; 2 | 3 | 4 | import com.conveyal.analysis.results.MultiOriginAssembler; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * This model object is sent to the UI serialized as JSON in order to report regional job progress. 10 | */ 11 | public final class RegionalAnalysisStatus implements Serializable { 12 | public int total; 13 | public int complete; 14 | 15 | public RegionalAnalysisStatus() { /* No-arg constructor for deserialization only. */ } 16 | 17 | public RegionalAnalysisStatus(MultiOriginAssembler assembler) { 18 | total = assembler.nOriginsTotal; 19 | complete = assembler.nComplete; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/UserPermissions.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis; 2 | 3 | import com.google.common.collect.Sets; 4 | 5 | import java.util.Set; 6 | 7 | /** 8 | * Groups together all information about what a user is allowed to do. 9 | * Currently all such information is known from the group ID. 10 | * In the future we might have an EnumSet of additional flags, or a simple enum of "power levels". 11 | */ 12 | public class UserPermissions { 13 | 14 | public final String email; 15 | 16 | public final Set groups; 17 | 18 | public final boolean admin; 19 | 20 | public UserPermissions (String email, boolean admin, String... groups) { 21 | this.email = email; 22 | this.admin = admin; 23 | this.groups = Sets.newHashSet(groups); 24 | } 25 | 26 | @Override 27 | public String toString () { 28 | return "UserPermissions{" + 29 | "email='" + email + '\'' + 30 | ", groups='" + groups + '\'' + 31 | '}'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/Authentication.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components; 2 | 3 | import com.conveyal.analysis.UserPermissions; 4 | import spark.Request; 5 | 6 | /** 7 | * An interface for determining who is issuing an HTTP request, and what permissions they have to act upon data in the 8 | * analysis system. Currently all permissions information is known from the group the user belongs to: a user may take 9 | * any action on objects belonging to their group. 10 | */ 11 | public interface Authentication extends Component { 12 | /** 13 | * Given an incoming HTTP request, determine who the user is and create a UserPermissions object with that 14 | * information. If the user cannot be identified and/or authenticated, don't set those attributes and throw an 15 | * exception. Otherwise return a UserPermissions object. 16 | */ 17 | UserPermissions authenticate (Request request); 18 | } -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/Component.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components; 2 | 3 | /** 4 | * These are the top-level modules of our analysis backend that are instantiated and wired up to one another when the 5 | * application starts up. There is typically only one instance of each component, and all references to the component 6 | * are final. 7 | * 8 | * Each component should encapsulate a distinct, well-defined set of functionality. Different implementations of 9 | * components allow running locally or in other environments like AWS or potentially other cloud service providers. 10 | * Currently this is a marker interface with no methods, just to indicate the role of certain classes in the project. 11 | */ 12 | public interface Component { 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/Compute.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components; 2 | 3 | /** 4 | * This is a stub abstraction for a component performing accessibility analysis computations. 5 | * Computation could be on remote or local hardware, using code in this repo or a dependency. 6 | * This would encapsulate any logic that manages a compute cluster. 7 | * In practice, the backend currently relays the requests to a cluster of local or remote workers running R5. 8 | */ 9 | public class Compute { 10 | 11 | public void handleRequest () { 12 | 13 | } 14 | 15 | /** Also allow swappable implementation of worker polling to avoid doing it over HTTP locally? */ 16 | public void workerPollForWork() { 17 | 18 | } 19 | 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/LocalAuthentication.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components; 2 | 3 | import com.conveyal.analysis.UserPermissions; 4 | import spark.Request; 5 | 6 | /** 7 | * Working "offline", hard-wire the user and group names. We might want to use something like "_local_" or "NONE" 8 | * instead of "OFFLINE" for the group, since someone running locally doesn't necessarily feel that they are offline. 9 | */ 10 | public class LocalAuthentication implements Authentication { 11 | 12 | public static final String LOCAL_USERNAME = "local"; 13 | 14 | public static final String LOCAL_GROUP = LOCAL_USERNAME; 15 | 16 | @Override 17 | public UserPermissions authenticate (Request request) { 18 | UserPermissions userPermissions = new UserPermissions(LOCAL_USERNAME, true, LOCAL_GROUP); 19 | request.attribute("permissions", userPermissions); 20 | request.attribute("email", LOCAL_USERNAME); 21 | request.attribute("accessGroup", LOCAL_GROUP); 22 | return userPermissions; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/WorkerLauncher.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components; 2 | 3 | import com.conveyal.analysis.components.broker.WorkerTags; 4 | import com.conveyal.r5.analyst.WorkerCategory; 5 | 6 | /** Interface for Components that start workers. */ 7 | public interface WorkerLauncher extends Component { 8 | 9 | /** Start worker instances to handle single point or regional tasks. */ 10 | public void launch (WorkerCategory category, WorkerTags workerTags, int nOnDemand, int nSpot); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/broker/WorkerStartupScriptTestHook.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components.broker; 2 | 3 | import com.google.common.io.ByteStreams; 4 | 5 | import java.io.ByteArrayOutputStream; 6 | import java.io.InputStream; 7 | import java.text.MessageFormat; 8 | 9 | /** 10 | * Test hook (main class) that reads the worker startup script and substitutes in values. 11 | */ 12 | public class WorkerStartupScriptTestHook { 13 | public static void main (String... args) throws Exception { 14 | InputStream scriptIs = Broker.class.getClassLoader().getResourceAsStream("worker.sh"); 15 | ByteArrayOutputStream scriptBaos = new ByteArrayOutputStream(); 16 | ByteStreams.copy(scriptIs, scriptBaos); 17 | scriptIs.close(); 18 | scriptBaos.close(); 19 | String scriptTemplate = scriptBaos.toString(); 20 | 21 | String workerDownloadUrl = "https://r5-builds.s3.amazonaws.com/v2.3.1.jar"; 22 | String logGroup = "test-log-group"; 23 | String workerConfigString = "key=val\nkey2=val\n"; 24 | 25 | String script = MessageFormat.format(scriptTemplate, workerDownloadUrl, logGroup, workerConfigString); 26 | System.out.println(script); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/broker/WorkerTags.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components.broker; 2 | 3 | import com.conveyal.analysis.models.RegionalAnalysis; 4 | 5 | /** 6 | * An immutable group of tags to be added to the worker instance to assist in usage analysis and cost breakdowns. 7 | * These Strings are purely for categorization of workers and should not be used for other purposes, only passed through 8 | * to the AWS SDK. 9 | */ 10 | public class WorkerTags { 11 | 12 | /** The unique name of the permissions group under which the user is working. */ 13 | public final String group; 14 | 15 | /** A unique ID for the user (the user's email address). */ 16 | public final String user; 17 | 18 | /** The UUID for the project. */ 19 | public final String projectId; 20 | 21 | /** The UUID for the project. */ 22 | public final String regionId; 23 | 24 | public WorkerTags (String group, String user, String projectId, String regionId) { 25 | this.group = group; 26 | this.user = user; 27 | this.projectId = projectId; 28 | this.regionId = regionId; 29 | } 30 | 31 | public static WorkerTags fromRegionalAnalysis (RegionalAnalysis regionalAnalysis) { 32 | return new WorkerTags( 33 | regionalAnalysis.accessGroup, 34 | regionalAnalysis.createdBy, 35 | regionalAnalysis.projectId, 36 | regionalAnalysis.regionId 37 | ); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/eventbus/CrudEvent.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components.eventbus; 2 | 3 | /** 4 | * Signals that a user has created, read, updated, or deleted a domain model object from the database. 5 | */ 6 | public class CrudEvent extends Event { 7 | 8 | enum Action { 9 | CREATE, READ, UPDATE, DELETE 10 | } 11 | 12 | public final Action action; 13 | 14 | public final String entityType; 15 | 16 | public final String entityId; 17 | 18 | public CrudEvent (Action action, String entityType, String entityId) { 19 | this.action = action; 20 | this.entityType = entityType; 21 | this.entityId = entityId; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/eventbus/FileUploadEvent.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components.eventbus; 2 | 3 | /** 4 | * Created by abyrd on 2020-06-12 5 | */ 6 | public class FileUploadEvent extends Event { 7 | 8 | enum Status { 9 | BEGIN, PROCESSING, COMPLETE, ERRORED 10 | } 11 | 12 | enum FileType { 13 | GTFS, OSM, SHAPE 14 | } 15 | 16 | public final String fileId; 17 | 18 | public final FileType fileType; 19 | 20 | public final Status status; 21 | 22 | public FileUploadEvent (String fileId, FileType fileType, Status status) { 23 | this.fileId = fileId; 24 | this.fileType = fileType; 25 | this.status = status; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/eventbus/RegionalAnalysisEvent.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components.eventbus; 2 | 3 | /** 4 | * Represents the progress of a regional analysis over time. 5 | */ 6 | public class RegionalAnalysisEvent extends Event { 7 | 8 | public enum State { 9 | ENQUEUED, STARTED, COMPLETED, CANCELED, ERRORED 10 | } 11 | 12 | public final String regionalAnalysisId; 13 | 14 | public final State state; 15 | 16 | public RegionalAnalysisEvent (String regionalAnalysisId, State state) { 17 | this.regionalAnalysisId = regionalAnalysisId; 18 | this.state = state; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/eventbus/SinglePointEvent.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components.eventbus; 2 | 3 | import com.fasterxml.jackson.annotation.JsonTypeName; 4 | 5 | /** 6 | * Created by abyrd on 2020-06-12 7 | */ 8 | @JsonTypeName("singpo") 9 | public class SinglePointEvent extends Event { 10 | 11 | public final String scenarioId; 12 | 13 | public final int durationMsec; 14 | 15 | public SinglePointEvent (String scenarioId, int durationMsec) { 16 | this.scenarioId = scenarioId; 17 | this.durationMsec = durationMsec; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/components/eventbus/WorkerEvent.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.components.eventbus; 2 | 3 | import com.conveyal.r5.analyst.WorkerCategory; 4 | 5 | /** 6 | * Created by abyrd on 2020-06-12 7 | */ 8 | public class WorkerEvent extends Event { 9 | 10 | public enum Role { 11 | SINGLE_POINT, REGIONAL 12 | } 13 | 14 | public enum Action { 15 | REQUESTED, STARTED, SHUT_DOWN 16 | } 17 | 18 | public final Role role; 19 | public final WorkerCategory category; 20 | public final Action action; 21 | public final int quantity; 22 | 23 | public WorkerEvent (Role role, WorkerCategory category, Action action, int quantity) { 24 | this.role = role; 25 | this.category = category; 26 | this.action = action; 27 | this.quantity = quantity; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/controllers/HttpController.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.controllers; 2 | 3 | /** 4 | * All of our classes defining HTTP API endpoints implement this interface. 5 | * It has a single method that registers all the endpoints. 6 | * For most controllers, all those endpoints will be under a single base URL path. 7 | * Each controller implementation should have a constructor taking all the application Components it needs as arguments. 8 | */ 9 | public interface HttpController { 10 | 11 | void registerEndpoints (spark.Service sparkService); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/controllers/WrappedFeedInfo.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.controllers; 2 | 3 | import com.conveyal.gtfs.api.graphql.WrappedGTFSEntity; 4 | import com.conveyal.gtfs.model.FeedInfo; 5 | 6 | /** 7 | * Wrap feed info with GTFS feed checksum and feed unique ID. 8 | */ 9 | public class WrappedFeedInfo extends WrappedGTFSEntity { 10 | public long checksum; 11 | 12 | 13 | /** 14 | * Wrap the given GTFS entity with the unique Feed ID specified (this is not generally a GTFS feed ID as they 15 | * are not unique between different versions of the same feed. Also pass in feed checksum. 16 | */ 17 | public WrappedFeedInfo(String feedUniqueID, FeedInfo entity, long checksum) { 18 | super(feedUniqueID, entity); 19 | this.checksum = checksum; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/controllers/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package should contain only the HttpController interface and implementations of that interface. 3 | * These are the classes that define the endpoints of our HTTP API and are registered with the Spark framework. 4 | */ 5 | package com.conveyal.analysis.controllers; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/AddStreets.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.conveyal.r5.profile.StreetMode; 4 | 5 | import java.util.EnumSet; 6 | 7 | /** 8 | * Fields replicated from the R5 AddStreets modification. 9 | */ 10 | public class AddStreets extends Modification { 11 | 12 | public double[][][] lineStrings; 13 | public EnumSet allowedModes; 14 | public Double carSpeedKph; 15 | public Double walkTimeFactor; 16 | public Double bikeTimeFactor; 17 | public Integer bikeLts; 18 | public boolean linkable; 19 | 20 | @Override 21 | public String getType() { 22 | return "add-streets"; 23 | } 24 | 25 | @Override 26 | public com.conveyal.r5.analyst.scenario.Modification toR5() { 27 | com.conveyal.r5.analyst.scenario.AddStreets mod = new com.conveyal.r5.analyst.scenario.AddStreets(); 28 | mod.comment = name; 29 | 30 | mod.lineStrings = lineStrings; 31 | mod.allowedModes = allowedModes; 32 | mod.carSpeedKph = carSpeedKph; 33 | mod.walkTimeFactor = walkTimeFactor; 34 | mod.bikeTimeFactor = bikeTimeFactor; 35 | mod.bikeLts = bikeLts; 36 | mod.linkable = linkable; 37 | 38 | return mod; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/AdjustDwellTime.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | /** 4 | * Created by matthewc on 3/3/16. 5 | */ 6 | public class AdjustDwellTime extends Modification { 7 | @Override 8 | public String getType() { 9 | return "adjust-dwell-time"; 10 | } 11 | 12 | public String feed; 13 | 14 | public String[] routes; 15 | 16 | public String[] trips; 17 | 18 | public String[] stops; 19 | 20 | /** are we scaling existing times (true) or replacing them with a brand new time (false) */ 21 | public boolean scale; 22 | 23 | /** the factor by which to scale, OR the new time, depending on the value of above */ 24 | public double value; 25 | 26 | public com.conveyal.r5.analyst.scenario.AdjustDwellTime toR5 () { 27 | com.conveyal.r5.analyst.scenario.AdjustDwellTime adt = new com.conveyal.r5.analyst.scenario.AdjustDwellTime(); 28 | adt.comment = name; 29 | 30 | if (trips == null) { 31 | adt.routes = feedScopeIds(feed, routes); 32 | } else { 33 | adt.patterns = feedScopeIds(feed, trips); 34 | } 35 | 36 | adt.stops = feedScopeIds(feed, stops); 37 | 38 | if (scale) { 39 | adt.scale = value; 40 | } else { 41 | adt.dwellSecs = (int) value; 42 | } 43 | 44 | return adt; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/AdjustSpeed.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Collectors; 5 | 6 | /** 7 | * Adjust the speed of a route. 8 | */ 9 | public class AdjustSpeed extends Modification { 10 | public String getType() { 11 | return "adjust-speed"; 12 | } 13 | 14 | public String feed; 15 | 16 | public String[] routes; 17 | 18 | public String[] trips; 19 | 20 | /** array of [from stop, to stop] specifying single hops this should be applied to */ 21 | public String[][] hops; 22 | 23 | /** the factor by which to scale speed. 1 means no change, 2 means faster. */ 24 | public double scale; 25 | 26 | public com.conveyal.r5.analyst.scenario.AdjustSpeed toR5 () { 27 | com.conveyal.r5.analyst.scenario.AdjustSpeed as = new com.conveyal.r5.analyst.scenario.AdjustSpeed(); 28 | as.comment = name; 29 | 30 | if (trips == null) { 31 | as.routes = feedScopeIds(feed, routes); 32 | } else { 33 | as.patterns = feedScopeIds(feed, trips); 34 | } 35 | 36 | if (hops != null) { 37 | as.hops = Arrays.stream(hops) 38 | .map(h -> feedScopeIds(feed, h)) 39 | .map(s -> { 40 | Object[] oa = s.toArray(); 41 | return Arrays.copyOf(oa, oa.length, String[].class); 42 | }) 43 | .collect(Collectors.toList()); 44 | } 45 | 46 | as.scale = scale; 47 | 48 | return as; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/AggregationArea.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | 5 | /** 6 | * An aggregation area defines a set of origin points to be averaged together to produce an aggregate accessibility figure. 7 | * It is defined by a geometry that is rasterized and stored as a grid, with pixels with values between 0 and 100,000 8 | * depending on how much of that pixel is overlapped by the mask. 9 | */ 10 | public class AggregationArea extends Model { 11 | public String regionId; 12 | 13 | @JsonIgnore 14 | public String getS3Key () { 15 | return String.format("%s/mask/%s.grid", regionId, _id); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/BaseModel.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import org.bson.types.ObjectId; 4 | 5 | public class BaseModel { 6 | // Can retrieve `createdAt` from here 7 | public ObjectId _id; 8 | 9 | // For version management. ObjectId's contain a timestamp, so can retrieve `updatedAt` from here. 10 | public ObjectId nonce = new ObjectId(); 11 | 12 | public String createdBy = null; 13 | public String updatedBy = null; 14 | 15 | // Who owns this? 16 | public String accessGroup = null; 17 | 18 | // Everything has a name 19 | public String name = null; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/Bounds.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import org.locationtech.jts.geom.Envelope; 4 | 5 | /** 6 | * Represents a bounding box in degrees in the HTTP API. 7 | */ 8 | public class Bounds { 9 | 10 | /** The latitude of the north edge and south edge, the longitude of the east edge and west edge of the box. */ 11 | public double north, east, south, west; 12 | 13 | @Override 14 | public boolean equals (Object other) { 15 | return equals(other, 0D); 16 | } 17 | 18 | public boolean equals (Object other, double tolerance) { 19 | if (!Bounds.class.isInstance(other)) return false; 20 | Bounds o = (Bounds) other; 21 | return Math.abs(north - o.north) <= tolerance && Math.abs(east - o.east) <= tolerance && 22 | Math.abs(south - o.south) <= tolerance && Math.abs(west - o.west) <= tolerance; 23 | } 24 | 25 | public Envelope envelope () { 26 | return new Envelope(this.west, this.east, this.south, this.north); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/CustomModificationHolder.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 4 | import com.fasterxml.jackson.annotation.JsonAnySetter; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * This is the UI/Backend model for a freeform JSON modification. 11 | * It uses the JsonAnyGetter and JsonAnySetter annotations to handle all unrecognized properties, i.e. anything 12 | * that does not map to a field on the base class. 13 | */ 14 | public class CustomModificationHolder extends Modification { 15 | 16 | public String getType() { 17 | return "custom"; 18 | } 19 | 20 | private Map freeformProperties = new HashMap<>(); 21 | 22 | @JsonAnyGetter 23 | public Map getFreeformProperties() { 24 | return freeformProperties; 25 | } 26 | 27 | @JsonAnySetter 28 | public void setFreeformProperties(String key, Object value) { 29 | this.freeformProperties.put(key, value); 30 | } 31 | 32 | public com.conveyal.r5.analyst.scenario.CustomModificationHolder toR5 () { 33 | com.conveyal.r5.analyst.scenario.CustomModificationHolder customR5 = 34 | new com.conveyal.r5.analyst.scenario.CustomModificationHolder(freeformProperties, name); 35 | return customR5; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/FileInfo.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.conveyal.file.FileStorageFormat; 4 | import com.conveyal.file.FileStorageKey; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import org.bson.types.ObjectId; 7 | 8 | public class FileInfo extends BaseModel { 9 | public String regionId = null; 10 | 11 | // What is the bucket or folder that this file is stored in? 12 | public String bucket = null; 13 | 14 | // The path to create a FileStorageKey 15 | public String path = null; 16 | 17 | // Has the file been uploaded and is ready to be used? 18 | public Boolean isReady = false; 19 | 20 | // Size (in bytes) 21 | public Integer size = 0; 22 | 23 | // Internal file format category. Corresponds to an extension and mime type. 24 | public FileStorageFormat format = null; 25 | 26 | // Get path 27 | @JsonIgnore 28 | public FileStorageKey getKey () { 29 | return new FileStorageKey(bucket, path); 30 | } 31 | 32 | /** 33 | * New objects will be stored using this path. 34 | * TODO clean path? 35 | * @param accessGroup 36 | * @param _id 37 | * @param filename 38 | * @return 39 | */ 40 | public static String generatePath (String accessGroup, ObjectId _id, String filename) { 41 | String fileName = String.join("-", _id.toString(), filename); 42 | return String.join("/", accessGroup, fileName); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/JsonViews.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | /** 4 | * Created by matthewc on 7/20/16. 5 | */ 6 | public class JsonViews { 7 | public static class Api { } 8 | public static class Db { } 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/ModifyStreets.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.conveyal.r5.profile.StreetMode; 4 | 5 | import java.util.EnumSet; 6 | 7 | /** 8 | * Fields replicated from the R5 ModifyStreets modification. 9 | */ 10 | public class ModifyStreets extends Modification { 11 | 12 | public double[][][] polygons; 13 | public EnumSet allowedModes; 14 | public Double carSpeedKph; 15 | public Double walkTimeFactor; 16 | public Double bikeTimeFactor; 17 | public Integer bikeLts; 18 | 19 | @Override 20 | public String getType() { 21 | return "modify-streets"; 22 | } 23 | 24 | @Override 25 | public com.conveyal.r5.analyst.scenario.Modification toR5() { 26 | com.conveyal.r5.analyst.scenario.ModifyStreets mod = new com.conveyal.r5.analyst.scenario.ModifyStreets(); 27 | mod.comment = name; 28 | 29 | mod.polygons = polygons; 30 | mod.allowedModes = allowedModes; 31 | mod.carSpeedKph = carSpeedKph; 32 | mod.walkTimeFactor = walkTimeFactor; 33 | mod.bikeTimeFactor = bikeTimeFactor; 34 | mod.bikeLts = bikeLts; 35 | 36 | return mod; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/Project.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.conveyal.analysis.AnalysisServerException; 4 | 5 | /** 6 | * Represents a TAUI project 7 | */ 8 | public class Project extends Model implements Cloneable { 9 | /** Names of the variants of this project */ 10 | public String[] variants; 11 | 12 | public String regionId; 13 | 14 | public String bundleId; 15 | 16 | public AnalysisRequest analysisRequestSettings; 17 | 18 | public Project clone () { 19 | try { 20 | return (Project) super.clone(); 21 | } catch (CloneNotSupportedException e) { 22 | throw AnalysisServerException.unknown(e); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/Region.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.conveyal.analysis.AnalysisServerException; 4 | 5 | /** 6 | * Represents a region. 7 | */ 8 | public class Region extends Model implements Cloneable { 9 | /** Region description */ 10 | public String description; 11 | 12 | /** Bounds of this region */ 13 | public Bounds bounds; 14 | 15 | public Region clone () { 16 | try { 17 | return (Region) super.clone(); 18 | } catch (CloneNotSupportedException e) { 19 | // can't happen. 20 | throw AnalysisServerException.unknown(e); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/RemoveStops.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | /** 4 | * Created by matthewc on 3/2/16. 5 | */ 6 | public class RemoveStops extends Modification { 7 | public String getType() { 8 | return "remove-stops"; 9 | } 10 | 11 | public String feed; 12 | 13 | public String[] routes; 14 | 15 | public String[] trips; 16 | 17 | public String[] stops; 18 | 19 | public int secondsSavedAtEachStop = 0; 20 | 21 | public com.conveyal.r5.analyst.scenario.RemoveStops toR5 () { 22 | com.conveyal.r5.analyst.scenario.RemoveStops rs = new com.conveyal.r5.analyst.scenario.RemoveStops(); 23 | rs.comment = name; 24 | rs.stops = feedScopeIds(feed, stops); 25 | 26 | if (trips == null) { 27 | rs.routes = feedScopeIds(feed, routes); 28 | } else { 29 | rs.patterns = feedScopeIds(feed, trips); 30 | } 31 | 32 | rs.secondsSavedAtEachStop = secondsSavedAtEachStop; 33 | 34 | return rs; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/RemoveTrips.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | /** 4 | * Remove trips from a graph. 5 | */ 6 | public class RemoveTrips extends Modification { 7 | public String getType () { 8 | return "remove-trips"; 9 | } 10 | 11 | public String feed; 12 | 13 | public String[] routes; 14 | 15 | public String[] patterns; 16 | 17 | public String[] trips; 18 | 19 | public com.conveyal.r5.analyst.scenario.RemoveTrips toR5 () { 20 | com.conveyal.r5.analyst.scenario.RemoveTrips rt = new com.conveyal.r5.analyst.scenario.RemoveTrips(); 21 | rt.comment = name; 22 | 23 | if (trips == null) { 24 | rt.routes = feedScopeIds(feed, routes); 25 | } else { 26 | rt.patterns = feedScopeIds(feed, trips); 27 | } 28 | 29 | return rt; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/models/Segment.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.models; 2 | 3 | import com.conveyal.geojson.GeometryDeserializer; 4 | import com.conveyal.geojson.GeometrySerializer; 5 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 6 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 7 | import org.locationtech.jts.geom.Geometry; 8 | 9 | /** 10 | * Represents a single segment of an added trip pattern (between two user-specified points) 11 | */ 12 | public class Segment { 13 | /** Is there a stop at the start of this segment */ 14 | public boolean stopAtStart; 15 | 16 | /** Is there a stop at the end of this segment */ 17 | public boolean stopAtEnd; 18 | 19 | /** If this segment starts at an existing stop, the feed-scoped stop ID (feed:stop_id). */ 20 | public String fromStopId; 21 | 22 | /** If this segment ends at an existing stop, the feed-scoped stop ID (feed:stop_id). */ 23 | public String toStopId; 24 | 25 | /** spacing between stops in this segment, meters */ 26 | public int spacing; 27 | 28 | /** 29 | * Geometry of this segment 30 | * Generally speaking, this will be a LineString, but the first segment may be a Point 31 | * iff there are no more segments. This is used when someone first starts drawing a line and 32 | * they have only drawn one stop so far. Of course a transit line with only one stop would 33 | * not be particularly useful. 34 | */ 35 | @JsonDeserialize(using= GeometryDeserializer.class) 36 | @JsonSerialize(using= GeometrySerializer.class) 37 | public Geometry geometry; 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/util/BsonObjectIdModule.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.util; 2 | 3 | import com.fasterxml.jackson.core.Version; 4 | import com.fasterxml.jackson.databind.DeserializationContext; 5 | import com.fasterxml.jackson.databind.deser.std.FromStringDeserializer; 6 | import com.fasterxml.jackson.databind.module.SimpleModule; 7 | import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; 8 | import org.bson.types.ObjectId; 9 | 10 | /** 11 | * This provides JSON serialization and deserialization of BSON IDs. 12 | */ 13 | public class BsonObjectIdModule extends SimpleModule { 14 | 15 | public BsonObjectIdModule () { 16 | super("BsonObjectId", new Version(1, 0, 0, null, "com.conveyal", "analysis")); 17 | this.addSerializer(ObjectId.class, new ToStringSerializer()); 18 | this.addDeserializer(ObjectId.class, new FromStringDeserializer<>(ObjectId.class) { 19 | @Override 20 | protected ObjectId _deserialize(String s, DeserializationContext deserializationContext) { 21 | return new ObjectId(s); 22 | } 23 | }); 24 | 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/util/HttpStatus.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.util; 2 | 3 | /** 4 | * It's kind of absurd to have our own set of HTTP status code constants, but I can't find any in the Spark project. 5 | */ 6 | public class HttpStatus { 7 | 8 | public static final int OK_200 = 200; 9 | public static final int ACCEPTED_202 = 202; 10 | public static final int NO_CONTENT_204 = 204; 11 | public static final int BAD_REQUEST_400 = 400; 12 | public static final int SERVER_ERROR_500 = 500; 13 | public static final int SERVICE_UNAVAILABLE = 000; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/util/HttpUtils.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.util; 2 | 3 | import com.conveyal.analysis.AnalysisServerException; 4 | import com.conveyal.r5.util.ExceptionUtils; 5 | import org.apache.commons.fileupload.FileItem; 6 | import org.apache.commons.fileupload.FileItemFactory; 7 | import org.apache.commons.fileupload.disk.DiskFileItemFactory; 8 | import org.apache.commons.fileupload.servlet.ServletFileUpload; 9 | 10 | import javax.servlet.http.HttpServletRequest; 11 | import java.util.List; 12 | import java.util.Map; 13 | 14 | public abstract class HttpUtils { 15 | /** Extract files from a Spark Request containing RFC 1867 multipart form-based file upload data. */ 16 | public static Map> getRequestFiles (HttpServletRequest req) { 17 | // The Javadoc on this factory class doesn't say anything about thread safety. Looking at the source code it 18 | // all looks threadsafe. But also very lightweight to instantiate, so in this code run by multiple threads 19 | // we play it safe and always create a new factory. 20 | // Setting a size threshold of 0 causes all files to be written to disk, which allows processing them in a 21 | // uniform way in other threads, after the request handler has returned. 22 | FileItemFactory fileItemFactory = new DiskFileItemFactory(0, null); 23 | ServletFileUpload sfu = new ServletFileUpload(fileItemFactory); 24 | try { 25 | return sfu.parseParameterMap(req); 26 | } catch (Exception e) { 27 | throw AnalysisServerException.badRequest(ExceptionUtils.asString(e)); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/util/Jobs.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.util; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | 6 | /** 7 | * Contains a shared ExecutorService. 8 | */ 9 | public class Jobs { 10 | public static ExecutorService service = Executors.newCachedThreadPool(); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/analysis/util/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.analysis.util; 2 | 3 | import com.conveyal.analysis.models.JsonViews; 4 | import com.conveyal.geojson.GeoJsonModule; 5 | import com.conveyal.r5.model.json_serialization.JavaLocalDateSerializer; 6 | import com.fasterxml.jackson.databind.DeserializationFeature; 7 | import com.fasterxml.jackson.databind.ObjectMapper; 8 | import org.mongojack.internal.MongoJackModule; 9 | import spark.ResponseTransformer; 10 | 11 | public abstract class JsonUtil { 12 | 13 | public static final ObjectMapper objectMapper = getObjectMapper(JsonViews.Api.class); 14 | public static final ResponseTransformer toJson = objectMapper::writeValueAsString; 15 | 16 | public static ObjectMapper getObjectMapper (Class view) { 17 | return getObjectMapper(view, false); 18 | } 19 | 20 | public static ObjectMapper getObjectMapper(Class view, boolean configureMongoJack) { 21 | ObjectMapper objectMapper = new ObjectMapper(); 22 | objectMapper.registerModule(new GeoJsonModule()); 23 | objectMapper.registerModule(JavaLocalDateSerializer.makeModule()); 24 | objectMapper.registerModule(new BsonObjectIdModule()); 25 | 26 | if (configureMongoJack) MongoJackModule.configure(objectMapper); 27 | 28 | // We removed a bunch of fields from ProfileRequests which are persisted to the database 29 | objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 30 | 31 | objectMapper.setConfig(objectMapper.getSerializationConfig().withView(view)); 32 | 33 | return objectMapper; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/data/census/FileSeamlessSource.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.data.census; 2 | 3 | import java.io.File; 4 | import java.io.FileInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | 8 | /** 9 | * Seamless source for the file system. 10 | */ 11 | public class FileSeamlessSource extends SeamlessSource { 12 | private File directory; 13 | 14 | public FileSeamlessSource(String path) { 15 | this.directory = new File(path); 16 | } 17 | 18 | @Override protected InputStream getInputStream(int x, int y) throws IOException { 19 | File dir = new File(directory, x + ""); 20 | File file = new File(dir, y + ".pbf.gz"); 21 | 22 | if (!file.exists()) 23 | return null; 24 | 25 | return new FileInputStream(file); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/data/census/TigerLineSource.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.data.census; 2 | 3 | import com.conveyal.data.geobuf.GeobufFeature; 4 | import org.geotools.data.FileDataStore; 5 | import org.geotools.data.FileDataStoreFinder; 6 | import org.geotools.data.Query; 7 | import org.geotools.data.simple.SimpleFeatureCollection; 8 | import org.geotools.data.simple.SimpleFeatureIterator; 9 | import org.geotools.data.simple.SimpleFeatureSource; 10 | import org.geotools.referencing.CRS; 11 | 12 | import java.io.File; 13 | import java.util.HashMap; 14 | 15 | /** 16 | * Reads TIGER/Line data into a MapDB. 17 | */ 18 | public class TigerLineSource { 19 | private File shapefile; 20 | 21 | public TigerLineSource (File shapefile) { 22 | this.shapefile = shapefile; 23 | } 24 | 25 | public void load (ShapeDataStore store) throws Exception { 26 | FileDataStore fds = FileDataStoreFinder.getDataStore(shapefile); 27 | SimpleFeatureSource src = fds.getFeatureSource(); 28 | 29 | Query q = new Query(); 30 | q.setCoordinateSystem(src.getInfo().getCRS()); 31 | q.setCoordinateSystemReproject(CRS.decode("EPSG:4326", true)); 32 | SimpleFeatureCollection sfc = src.getFeatures(q); 33 | 34 | for (SimpleFeatureIterator it = sfc.features(); it.hasNext();) { 35 | GeobufFeature feat = new GeobufFeature(it.next()); 36 | feat.id = null; 37 | feat.numericId = Long.parseLong((String) feat.properties.get("GEOID10")); 38 | feat.properties = new HashMap<>(); 39 | store.add(feat); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/data/geobuf/GeobufDecoder.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.data.geobuf; 2 | 3 | import geobuf.Geobuf; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.util.Iterator; 8 | import java.util.List; 9 | 10 | /** 11 | * Decode a Geobuf. 12 | */ 13 | public class GeobufDecoder implements Iterator { 14 | private int maxFeat, i = 0; 15 | 16 | private Geobuf.Data.FeatureCollection featureCollection; 17 | 18 | private List keys; 19 | 20 | private double precisionDivisor; 21 | 22 | /** Create a Geobuf decoder, optionally backed by high-performance on-disk storage */ 23 | public GeobufDecoder (InputStream is) throws IOException { 24 | // read everything into memory 25 | Geobuf.Data data = Geobuf.Data.parseFrom(is); 26 | keys = data.getKeysList(); 27 | featureCollection = data.getFeatureCollection(); 28 | 29 | if (featureCollection == null) 30 | throw new UnsupportedOperationException("Geobuf is not a feature collection"); 31 | 32 | maxFeat = featureCollection.getFeaturesCount(); 33 | 34 | // calculate what to divide coords by; coords are stored as fixed-point longs 35 | precisionDivisor = Math.pow(10, data.getPrecision()); 36 | 37 | is.close(); 38 | } 39 | 40 | @Override public boolean hasNext() { 41 | return i < maxFeat; 42 | } 43 | 44 | @Override public GeobufFeature next() { 45 | return new GeobufFeature(featureCollection.getFeatures(i++), keys, precisionDivisor); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/data/geobuf/ShapefileToGeobuf.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.data.geobuf; 2 | 3 | import org.geotools.data.FileDataStore; 4 | import org.geotools.data.FileDataStoreFinder; 5 | import org.geotools.data.Query; 6 | import org.geotools.data.simple.SimpleFeatureCollection; 7 | import org.geotools.data.simple.SimpleFeatureIterator; 8 | import org.geotools.data.simple.SimpleFeatureSource; 9 | import org.geotools.referencing.CRS; 10 | 11 | import java.io.File; 12 | import java.io.FileOutputStream; 13 | import java.util.ArrayList; 14 | import java.util.Collection; 15 | 16 | /** 17 | * Convert a Shapefile to Geobuf format. 18 | */ 19 | public class ShapefileToGeobuf { 20 | public static void main (String... args) throws Exception { 21 | File inShp = new File(args[0]); 22 | File outGb = new File(args[1]); 23 | 24 | GeobufEncoder encoder = new GeobufEncoder(new FileOutputStream(outGb), 5); 25 | 26 | FileDataStore store = FileDataStoreFinder.getDataStore(inShp); 27 | SimpleFeatureSource src = store.getFeatureSource(); 28 | 29 | Query q = new Query(); 30 | q.setCoordinateSystem(src.getInfo().getCRS()); 31 | q.setCoordinateSystemReproject(CRS.decode("EPSG:4326", true)); 32 | SimpleFeatureCollection sfc = src.getFeatures(q); 33 | 34 | Collection features = new ArrayList<>(); 35 | 36 | for (SimpleFeatureIterator it = sfc.features(); it.hasNext();) { 37 | GeobufFeature feat = new GeobufFeature(it.next()); 38 | features.add(feat); 39 | } 40 | 41 | encoder.writeFeatureCollection(features); 42 | 43 | encoder.close(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/file/FileStorageFormat.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.file; 2 | 3 | public enum FileStorageFormat { 4 | FREEFORM("pointset", "application/octet-stream"), 5 | GRID("grid", "application/octet-stream"), 6 | POINTSET("pointset", "application/octet-stream"), 7 | PNG("png", "image/png"), 8 | TIFF("tiff", "image/tiff"); 9 | 10 | // These are not currently used but plan to be in the future. Exact types need to be determined 11 | // CSV("csv", "text/csv"), 12 | // GTFS("zip", "application/zip"), 13 | // PBF("pbf", "application/octet-stream"), 14 | // SHP("shp", "application/octet-stream") // This type does not work as is, it should be a zip? 15 | 16 | public final String extension; 17 | public final String mimeType; 18 | 19 | FileStorageFormat(String extension, String mimeType) { 20 | this.extension = extension; 21 | this.mimeType = mimeType; 22 | } 23 | 24 | public static FileStorageFormat fromFilename (String filename) { 25 | String extension = filename.substring(filename.lastIndexOf(".") + 1); 26 | return FileStorageFormat.valueOf(extension.toUpperCase()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/api/graphql/WrappedEntityFieldFetcher.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.api.graphql; 2 | 3 | import graphql.schema.DataFetcher; 4 | import graphql.schema.DataFetchingEnvironment; 5 | 6 | import java.lang.reflect.Field; 7 | 8 | /** 9 | * Fetch data from wrapped GTFS entities. Modeled after graphql-java FieldDataFetcher. 10 | */ 11 | public class WrappedEntityFieldFetcher implements DataFetcher { 12 | private final String field; 13 | 14 | public WrappedEntityFieldFetcher (String field) { 15 | this.field = field; 16 | } 17 | 18 | @Override 19 | public Object get(DataFetchingEnvironment dataFetchingEnvironment) { 20 | Object source = dataFetchingEnvironment.getSource(); 21 | 22 | if (source instanceof WrappedGTFSEntity) source = ((WrappedGTFSEntity) source).entity; 23 | 24 | Field field = null; 25 | try { 26 | field = source.getClass().getField(this.field); 27 | } catch (NoSuchFieldException e) { 28 | return null; 29 | } 30 | 31 | try { 32 | return field.get(source); 33 | } catch (IllegalAccessException e) { 34 | throw new RuntimeException(e); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/api/graphql/WrappedGTFSEntity.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.api.graphql; 2 | 3 | /** 4 | * Wraps a GTFS entity, whose own ID may only be unique within the feed, decorating it with the unique ID of the feed 5 | * it came from. 6 | */ 7 | public class WrappedGTFSEntity { 8 | public T entity; 9 | public String feedUniqueId; 10 | 11 | /** 12 | * Wrap the given GTFS entity with the unique Feed ID specified (this is not generally a GTFS feed ID as they 13 | * are not unique between different versions of the same feed. 14 | */ 15 | public WrappedGTFSEntity (String feedUniqueID, T entity) { 16 | this.feedUniqueId = feedUniqueID; 17 | this.entity = entity; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/api/graphql/types/StopTimeType.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.api.graphql.types; 2 | 3 | import com.conveyal.gtfs.api.graphql.fetchers.TripDataFetcher; 4 | import graphql.schema.GraphQLObjectType; 5 | import graphql.schema.GraphQLTypeReference; 6 | 7 | import static com.conveyal.gtfs.api.util.GraphQLUtil.*; 8 | import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition; 9 | import static graphql.schema.GraphQLObjectType.newObject; 10 | 11 | /** 12 | * Created by landon on 10/3/16. 13 | */ 14 | public class StopTimeType { 15 | public static GraphQLObjectType build () { 16 | return newObject() 17 | .name("stopTime") 18 | .field(intt("arrival_time")) 19 | .field(intt("departure_time")) 20 | .field(intt("stop_sequence")) 21 | .field(string("stop_id")) 22 | .field(string("stop_headsign")) 23 | .field(doublee("shape_dist_traveled")) 24 | .field(feed()) 25 | .field(newFieldDefinition() 26 | .name("trip") 27 | .type(new GraphQLTypeReference("trip")) 28 | .dataFetcher(TripDataFetcher::fromStopTime) 29 | .argument(stringArg("date")) 30 | .argument(longArg("from")) 31 | .argument(longArg("to")) 32 | .build() 33 | ) 34 | .build(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/api/util/GeomUtil.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.api.util; 2 | 3 | import org.locationtech.jts.geom.Coordinate; 4 | import org.locationtech.jts.geom.CoordinateList; 5 | import org.locationtech.jts.geom.Envelope; 6 | 7 | /** 8 | * Created by landon on 2/8/16. 9 | */ 10 | public class GeomUtil { 11 | public static Envelope getBoundingBox(Coordinate coordinate, Double radius){ 12 | Envelope boundingBox; 13 | 14 | double R = 6371; // earth radius in km 15 | 16 | // radius argument is also in km 17 | 18 | double x1 = coordinate.x - Math.toDegrees(radius/R/Math.cos(Math.toRadians(coordinate.y))); 19 | 20 | double x2 = coordinate.x + Math.toDegrees(radius/R/Math.cos(Math.toRadians(coordinate.y))); 21 | 22 | double y1 = coordinate.y + Math.toDegrees(radius/R); 23 | 24 | double y2 = coordinate.y - Math.toDegrees(radius/R); 25 | 26 | boundingBox = new Envelope(x1, x2, y1, y2); 27 | 28 | return boundingBox; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/DateParseError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Represents a problem parsing a date field from a GTFS feed. */ 6 | public class DateParseError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public DateParseError(String file, long line, String field) { 10 | super(file, line, field); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return "Could not parse date (format should be YYYYMMDD)."; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/DuplicateKeyError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Indicates that a GTFS entity was not added to a table because another object already exists with the same primary key. */ 6 | public class DuplicateKeyError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public DuplicateKeyError(String file, long line, String field) { 10 | super(file, line, field); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return "Duplicate primary key."; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/DuplicateStopError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.validator.model.DuplicateStops; 4 | 5 | import java.io.Serializable; 6 | 7 | /** Indicates that a stop exists more than once in the feed. */ 8 | public class DuplicateStopError extends GTFSError implements Serializable { 9 | public static final long serialVersionUID = 1L; 10 | 11 | private final String message; 12 | public final DuplicateStops duplicateStop; 13 | 14 | public DuplicateStopError(DuplicateStops duplicateStop) { 15 | super("stop", duplicateStop.getDuplicatedStop().sourceFileLine, "stop_lat,stop_lon", duplicateStop.getDuplicatedStop().stop_id); 16 | this.message = duplicateStop.toString(); 17 | this.duplicateStop = duplicateStop; 18 | } 19 | 20 | @Override public String getMessage() { 21 | return message; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/DuplicateTripError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.model.Trip; 4 | import com.conveyal.gtfs.validator.model.Priority; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Created by landon on 5/6/16. 10 | */ 11 | public class DuplicateTripError extends GTFSError implements Serializable { 12 | public static final long serialVersionUID = 1L; 13 | 14 | public final Priority priority = Priority.LOW; 15 | public final String duplicateTripId; 16 | public final String patternName; 17 | public final String routeId; 18 | String serviceId; 19 | String blockId; 20 | String firstDeparture; 21 | String lastArrival; 22 | 23 | public DuplicateTripError(Trip trip, long line, String duplicateTripId, String patternName, String firstDeparture, String lastArrival) { 24 | super("trips", line, "trip_id", trip.trip_id); 25 | this.duplicateTripId = duplicateTripId; 26 | this.patternName = patternName; 27 | this.routeId = trip.route_id; 28 | this.blockId = trip.block_id; 29 | this.serviceId = trip.service_id; 30 | this.firstDeparture = firstDeparture; 31 | this.lastArrival = lastArrival; 32 | } 33 | 34 | @Override public String getMessage() { 35 | return String.format("Trip Ids %s & %s (route %s) are duplicates (pattern: %s, calendar: %s, from %s to %s)", duplicateTripId, affectedEntityId, routeId, patternName, serviceId, firstDeparture, lastArrival); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/EmptyFieldError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Indicates that a field marked as required is not present in a GTFS feed on a particular line. */ 6 | public class EmptyFieldError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public EmptyFieldError(String file, long line, String field) { 10 | super(file, line, field); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return String.format("No value supplied for a required column."); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/EmptyTableError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by landon on 4/5/17. 7 | */ 8 | public class EmptyTableError extends GTFSError implements Serializable { 9 | public static final long serialVersionUID = 1L; 10 | 11 | public EmptyTableError(String file) { 12 | super(file, 0, null); 13 | } 14 | 15 | @Override public String getMessage() { 16 | return String.format("Table is present in zip file, but it has no entries."); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/GeneralError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Represents any GTFS loading problem that does not have its own class, with a free-text message. */ 6 | public class GeneralError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | private String message; 10 | 11 | public GeneralError(String file, long line, String field, String message) { 12 | super(file, line, field); 13 | this.message = message; 14 | } 15 | 16 | @Override public String getMessage() { 17 | return message; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/MisplacedStopError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.model.Stop; 4 | import com.conveyal.gtfs.validator.model.Priority; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Created by landon on 5/11/16. 10 | */ 11 | public class MisplacedStopError extends GTFSError implements Serializable { 12 | public static final long serialVersionUID = 1L; 13 | 14 | public final Priority priority; 15 | public final Stop stop; 16 | 17 | public MisplacedStopError(String affectedEntityId, long line, Stop stop) { 18 | super("stops", line, "stop_id", affectedEntityId); 19 | this.priority = Priority.HIGH; 20 | this.stop = stop; 21 | } 22 | 23 | @Override public String getMessage() { 24 | return String.format("Stop Id %s is misplaced.", affectedEntityId); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/MissingColumnError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Indicates that a column marked as required is entirely missing from a GTFS feed. */ 6 | public class MissingColumnError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public MissingColumnError(String file, String field) { 10 | super(file, 1, field); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return String.format("Missing required column."); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/MissingShapeError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.model.Trip; 4 | import com.conveyal.gtfs.validator.model.Priority; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Created by landon on 5/6/16. 10 | */ 11 | public class MissingShapeError extends GTFSError implements Serializable { 12 | public static final long serialVersionUID = 1L; 13 | 14 | public final Priority priority = Priority.MEDIUM; 15 | 16 | public MissingShapeError(Trip trip) { 17 | super("trips", trip.sourceFileLine, "shape_id", trip.trip_id); 18 | } 19 | 20 | @Override public String getMessage() { 21 | return "Trip " + affectedEntityId + " is missing a shape"; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/MissingTableError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Indicates that a table marked as required is not present in a GTFS feed. */ 6 | public class MissingTableError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public MissingTableError(String file) { 10 | super(file, 0, null); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return String.format("This table is required by the GTFS specification but is missing."); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/NoAgencyInFeedError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.validator.model.Priority; 4 | 5 | /** 6 | * Created by landon on 5/2/17. 7 | */ 8 | public class NoAgencyInFeedError extends GTFSError { 9 | public final Priority priority = Priority.HIGH; 10 | 11 | public NoAgencyInFeedError() { 12 | super("agency", 0, "agency_id"); 13 | } 14 | 15 | @Override public String getMessage() { 16 | return String.format("No agency listed in feed (must have at least one)."); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/NoTripsForRouteError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | /** 4 | * Created by landon on 5/26/16. 5 | */ 6 | public class NoTripsForRouteError { 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/NumberParseError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Represents a problem parsing an integer field of GTFS feed. */ 6 | public class NumberParseError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public NumberParseError(String file, long line, String field) { 10 | super(file, line, field); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return String.format("Error parsing a number from a string."); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/OverlappingTripsInBlockError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.validator.model.Priority; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by landon on 5/6/16. 9 | */ 10 | public class OverlappingTripsInBlockError extends GTFSError implements Serializable { 11 | public static final long serialVersionUID = 1L; 12 | 13 | public final String[] tripIds; 14 | public final Priority priority = Priority.HIGH; 15 | public final String routeId; 16 | 17 | public OverlappingTripsInBlockError(long line, String field, String affectedEntityId, String routeId, String[] tripIds) { 18 | super("trips", line, field, affectedEntityId); 19 | this.tripIds = tripIds; 20 | this.routeId = routeId; 21 | } 22 | 23 | @Override public String getMessage() { 24 | return String.format("Trip Ids %s overlap (route: %s) and share block ID %s", String.join(" & ", tripIds), routeId, affectedEntityId); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/RangeError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Indicates that a number is out of the acceptable range. */ 6 | public class RangeError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | final double min, max, actual; 10 | 11 | public RangeError(String file, long line, String field, double min, double max, double actual) { 12 | super(file, line, field); 13 | this.min = min; 14 | this.max = max; 15 | this.actual = actual; 16 | } 17 | 18 | @Override public String getMessage() { 19 | return String.format("Number %s outside of acceptable range [%s,%s].", actual, min, max); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/ReferentialIntegrityError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Indicates that an entity referenced another entity that does not exist. */ 6 | public class ReferentialIntegrityError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | // TODO: maybe also store the entity ID of the entity which contained the bad reference, in addition to the row number 10 | public final String badReference; 11 | 12 | public ReferentialIntegrityError(String tableName, long row, String field, String badReference) { 13 | super(tableName, row, field); 14 | this.badReference = badReference; 15 | } 16 | 17 | /** must be comparable to put into mapdb */ 18 | @Override 19 | public int compareTo (GTFSError o) { 20 | int compare = super.compareTo(o); 21 | if (compare != 0) return compare; 22 | return this.badReference.compareTo((((ReferentialIntegrityError) o).badReference)); 23 | } 24 | 25 | @Override public String getMessage() { 26 | return String.format(badReference); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/ReversedTripShapeError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.model.Trip; 4 | import com.conveyal.gtfs.validator.model.Priority; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Created by landon on 5/6/16. 10 | */ 11 | public class ReversedTripShapeError extends GTFSError implements Serializable { 12 | public static final long serialVersionUID = 1L; 13 | 14 | public final Priority priority = Priority.HIGH; 15 | public final String shapeId; 16 | 17 | public ReversedTripShapeError(Trip trip) { 18 | super("trips", trip.sourceFileLine, "shape_id", trip.trip_id); 19 | this.shapeId = trip.shape_id; 20 | } 21 | 22 | @Override public String getMessage() { 23 | return "Trip " + affectedEntityId + " references reversed shape " + shapeId; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/ShapeMissingCoordinatesError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.model.ShapePoint; 4 | import com.conveyal.gtfs.validator.model.Priority; 5 | 6 | import java.io.Serializable; 7 | 8 | /** 9 | * Created by landon on 5/2/16. 10 | */ 11 | public class ShapeMissingCoordinatesError extends GTFSError implements Serializable { 12 | public static final long serialVersionUID = 1L; 13 | 14 | public final Priority priority = Priority.MEDIUM; 15 | public final String[] tripIds; 16 | 17 | public ShapeMissingCoordinatesError(ShapePoint shapePoint, String[] tripIds) { 18 | super("shapes", shapePoint.sourceFileLine, "shape_id", shapePoint.shape_id); 19 | this.tripIds = tripIds; 20 | } 21 | 22 | @Override public String getMessage() { 23 | return "Shape " + affectedEntityId + " is missing coordinates (affects " + tripIds.length + " trips)"; 24 | } 25 | } -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/TableInSubdirectoryError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.validator.model.Priority; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * Created by landon on 10/14/16. 9 | */ 10 | public class TableInSubdirectoryError extends GTFSError implements Serializable { 11 | public static final long serialVersionUID = 1L; 12 | 13 | public final String directory; 14 | public final Priority priority = Priority.HIGH; 15 | 16 | public TableInSubdirectoryError(String file, String directory) { 17 | super(file, 0, null); 18 | this.directory = directory; 19 | } 20 | 21 | @Override public String getMessage() { 22 | return String.format("All GTFS files (including %s.txt) should be at root of zipfile, not nested in subdirectory (%s)", file, directory); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/TimeParseError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Represents a problem parsing a time of day field of GTFS feed. */ 6 | public class TimeParseError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public TimeParseError(String file, long line, String field) { 10 | super(file, line, field); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return "Could not parse time (format should be HH:MM:SS)."; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/TimeZoneError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * Created by landon on 5/11/16. 7 | */ 8 | 9 | public class TimeZoneError extends GTFSError implements Serializable { 10 | public static final long serialVersionUID = 1L; 11 | 12 | public final String message; 13 | 14 | /** 15 | * 16 | * @param tableName name of table where error was found 17 | * @param line line of invalid timezone reference 18 | * @param field name of field for invalid timezone reference (agency_timezone or stop_timezone) 19 | * @param affectedEntityId stop or agency ID of the invalid timezone reference 20 | * @param message description of issue with timezone reference 21 | */ 22 | public TimeZoneError(String tableName, long line, String field, String affectedEntityId, String message) { 23 | super(tableName, line, field, affectedEntityId); 24 | this.message = message; 25 | } 26 | 27 | @Override public String getMessage() { 28 | return message + ". (" + field + ": " + affectedEntityId + ")"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/URLParseError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import java.io.Serializable; 4 | 5 | /** Represents a problem parsing a URL field from a GTFS feed. */ 6 | public class URLParseError extends GTFSError implements Serializable { 7 | public static final long serialVersionUID = 1L; 8 | 9 | public URLParseError(String file, long line, String field) { 10 | super(file, line, field); 11 | } 12 | 13 | @Override public String getMessage() { 14 | return "Could not parse URL (format should be ://?#)."; 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/UnusedStopError.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.error; 2 | 3 | import com.conveyal.gtfs.model.Stop; 4 | import com.conveyal.gtfs.validator.model.Priority; 5 | 6 | import java.io.Serializable; 7 | 8 | /** Indicates that a stop exists more than once in the feed. */ 9 | public class UnusedStopError extends GTFSError implements Serializable { 10 | public static final long serialVersionUID = 1L; 11 | 12 | public final Priority priority; 13 | public final Stop stop; 14 | 15 | public UnusedStopError(Stop stop) { 16 | super("stops", stop.sourceFileLine, "stop_id", stop.stop_id); 17 | this.priority = Priority.LOW; 18 | this.stop = stop; 19 | } 20 | 21 | @Override public String getMessage() { 22 | return String.format("Stop Id %s is not used in any trips.", affectedEntityId); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/error/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains all the objects that represent errors encountered during GTFS loading. 3 | */ 4 | package com.conveyal.gtfs.error; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/BooleanField.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | import com.conveyal.gtfs.storage.StorageException; 4 | 5 | import java.sql.JDBCType; 6 | import java.sql.PreparedStatement; 7 | import java.sql.SQLType; 8 | 9 | /** 10 | * A GTFS boolean field, coded as a single character string 0 or 1. 11 | */ 12 | public class BooleanField extends Field { 13 | 14 | public BooleanField (String name, Requirement requirement) { 15 | super(name, requirement); 16 | } 17 | 18 | private boolean validate (String string) { 19 | if ( ! ("0".equals(string) || "1".equals(string))) throw new StorageException("Field must be 0 or 1."); 20 | return "1".equals(string); 21 | } 22 | 23 | @Override 24 | public void setParameter (PreparedStatement preparedStatement, int oneBasedIndex, String string) { 25 | try { 26 | preparedStatement.setBoolean(oneBasedIndex, validate(string)); 27 | } catch (Exception ex) { 28 | throw new StorageException(ex); 29 | } 30 | } 31 | 32 | /** 33 | * The 0 or 1 will be converted to the string "true" or "false" for SQL COPY. 34 | */ 35 | @Override 36 | public String validateAndConvert (String string) { 37 | return Boolean.toString(validate(string)); 38 | } 39 | 40 | @Override 41 | public SQLType getSqlType () { 42 | return JDBCType.BOOLEAN; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/Requirement.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | /** 4 | * Created by abyrd on 2017-03-30 5 | */ 6 | public enum Requirement { 7 | REQUIRED, // Required by the GTFS spec 8 | OPTIONAL, // Optional according to the GTFS spec 9 | EXTENSION, // Extension proposed and documented on gtfs-changes 10 | PROPRIETARY, // Known proprietary extension that is not yet an official proposal 11 | UNKNOWN // Undocumented proprietary extension 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/SQLEntityFetcher.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | import java.sql.PreparedStatement; 4 | 5 | /** 6 | * Created by abyrd on 2017-04-04 7 | */ 8 | public abstract class SQLEntityFetcher implements Iterable { 9 | 10 | EntityPopulator entityPopulator; 11 | 12 | public SQLEntityFetcher (PreparedStatement fetchAllStatement, EntityPopulator entityPopulator) { 13 | this.entityPopulator = entityPopulator; 14 | } 15 | 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/ShortField.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | import com.conveyal.gtfs.storage.StorageException; 4 | 5 | import java.sql.JDBCType; 6 | import java.sql.PreparedStatement; 7 | import java.sql.SQLType; 8 | 9 | /** 10 | * Created by abyrd on 2017-03-31 11 | */ 12 | public class ShortField extends Field { 13 | 14 | private int maxValue; // can be shared with all numeric field types? 15 | 16 | public ShortField (String name, Requirement requirement, int maxValue) { 17 | super(name, requirement); 18 | this.maxValue = maxValue; 19 | } 20 | 21 | private short validate (String string) { 22 | if (string == null || string.isEmpty()) return 0; // Default numeric fields to zero. 23 | short s = Short.parseShort(string); 24 | if (s < 0) throw new StorageException("negative field in " + name ); 25 | // TODO enforce 26 | // if (s > maxValue) throw new StorageException("excessively large short integer value in field " + name); 27 | return s; 28 | } 29 | 30 | @Override 31 | public void setParameter(PreparedStatement preparedStatement, int oneBasedIndex, String string) { 32 | try { 33 | preparedStatement.setShort(oneBasedIndex, validate(string)); 34 | } catch (Exception ex) { 35 | throw new StorageException(ex); 36 | } 37 | } 38 | 39 | @Override 40 | public String validateAndConvert(String string) { 41 | validate(string); 42 | return string; 43 | } 44 | 45 | @Override 46 | public SQLType getSqlType () { 47 | return JDBCType.SMALLINT; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/StringField.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | import com.conveyal.gtfs.storage.StorageException; 4 | 5 | import java.sql.JDBCType; 6 | import java.sql.PreparedStatement; 7 | import java.sql.SQLType; 8 | 9 | /** 10 | * Created by abyrd on 2017-03-31 11 | */ 12 | public class StringField extends Field { 13 | 14 | public StringField (String name, Requirement requirement) { 15 | super(name, requirement); 16 | } 17 | 18 | /** Check that a string can be properly parsed and is in range. */ 19 | public String validateAndConvert (String string) { 20 | return cleanString(string); 21 | } 22 | 23 | public void setParameter(PreparedStatement preparedStatement, int oneBasedIndex, String string) { 24 | try { 25 | preparedStatement.setString(oneBasedIndex, validateAndConvert(string)); 26 | } catch (Exception ex) { 27 | throw new StorageException(ex); 28 | } 29 | } 30 | 31 | @Override 32 | public SQLType getSqlType() { 33 | return JDBCType.VARCHAR; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/TableReader.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | import com.conveyal.gtfs.model.Entity; 4 | 5 | /** 6 | * This is an interface for classes that can iterate over all entities in a single GTFS table, or fetch single entities 7 | * by ID, or fetch ordered groups of entities with the same ID (e.g. all stop times with the same trip_id). 8 | * Created by abyrd on 2017-04-06 9 | */ 10 | public interface TableReader extends Iterable { 11 | 12 | public T get (String id); 13 | 14 | // public Iterable getAll (); 15 | 16 | // public Iterable getAllOrdered (); 17 | 18 | public Iterable getOrdered (String id); 19 | 20 | public void close (); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/TimeField.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | import com.conveyal.gtfs.storage.StorageException; 4 | 5 | import java.sql.JDBCType; 6 | import java.sql.PreparedStatement; 7 | import java.sql.SQLType; 8 | 9 | /** 10 | * A field in the format HH:MM:SS, which will be stored as a number of seconds after midnight. 11 | */ 12 | public class TimeField extends Field { 13 | 14 | public TimeField(String name, Requirement requirement) { 15 | super(name, requirement); 16 | } 17 | 18 | @Override 19 | public void setParameter(PreparedStatement preparedStatement, int oneBasedIndex, String string) { 20 | try { 21 | preparedStatement.setInt(oneBasedIndex, getSeconds(string)); 22 | } catch (Exception ex) { 23 | throw new StorageException(ex); 24 | } 25 | } 26 | 27 | // Actually this is converting the string. Can we use some JDBC existing functions for this? 28 | @Override 29 | public String validateAndConvert(String hhmmss) { 30 | return Integer.toString(getSeconds(hhmmss)); 31 | } 32 | 33 | private static int getSeconds (String hhmmss) { 34 | if (hhmmss.length() != 8) { 35 | throw new StorageException("Time field should be 8 characters long."); 36 | } 37 | String[] fields = hhmmss.split(":"); 38 | int h = Integer.parseInt(fields[0]); 39 | int m = Integer.parseInt(fields[1]); 40 | int s = Integer.parseInt(fields[2]); 41 | return ((h * 60) + m) * 60 + s; 42 | } 43 | 44 | @Override 45 | public SQLType getSqlType () { 46 | return JDBCType.INTEGER; 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/loader/URLField.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.loader; 2 | 3 | import com.conveyal.gtfs.storage.StorageException; 4 | 5 | import java.sql.JDBCType; 6 | import java.sql.PreparedStatement; 7 | import java.sql.SQLType; 8 | 9 | /** 10 | * Created by abyrd on 2017-03-31 11 | */ 12 | public class URLField extends Field { 13 | 14 | public URLField(String name, Requirement requirement) { 15 | super(name, requirement); 16 | } 17 | 18 | /** Check that a string can be properly parsed and is in range. */ 19 | public String validateAndConvert (String string) { 20 | try { 21 | string = cleanString(string); 22 | // new URL(cleanString); TODO call this to validate, but we can't default to zero 23 | return string; 24 | } catch (Exception ex) { 25 | throw new StorageException(ex); 26 | } 27 | } 28 | 29 | public void setParameter(PreparedStatement preparedStatement, int oneBasedIndex, String string) { 30 | try { 31 | preparedStatement.setString(oneBasedIndex, validateAndConvert(string)); 32 | } catch (Exception ex) { 33 | throw new StorageException(ex); 34 | } 35 | } 36 | 37 | @Override 38 | public SQLType getSqlType() { 39 | return JDBCType.VARCHAR; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/model/Fare.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.model; 2 | 3 | import com.google.common.collect.Lists; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | /** 9 | * This table does not exist in GTFS. It is a join of fare_attributes and fare_rules on fare_id. 10 | * There should only be one fare_attribute per fare_id, but there can be many fare_rules per fare_id. 11 | */ 12 | public class Fare implements Serializable { 13 | public static final long serialVersionUID = 1L; 14 | 15 | public String fare_id; 16 | public FareAttribute fare_attribute; 17 | public List fare_rules = Lists.newArrayList(); 18 | 19 | public Fare(String fare_id) { 20 | this.fare_id = fare_id; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/model/Shape.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.model; 2 | 3 | import com.conveyal.gtfs.GTFSFeed; 4 | import org.locationtech.jts.geom.Coordinate; 5 | import org.locationtech.jts.geom.LineString; 6 | import org.mapdb.Fun; 7 | 8 | import java.util.Map; 9 | 10 | import static com.conveyal.gtfs.util.GeometryUtil.geometryFactory; 11 | 12 | /** 13 | * Represents a collection of GTFS shape points. Never saved in MapDB but constructed on the fly. 14 | */ 15 | public class Shape { 16 | /** The shape itself */ 17 | public LineString geometry; 18 | 19 | /** shape_dist_traveled for each point in the geometry. TODO how to handle shape dist traveled not specified, or not specified on all stops? */ 20 | public double[] shape_dist_traveled; 21 | 22 | public Shape (GTFSFeed feed, String shape_id) { 23 | Map, ShapePoint> points = 24 | feed.shape_points.subMap(new Fun.Tuple2(shape_id, null), new Fun.Tuple2(shape_id, Fun.HI)); 25 | 26 | Coordinate[] coords = points.values().stream() 27 | .map(point -> new Coordinate(point.shape_pt_lon, point.shape_pt_lat)) 28 | .toArray(i -> new Coordinate[i]); 29 | geometry = geometryFactory.createLineString(coords); 30 | shape_dist_traveled = points.values().stream().mapToDouble(point -> point.shape_dist_traveled).toArray(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/model/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains an alternative to the GTFS loading classes we have been using from OBA. 3 | * It loads GTFS into a disk-backed map and attempts to be relatively efficient space-wise. 4 | * The intent is to eliminate the need for AgencyAndIds, using feed IDs and keeping each feed in its own 5 | * separate data structure. 6 | */ 7 | package com.conveyal.gtfs.model; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/storage/StorageException.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.storage; 2 | 3 | import com.conveyal.gtfs.error.NewGTFSErrorType; 4 | 5 | /** 6 | * Created by abyrd on 2017-03-25 7 | */ 8 | public class StorageException extends RuntimeException { 9 | 10 | public NewGTFSErrorType errorType = NewGTFSErrorType.OTHER; 11 | 12 | public String badValue = null; 13 | 14 | public StorageException(NewGTFSErrorType errorType, String badValue) { 15 | super(errorType.englishMessage); 16 | this.errorType = errorType; 17 | this.badValue = badValue; 18 | } 19 | 20 | public StorageException(Exception ex) { 21 | super(ex); 22 | } 23 | 24 | public StorageException (String message) { 25 | super(message); 26 | } 27 | 28 | public StorageException(String message, Exception ex) { 29 | super(message, ex); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/util/Renamer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.util; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | import java.util.UUID; 6 | 7 | /** 8 | * Creates new unique names to give things new IDs. 9 | */ 10 | public class Renamer { 11 | 12 | private Map newNameForOldName = new HashMap<>(); 13 | private Map oldNameForNewName = new HashMap<>(); 14 | 15 | public String getNewName(String oldName) { 16 | String newName = newNameForOldName.get(oldName); 17 | if (newName == null) { 18 | while (newName == null || oldNameForNewName.containsKey(newName)) { 19 | newName = UUID.randomUUID().toString().substring(0, 6); 20 | } 21 | newNameForOldName.put(oldName, newName); 22 | oldNameForNewName.put(newName, oldName); 23 | System.out.println(oldName + " <--> " + newName); 24 | } 25 | return newName; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/util/json/Rectangle2DDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.util.json; 2 | 3 | import com.fasterxml.jackson.core.JsonParseException; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.databind.DeserializationContext; 6 | import com.fasterxml.jackson.databind.JsonDeserializer; 7 | 8 | import java.awt.geom.Rectangle2D; 9 | import java.io.IOException; 10 | 11 | public class Rectangle2DDeserializer extends JsonDeserializer { 12 | 13 | @Override 14 | public Rectangle2D deserialize(JsonParser jp, DeserializationContext arg1) throws IOException { 15 | 16 | IntermediateBoundingBox bbox = jp.readValueAs(IntermediateBoundingBox.class); 17 | 18 | if (bbox.north == null || bbox.south == null || bbox.east == null || bbox.west == null) 19 | throw new JsonParseException("Unable to deserialize bounding box; need north, south, east, and west.", jp.getCurrentLocation()); 20 | 21 | Rectangle2D.Double ret = new Rectangle2D.Double(bbox.west, bbox.north, 0, 0); 22 | ret.add(bbox.east, bbox.south); 23 | return ret; 24 | } 25 | 26 | /** 27 | * A place to hold information from the JSON stream temporarily. 28 | */ 29 | private static class IntermediateBoundingBox { 30 | public Double north; 31 | public Double south; 32 | public Double east; 33 | public Double west; 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/util/json/Rectangle2DMixIn.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.util.json; 2 | 3 | import com.fasterxml.jackson.annotation.JsonFilter; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | 6 | // ignore all by default 7 | @JsonFilter("bbox") 8 | public abstract class Rectangle2DMixIn { 9 | // stored as lon, lat 10 | @JsonProperty("west") public abstract double getMinX(); 11 | @JsonProperty("east") public abstract double getMaxX(); 12 | @JsonProperty("north") public abstract double getMaxY(); 13 | @JsonProperty("south") public abstract double getMinY(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/validator/model/DuplicateStops.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.validator.model; 2 | 3 | import com.conveyal.gtfs.model.Stop; 4 | 5 | import java.io.Serializable; 6 | 7 | public class DuplicateStops implements Serializable { 8 | 9 | public Stop stop1; 10 | public Stop stop2; 11 | 12 | public double distance; 13 | 14 | public DuplicateStops(Stop s1, Stop s2, double dist) { 15 | stop1 = s1; 16 | stop2 = s2; 17 | distance = dist; 18 | } 19 | public Stop getOriginalStop () { return stop1.sourceFileLine < stop2.sourceFileLine ? stop1 : stop2; } 20 | 21 | public Stop getDuplicatedStop () { return stop1.sourceFileLine > stop2.sourceFileLine ? stop1 : stop2; } 22 | 23 | public String getStop1Id() { 24 | return stop1.stop_id; 25 | } 26 | 27 | public String getStop2Id() { 28 | return stop2.stop_id; 29 | } 30 | 31 | public String getStopIds() { 32 | return this.getStop1Id() + "," + this.getStop2Id(); 33 | } 34 | 35 | public String toString() { 36 | return "Stops " + this.getStop1Id() + " and " + this.getStop2Id() + " are within " + this.distance + " meters"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/validator/model/Priority.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.validator.model; 2 | 3 | public enum Priority { 4 | /** 5 | * Something that is likely to break routing results, 6 | * e.g. stop times out of sequence or high-speed travel 7 | */ 8 | HIGH, 9 | 10 | /** 11 | * Something that is likely to break display, but still give accurate routing results, 12 | * e.g. broken shapes or route long name containing route short name. 13 | */ 14 | MEDIUM, 15 | 16 | /** 17 | * Something that will not affect user experience but should be corrected as time permits, 18 | * e.g. unused stops. 19 | */ 20 | LOW, 21 | 22 | /** 23 | * An error for which we do not have a priority 24 | */ 25 | UNKNOWN 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/gtfs/validator/service/ProjectedCoordinate.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.validator.service; 2 | 3 | import org.locationtech.jts.geom.Coordinate; 4 | import org.opengis.referencing.operation.MathTransform; 5 | 6 | public class ProjectedCoordinate extends Coordinate { 7 | 8 | private static final long serialVersionUID = 2905131060296578237L; 9 | 10 | final private MathTransform transform; 11 | final private Coordinate refLatLon; 12 | 13 | public ProjectedCoordinate(MathTransform mathTransform, 14 | Coordinate to, Coordinate refLatLon) { 15 | this.transform = mathTransform; 16 | this.x = to.x; 17 | this.y = to.y; 18 | this.refLatLon = refLatLon; 19 | } 20 | 21 | public String epsgCode() { 22 | final String epsgCode = 23 | "EPSG:" + GeoUtils.getEPSGCodefromUTS(refLatLon); 24 | return epsgCode; 25 | } 26 | 27 | public Coordinate getReferenceLatLon() { 28 | return refLatLon; 29 | } 30 | 31 | public MathTransform getTransform() { 32 | return transform; 33 | } 34 | 35 | public double getX() 36 | { 37 | return this.x; 38 | } 39 | 40 | public double getY() 41 | { 42 | return this.y; 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/Node.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | import java.io.Serializable; 4 | 5 | public class Node extends OSMEntity implements Serializable { 6 | 7 | private static final long serialVersionUID = 1L; 8 | 9 | // PBF uses 100 nanodegrees (1e7) by default. (180 * 10^7) / (2^31) ~= 0.84 so we should be fine. 10 | private static final double FIXED_PRECISION_FACTOR = 1e7; 11 | 12 | public Node () { } 13 | 14 | public Node (double lat, double lon) { 15 | setLatLon(lat, lon); 16 | } 17 | 18 | /* Angles are stored as fixed precision 32 bit integers because 32 bit floats are not sufficiently precise. */ 19 | public int fixedLat; 20 | public int fixedLon; 21 | 22 | public double getLat() {return fixedLat / FIXED_PRECISION_FACTOR;} 23 | 24 | public double getLon() {return fixedLon / FIXED_PRECISION_FACTOR;} 25 | 26 | public void setLatLon (double lat, double lon) { 27 | this.fixedLat = (int)(lat * FIXED_PRECISION_FACTOR); 28 | this.fixedLon = (int)(lon * FIXED_PRECISION_FACTOR); 29 | } 30 | 31 | @Override 32 | public Type getType() { 33 | return Type.NODE; 34 | } 35 | 36 | public String toString() { 37 | return "[Node "+getLat()+" "+getLon()+"]"; 38 | } 39 | 40 | @Override 41 | public boolean equals(Object other) { 42 | if ( ! (other instanceof Node)) return false; 43 | Node otherNode = (Node) other; 44 | return this.fixedLat == otherNode.fixedLat && 45 | this.fixedLon == otherNode.fixedLon && 46 | this.tagsEqual(otherNode); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/VexFormat.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | public abstract class VexFormat { 4 | 5 | public static final byte[] HEADER = "VEXFMT".getBytes(); 6 | 7 | // FIXME use OSMEntity.Type or Classes themselves 8 | public static final int VEX_NODE = 0; 9 | public static final int VEX_WAY = 1; 10 | public static final int VEX_RELATION = 2; 11 | public static final int VEX_NONE = 3; 12 | 13 | // TODO OSM layer support 14 | public static final int LAYER_ANY = 0; 15 | public static final int LAYER_STREET = 1; 16 | public static final int LAYER_LANDUSE = 2; 17 | public static final int LAYER_BUILDING = 3; 18 | 19 | // TODO helper methods that give etype for class, int for etype, etc. 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/Way.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | import java.io.Serializable; 4 | import java.util.Arrays; 5 | 6 | public class Way extends OSMEntity implements Serializable { 7 | 8 | private static final long serialVersionUID = 1L; 9 | 10 | public long[] nodes; 11 | 12 | @Override 13 | public String toString() { 14 | return String.format("Way with %d tags and %d nodes", tags.size(), nodes.length); 15 | } 16 | 17 | @Override 18 | public Type getType() { 19 | return Type.WAY; 20 | } 21 | 22 | @Override 23 | public boolean equals(Object other) { 24 | if ( ! (other instanceof Way)) return false; 25 | Way otherWay = (Way) other; 26 | return Arrays.equals(this.nodes, otherWay.nodes) && this.tagsEqual(otherWay); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/WebMercatorTile.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | /** 4 | * 5 | */ 6 | public class WebMercatorTile { 7 | 8 | //http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/ 9 | public final int ZOOM = 12; 10 | public final int xtile, ytile; 11 | 12 | /** 13 | * Tile definition equations from: TODO URL 14 | */ 15 | public WebMercatorTile(double lat, double lon) { 16 | xtile = (int) Math.floor((lon + 180) / 360 * (1 << ZOOM)); 17 | ytile = (int) Math.floor((1 - Math.log(Math.tan(Math.toRadians(lat)) 18 | + 1 / Math.cos(Math.toRadians(lat))) / Math.PI) / 2 * (1 << ZOOM)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/display/GraphicsSink.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib.display; 2 | 3 | import com.conveyal.osmlib.Node; 4 | import com.conveyal.osmlib.OSMEntitySink; 5 | import com.conveyal.osmlib.Relation; 6 | import com.conveyal.osmlib.Way; 7 | 8 | import java.awt.*; 9 | import java.awt.geom.Line2D; 10 | import java.io.IOException; 11 | import java.time.Instant; 12 | import java.time.ZoneId; 13 | 14 | /** 15 | * 16 | */ 17 | public class GraphicsSink implements OSMEntitySink { 18 | 19 | Graphics2D g2d; 20 | 21 | public GraphicsSink(Graphics2D g2d) { 22 | this.g2d = g2d; 23 | } 24 | 25 | @Override 26 | public void writeBegin() throws IOException { 27 | 28 | } 29 | 30 | @Override 31 | public void setReplicationTimestamp(long secondsSinceEpoch) { 32 | g2d.drawString(Instant.ofEpochSecond(secondsSinceEpoch).atZone(ZoneId.systemDefault()).toString(), 0, 0); 33 | } 34 | 35 | @Override 36 | public void writeNode(long id, Node node) throws IOException { 37 | Shape line = new Line2D.Double(node.getLon(), node.getLat(), node.getLon(), node.getLat()); 38 | g2d.draw(line); 39 | } 40 | 41 | @Override 42 | public void writeWay(long id, Way way) throws IOException { 43 | 44 | } 45 | 46 | @Override 47 | public void writeRelation(long id, Relation relation) throws IOException { 48 | 49 | } 50 | 51 | @Override 52 | public void writeEnd() throws IOException { 53 | 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/main/Converter.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib.main; 2 | 3 | import com.conveyal.osmlib.OSMEntitySink; 4 | import com.conveyal.osmlib.OSMEntitySource; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.io.IOException; 9 | 10 | public class Converter { 11 | 12 | private static final Logger LOG = LoggerFactory.getLogger(Converter.class); 13 | 14 | /** 15 | * This main method will load a file into the osm-lib representation and write it back out as a stream, 16 | * without using an intermediate MapDB. File types are detected from the file name extensions. 17 | */ 18 | public static void main(String[] args) { 19 | 20 | // Get input and output file names 21 | if (args.length < 2) { 22 | System.err.println("usage: Convert input.[pbf|vex] output.[pbf|vex|txt]"); 23 | System.exit(0); 24 | } 25 | String inputPath = args[0]; 26 | String outputPath = args[1]; 27 | 28 | // Pump the entities from the input file directly to the output file. 29 | long startTime = System.currentTimeMillis(); 30 | try { 31 | OSMEntitySource source = OSMEntitySource.forFile(inputPath); 32 | OSMEntitySink sink = OSMEntitySink.forFile(outputPath); 33 | source.copyTo(sink); 34 | } catch (IOException ex) { 35 | throw new RuntimeException(ex); 36 | } 37 | LOG.info("Total run time: {} sec", (System.currentTimeMillis() - startTime)/1000D); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/main/SpeedSetter.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib.main; 2 | 3 | import com.conveyal.osmlib.OSM; 4 | import com.conveyal.osmlib.Way; 5 | 6 | import java.io.BufferedReader; 7 | import java.io.File; 8 | import java.io.FileReader; 9 | 10 | /** 11 | * This is an example utility main method for setting speeds from a csv file. 12 | * It's meant to be run from an IDE as part of a data preparation pipeline. 13 | */ 14 | public class SpeedSetter { 15 | 16 | public static void main (String[] args) throws Exception { 17 | OSM osm = new OSM(null); 18 | osm.readFromFile("/Users/abyrd/predicted_speeds_2015_for_conveyal.pbf"); 19 | 20 | System.out.println("Setting maxspeed:motorcar tags..."); 21 | File speedsFile = new File("/Users/abyrd/predicted_speeds_2015_for_conveyal.csv"); 22 | try(BufferedReader br = new BufferedReader(new FileReader(speedsFile))) { 23 | br.readLine(); // skip headers 24 | for(String line; (line = br.readLine()) != null; ) { 25 | String[] fields = line.split(","); 26 | long osmWayId = Long.parseLong(fields[0]); 27 | double speedKph = Double.parseDouble(fields[1]); 28 | Way way = osm.ways.get(osmWayId); 29 | // R5 currently prioritizes maxspeed:motorcar above all other maxspeed tags 30 | way.addOrReplaceTag("maxspeed:motorcar", String.format("%1.1f kph", speedKph)); 31 | osm.ways.put(osmWayId, way); 32 | } 33 | } 34 | osm.writeToFile("/Users/abyrd/predicted_speeds_output.pbf"); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package duplicates functionality in the data model classes in org.otp.openstreetmap, but is designed for 3 | * loading OSM data into disk-backed maps in a more space efficient manner so that the OSM data can be retained for 4 | * later use. It is not yet used by OTP. 5 | */ 6 | package com.conveyal.osmlib; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/serializer/NodeSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib.serializer; 2 | 3 | import com.conveyal.osmlib.Node; 4 | import org.mapdb.Serializer; 5 | 6 | import java.io.DataInput; 7 | import java.io.DataOutput; 8 | import java.io.IOException; 9 | import java.io.Serializable; 10 | 11 | public class NodeSerializer implements Serializer, Serializable { 12 | 13 | @Override 14 | public void serialize(DataOutput out, Node node) throws IOException { 15 | out.writeInt(node.fixedLat); 16 | out.writeInt(node.fixedLon); 17 | VarInt.writeTags(out, node); 18 | } 19 | 20 | @Override 21 | public Node deserialize(DataInput in, int available) throws IOException { 22 | Node node = new Node(); 23 | node.fixedLat = in.readInt(); 24 | node.fixedLon = in.readInt(); 25 | VarInt.readTags(in, node); 26 | return node; 27 | } 28 | 29 | @Override 30 | public int fixedSize() { 31 | return -1; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/serializer/WaySerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib.serializer; 2 | 3 | import com.conveyal.osmlib.Way; 4 | import org.mapdb.Serializer; 5 | 6 | import java.io.DataInput; 7 | import java.io.DataOutput; 8 | import java.io.IOException; 9 | import java.io.Serializable; 10 | 11 | /** Ideally, these serializers would be the same ones used in the VEX binary exchange format. */ 12 | public class WaySerializer implements Serializer, Serializable { 13 | 14 | /** Delta-code the series of node references, and write out all values as varints. */ 15 | @Override 16 | public void serialize(DataOutput out, Way way) throws IOException { 17 | VarInt.writeRawVarint32(out, way.nodes.length); 18 | long lastNodeId = 0; 19 | for (int i = 0; i < way.nodes.length; i++) { 20 | long delta = way.nodes[i] - lastNodeId; 21 | VarInt.writeSInt64NoTag(out, delta); 22 | lastNodeId = way.nodes[i]; 23 | } 24 | VarInt.writeTags(out, way); 25 | } 26 | 27 | @Override 28 | public Way deserialize(DataInput in, int available) throws IOException { 29 | Way way = new Way(); 30 | int nNodes = VarInt.readRawVarint32(in); 31 | way.nodes = new long[nNodes]; 32 | long lastNodeId = 0; 33 | for (int i = 0; i < nNodes; i++) { 34 | lastNodeId += VarInt.readSInt64(in); 35 | way.nodes[i] = lastNodeId; 36 | } 37 | VarInt.readTags(in, way); 38 | return way; 39 | } 40 | 41 | @Override 42 | public int fixedSize() { return -1; } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/osmlib/serializer/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains custom MapDB serializers for OTP's OSM data model. 3 | * Without them, the 70MB DC PBF becomes a 248MB MapDB 4 | * With them, using compression and variable-byte encodings, it becomes a 158MB MapDB 5 | */ 6 | package com.conveyal.osmlib.serializer; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/OneOriginResult.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5; 2 | 3 | import com.conveyal.r5.analyst.AccessibilityResult; 4 | import com.conveyal.r5.analyst.cluster.TravelTimeResult; 5 | 6 | /** 7 | * This provides a single return type (for internal R5 use) for all the kinds of results we can get from a travel time 8 | * computer and reducer for a single origin point. Currently, these results include travel times to points in a 9 | * destination pointset, and accessibility indicator values for various travel time cutoffs and percentiles of travel 10 | * time. 11 | * 12 | * TODO add fields to record travel time breakdowns into wait and ride and walk time, and paths to destinations. 13 | */ 14 | public class OneOriginResult { 15 | 16 | public final TravelTimeResult travelTimes; 17 | 18 | public final AccessibilityResult accessibility; 19 | 20 | public OneOriginResult(TravelTimeResult travelTimes, AccessibilityResult accessibility) { 21 | this.travelTimes = travelTimes; 22 | this.accessibility = accessibility; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/ByteArrayOutputInputStream.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.InputStream; 6 | 7 | /** 8 | * An OutputStream that buffers everything in memory, allowing the contents of that buffer to be read back out as an 9 | * InputStream. This works around the fact that ByteArrayOutputStream.toByteArray makes a copy of the backing byte 10 | * array, doubling memory consumption and wasting time. 11 | */ 12 | public class ByteArrayOutputInputStream extends ByteArrayOutputStream { 13 | 14 | /** 15 | * @return an input stream wrapping the internal byte buffer. Further writes are not possible. 16 | */ 17 | public InputStream getInputStream () { 18 | try { 19 | this.close(); 20 | InputStream inputStream = new ByteArrayInputStream(buf); 21 | // Prevent additional writes to the internal buffer. 22 | buf = null; 23 | return inputStream; 24 | } catch (Exception e) { 25 | throw new RuntimeException(e); 26 | } 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/FileCategory.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst; 2 | 3 | /** 4 | * For use by FilePersistence. Avoids specifying bucket names or subfolders with Strings. 5 | */ 6 | public enum FileCategory { 7 | 8 | POLYGON, // Only this one is currently used, others are examples 9 | GRID, 10 | BUNDLE; 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/LittleEndianIntOutputStream.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst; 2 | 3 | import java.io.FilterOutputStream; 4 | import java.io.IOException; 5 | import java.io.OutputStream; 6 | import java.nio.charset.Charset; 7 | 8 | /** 9 | * Class to output ints. An order of magnitude faster than Guava LittleEndianDataOutputStream. 10 | */ 11 | public class LittleEndianIntOutputStream extends FilterOutputStream { 12 | public LittleEndianIntOutputStream(OutputStream out) { 13 | super(out); 14 | } 15 | 16 | public void writeInt (int value) throws IOException { 17 | byte[] bytes = new byte[]{ 18 | (byte) (value & 0xff), 19 | (byte) (value >> 8 & 0xff), 20 | (byte) (value >> 16 & 0xff), 21 | (byte) (value >> 24 & 0xff) 22 | }; 23 | 24 | out.write(bytes); 25 | } 26 | 27 | /** Write an ASCII string as bytes, generally used as a header */ 28 | public void writeAscii(String string) throws IOException { 29 | byte[] bytes = string.getBytes(Charset.forName("ASCII")); 30 | out.write(bytes); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/WorkerCategory.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst; 2 | 3 | import java.io.Serializable; 4 | import java.util.Objects; 5 | 6 | /** 7 | * This identifies a category of workers that are all running the same R5 commit and have the same graph loaded. 8 | * TODO perhaps this is a TaskCategory rather than a WorkerCategory. 9 | */ 10 | public class WorkerCategory implements Comparable, Serializable { 11 | 12 | public final String graphId; 13 | public final String workerVersion; 14 | 15 | public WorkerCategory(String graphId, String workerCommit) { 16 | this.graphId = graphId; 17 | this.workerVersion = workerCommit; 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "graph ID '" + graphId + '\'' + ", worker version '" + workerVersion + '\''; 23 | } 24 | 25 | @Override 26 | public boolean equals(Object o) { 27 | if (this == o) return true; 28 | if (o == null || getClass() != o.getClass()) return false; 29 | WorkerCategory that = (WorkerCategory) o; 30 | return Objects.equals(graphId, that.graphId) && 31 | Objects.equals(workerVersion, that.workerVersion); 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return Objects.hash(graphId, workerVersion); 37 | } 38 | 39 | @Override 40 | public int compareTo (WorkerCategory other) { 41 | int result = this.graphId.compareTo(other.graphId); 42 | return result == 0 ? this.workerVersion.compareTo(other.workerVersion) : result; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/cluster/BundleManifest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.cluster; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Originally transportation data "bundles" were a zip file of GTFS files and OSM files. 7 | * OSM data is no longer specific to a GTFS feed, at least within our UI. OSM is now associated with a whole project. 8 | * So "new-style" bundles are no longer zip files of data, they are just references to OSM and GTFS files on S3. 9 | * The fields in this class do not contain filenames but IDs that will be sanitized and have file extensions added 10 | * before being looked up as S3 objects. 11 | */ 12 | public class BundleManifest { 13 | /** ID of the OSM file, for use with OSMCache */ 14 | public String osmId; 15 | 16 | /** IDs of the GTFS files, for use with GTFSCache */ 17 | public List gtfsIds; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/cluster/WorkerNotReadyException.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.cluster; 2 | 3 | import com.conveyal.r5.transit.TransportNetwork; 4 | import com.conveyal.r5.util.AsyncLoader; 5 | 6 | /** 7 | * This exception is thrown to indicate that a function cannot complete because it's still asynchronously loading 8 | * data it needs to perform its calculations. It implies that the thrower has already recorded the need for 9 | * those data and has begun an attempt to prepare them. 10 | * 11 | * Created by abyrd on 2018-10-30 12 | */ 13 | public class WorkerNotReadyException extends Exception { 14 | 15 | public final AsyncLoader.LoaderState asyncLoaderState; 16 | 17 | public WorkerNotReadyException(AsyncLoader.LoaderState asyncLoaderState) { 18 | super(asyncLoaderState.toString()); 19 | this.asyncLoaderState = asyncLoaderState; 20 | } 21 | 22 | public boolean isError() { 23 | return asyncLoaderState.status == AsyncLoader.Status.ERROR; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/decay/ExponentialDecayFunction.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.decay; 2 | 3 | import org.apache.commons.math3.util.FastMath; 4 | 5 | /** 6 | * This an exponential decay function where the cutoff parameter c is treated as the half-life. 7 | * So rather than working with the base e, we use: N(t) = 2^(-t/c) = 0.5^(t/c) 8 | * Exp() is usually faster than the more general pow(). 9 | * Since pow(x,y) = exp(y*log(x)) and we generally hold c constant while varying t: 10 | * N(t) = exp(log(0.5) * t/c) 11 | * JIT may be smart enough to factor the (log(0.5)/cutoff) out of the series of method calls, without us needing to 12 | * create specific function instances with precomputed constants for each separate cutoff. 13 | */ 14 | public class ExponentialDecayFunction extends DecayFunction { 15 | 16 | private static final double logOneHalf = FastMath.log(0.5); 17 | 18 | @Override 19 | public double computeWeight (int cutoffSeconds, int travelTimeSeconds) { 20 | if (travelTimeSeconds <= 0) { 21 | return 1; 22 | } 23 | if (travelTimeSeconds >= TWO_HOURS_IN_SECONDS) { 24 | return 0; 25 | } 26 | return FastMath.exp(logOneHalf / cutoffSeconds * travelTimeSeconds); 27 | } 28 | 29 | @Override 30 | public void prepare () { } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/decay/StepDecayFunction.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.decay; 2 | 3 | /** 4 | * Simple cliff-edge weight function. No parameters to set or validate. 5 | */ 6 | public class StepDecayFunction extends DecayFunction { 7 | 8 | @Override 9 | public void prepare () { 10 | // Nothing to validate or prepare. 11 | } 12 | 13 | @Override 14 | public int reachesZeroAt (int cutoffSeconds) { 15 | return cutoffSeconds; 16 | } 17 | 18 | @Override 19 | public double computeWeight (int cutoffSeconds, int travelTimeSeconds) { 20 | if (travelTimeSeconds < cutoffSeconds) { 21 | return 1; 22 | } else { 23 | return 0; 24 | } 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/error/ScenarioApplicationException.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.error; 2 | 3 | import com.conveyal.r5.analyst.scenario.Modification; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * This Exception is thrown when a Scenario does not apply cleanly to a TransportNetwork. 10 | * We make an effort to recover from scenario application errors so that we can report as many errors as possible at once. 11 | * This Exception should contain one TaskError object for each Modification within the Scenario that failed to apply. 12 | */ 13 | public class ScenarioApplicationException extends RuntimeException { 14 | 15 | /** The structured error reports that can be sent back to the client via the broker. */ 16 | public final List taskErrors = new ArrayList<>(); 17 | 18 | /** 19 | * Pass in all the modifications that failed. 20 | * The warning messages will be extracted and they will be converted to TaskErrors. 21 | * @param badModifications 22 | */ 23 | public ScenarioApplicationException(List badModifications) { 24 | super("Errors occurred while applying a scenario to a network."); 25 | for (Modification modification : badModifications) { 26 | taskErrors.add(new TaskError(modification, modification.errors)); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/error/UnsupportedGeometryException.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.error; 2 | 3 | public class UnsupportedGeometryException extends Exception { 4 | 5 | public String message; 6 | 7 | public UnsupportedGeometryException(String message) { 8 | this.message = message; 9 | } 10 | 11 | } -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/fare/FareBounds.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.fare; 2 | 3 | /** 4 | * Used in InRoutingFareCalculator (and its extensions) to track how much has been paid to reach a state 5 | * (cumulativeFarePaid) and transfer privileges that may be redeemed at future boardings (transferAllowance). We need 6 | * to track the latter to protect certain states from premature pruning in Pareto search. 7 | */ 8 | 9 | public class FareBounds { 10 | public int cumulativeFarePaid; // cash already paid, cumulatively for all previous journey stages 11 | public TransferAllowance transferAllowance; // possible remaining value; how much you stand to lose if you 12 | // throw your ticket on the ground 13 | 14 | public FareBounds(int cumulativeFarePaid, TransferAllowance transferAllowance){ 15 | this.cumulativeFarePaid = cumulativeFarePaid; 16 | this.transferAllowance = transferAllowance; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/fare/SimpleInRoutingFareCalculator.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.fare; 2 | 3 | import com.conveyal.r5.profile.McRaptorSuboptimalPathProfileRouter; 4 | 5 | /** 6 | * A simple greedy fare calculator that simply applies a single fare at each boarding. 7 | */ 8 | public class SimpleInRoutingFareCalculator extends InRoutingFareCalculator { 9 | public int fare; 10 | 11 | @Override 12 | public FareBounds calculateFare(McRaptorSuboptimalPathProfileRouter.McRaptorState state, int maxClockTime) { 13 | int fareForState = 0; 14 | 15 | while (state != null) { 16 | if (state.pattern != -1) fareForState += fare; 17 | state = state.back; 18 | } 19 | 20 | return new FareBounds(fareForState, new TransferAllowance()); 21 | } 22 | 23 | @Override 24 | public String getType() { 25 | return "simple"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/fare/ZoneBasedFareSystem.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.fare; 2 | 3 | import java.util.Map; 4 | 5 | /* 6 | Fares specified only by origin_id and destination_id. 7 | */ 8 | 9 | public class ZoneBasedFareSystem { 10 | public Map fareByZonePair; 11 | 12 | public class Pair { 13 | String origin_id; // zone_id of stop at start of journey stage 14 | String destination_id; // zone_id of stop at end of journey stage 15 | 16 | public Pair(String origin_id, String destination_id){ 17 | this.origin_id = origin_id; 18 | this.destination_id = destination_id; 19 | } 20 | } 21 | 22 | public void addZonePair(String origin_id, String destination_id, int price) { 23 | Pair pair = new Pair(origin_id, destination_id); 24 | fareByZonePair.put(pair, price); 25 | } 26 | 27 | public int getFare(String origin_id, String destination_id){ 28 | Pair pair = new Pair(origin_id, destination_id); 29 | return fareByZonePair.get(pair); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/fare/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This contains fare calculation implementations that are used in accessibility analysis to apply cost limits while 3 | * a search is happening. This is a resource limiting problem and requires pareto-path routing. It's a distinct 4 | * problem from calculating fares for Modeify or normal point to point routing, where fares are not considered during 5 | * routing and are only calculated after the path is already found. 6 | */ 7 | package com.conveyal.r5.analyst.fare; 8 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/progress/NoopProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.progress; 2 | 3 | public class NoopProgressListener implements ProgressListener { 4 | 5 | @Override 6 | public void beginTask(String description, int totalElements) { 7 | 8 | } 9 | 10 | @Override 11 | public void increment() { 12 | 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/progress/ProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.progress; 2 | 3 | /** 4 | * This interface provides simple callbacks to allow long running, asynchronous operations to report on their progress. 5 | */ 6 | public interface ProgressListener { 7 | 8 | /** 9 | * Call this method once at the beginning of a new task, specifying how many sub-units of work will be performed. 10 | * This does not allow for subsequently starting sub-tasks that use the same ProgressListener while progress is 11 | * still being reported. Any recursion launching sub-tasks will need to be head- or tail-recursion, launched before 12 | * you call beginTask or after the last unit of work is complete. 13 | * Rather than implementing some kind of push/pop mechanism, we may eventually have some kind of nested task system, 14 | * where all tasks are retrieved in a hierarchy and progress on sub-tasks bubbles up to super-tasks. 15 | * Or alternatively, we may never recurse into lazy-loading code, which is probably a better long term goal. 16 | */ 17 | void beginTask(String description, int totalElements); 18 | 19 | /** 20 | * Call this method to report that one unit of work has been performed. 21 | */ 22 | void increment(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/progress/TaskAction.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.progress; 2 | 3 | /** 4 | * This represents the work actually carried out by a Task. 5 | * It's a single-method interface so it can be defined with lambda functions, or other objects can implement it. 6 | * When the action is run, it will receive an object implementing an interface through which it can report progress 7 | * and errors. 8 | */ 9 | public interface TaskAction { 10 | 11 | /** 12 | * This method will define an asynchronous action to take. 13 | * The parameter is a simpler interface of Task that only allows progress reporting, to encapsulate actions and 14 | * prevent them from seeing or modifying the task hierarchy that triggers and manages them. 15 | */ 16 | public void action (ProgressListener progressListener); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/scenario/ModificationPolygon.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.scenario; 2 | 3 | import org.locationtech.jts.geom.Geometry; 4 | import org.locationtech.jts.geom.Polygonal; 5 | 6 | /** 7 | * This associates a single Polygonal Geometry with a name, numerical data, and a priority relative to other polygons 8 | * in the same set. 9 | */ 10 | public class ModificationPolygon { 11 | 12 | public final Geometry polygonal; 13 | public final String id; 14 | public final String name; 15 | public final double data; 16 | public final double priority; 17 | 18 | public ModificationPolygon ( 19 | Polygonal polygonal, 20 | String id, 21 | String name, 22 | double data, 23 | double priority 24 | ) { 25 | this.polygonal = (Geometry) polygonal; 26 | this.id = id; 27 | this.name = name; 28 | this.data = data; 29 | this.priority = priority; 30 | } 31 | 32 | } 33 | 34 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/scenario/SetFareCalculator.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.scenario; 2 | 3 | import com.conveyal.r5.analyst.fare.InRoutingFareCalculator; 4 | import com.conveyal.r5.transit.TransportNetwork; 5 | 6 | /** 7 | * Set the fare calculator on a transport network. 8 | */ 9 | public class SetFareCalculator extends Modification { 10 | public InRoutingFareCalculator fareCalculator; 11 | 12 | @Override 13 | public boolean apply(TransportNetwork network) { 14 | // NB will break if applied more than once, but don't think that should happen 15 | network.fareCalculator = this.fareCalculator; 16 | network.fareCalculator.transitLayer = network.transitLayer; 17 | return false; 18 | } 19 | 20 | @Override 21 | public int getSortOrder() { 22 | return 100; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/analyst/scenario/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains classes for modeling transport scenarios as an ordered series of modifications to be applied 3 | * to an underlying baseline graph. It is used for impact analysis: the interactive creation and comparison of the 4 | * accessibility effects of modifications to a transport network. 5 | */ 6 | package com.conveyal.r5.analyst.scenario; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/GraphQlRequest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | /** 6 | * Dummy request for GraphQL 7 | * 8 | * Since GraphQL request is in JSON Jackson needs this to parse it correctly. 9 | */ 10 | @JsonIgnoreProperties(ignoreUnknown = true) 11 | public class GraphQlRequest { 12 | public String query; 13 | //FIXME: This should be Map and be serialized automatically with Jackson but it 14 | //doesn't seems to work. 15 | public String variables; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/AbsoluteDirection.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | 4 | /** 5 | * An absolute cardinal or intermediate direction. 6 | */ 7 | public enum AbsoluteDirection { 8 | NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST 9 | } -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/Alert.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | import java.time.ZonedDateTime; 4 | 5 | /** 6 | * Simple alert 7 | */ 8 | public class Alert { 9 | 10 | //TODO: localization etc. 11 | 12 | //Header of alert if it exists 13 | public String alertHeaderText; 14 | 15 | /** 16 | * Long description of alert notnull 17 | */ 18 | public String alertDescriptionText; 19 | 20 | //Url with more information 21 | public String alertUrl; 22 | 23 | //When this alerts comes into effect 24 | public ZonedDateTime effectiveStartDate; 25 | public ZonedDateTime effectiveEndDate; 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/BikeRentalStation.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | import java.io.Serializable; 4 | import java.util.Set; 5 | 6 | /** 7 | * Information about Bike rental station 8 | */ 9 | public class BikeRentalStation implements Serializable { 10 | 11 | //@notnull 12 | public String id; 13 | 14 | public String name; 15 | 16 | //Coordinates @notnull 17 | public float lat, lon; 18 | 19 | public int bikesAvailable; 20 | 21 | public int spacesAvailable; 22 | 23 | public boolean allowDropoff = true; 24 | 25 | public Set networks; 26 | 27 | public boolean realTimeData = false; 28 | 29 | @Override 30 | public String toString() { 31 | String sb = "BikeRentalStation{" + "id='" + id + '\'' + 32 | ", name='" + name + '\'' + 33 | ", lat=" + lat + 34 | ", lon=" + lon + 35 | ", bikesAvailable=" + bikesAvailable + 36 | ", spacesAvailable=" + spacesAvailable + 37 | ", allowDropoff=" + allowDropoff + 38 | ", networks=" + networks + 39 | ", realTimeData=" + realTimeData + 40 | '}'; 41 | return sb; 42 | } 43 | } -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/Coordinate.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * Input type for profile 5 | */ 6 | public class Coordinate { 7 | public float lat; 8 | public float lon; 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/Elevation.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * TODO: this could also be copressed like Mapquest is doing 5 | */ 6 | public class Elevation { 7 | //Distance from start of segment in meters @notnull 8 | public float distance; 9 | //Height in m at this distance @notnull 10 | public float elevation; 11 | 12 | public Elevation(float distance, float height) { 13 | this.distance = distance; 14 | this.elevation = height; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/ModeStopIndex.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | import java.util.Objects; 4 | 5 | /** 6 | * Used as a key so that access and egress paths are not duplicated and are each inserted only once in each profileOption 7 | * 8 | */ 9 | public class ModeStopIndex { 10 | public LegMode mode; 11 | public int stopIndex; 12 | 13 | public ModeStopIndex(LegMode mode, int stopIndex) { 14 | this.mode = mode; 15 | this.stopIndex = stopIndex; 16 | } 17 | 18 | @Override 19 | public boolean equals(Object o) { 20 | if (this == o) 21 | return true; 22 | if (o == null || getClass() != o.getClass()) 23 | return false; 24 | ModeStopIndex that = (ModeStopIndex) o; 25 | return stopIndex == that.stopIndex && mode == that.mode; 26 | } 27 | 28 | @Override 29 | public int hashCode() { 30 | return Objects.hash(mode, stopIndex); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/NonTransitMode.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * Modes of transportation that aren't public transit 5 | */ 6 | public enum NonTransitMode { 7 | WALK, BICYCLE, CAR 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/PointToPointConnection.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Object which pulls together specific access, transit and egress part of an option 7 | */ 8 | public class PointToPointConnection { 9 | //Index of access part of this trip @notnull 10 | public int access; 11 | //Index of egress part of this trip 12 | public Integer egress; 13 | /*chooses which specific trip should be used 14 | Index in transit list specifies transit with same index 15 | Each TransitJourneyID has pattern in chosen index an time index in chosen pattern 16 | 17 | This can uniquly identify specific trip with transit */ 18 | public List transit; 19 | 20 | //Connection for transit modes 21 | public PointToPointConnection(int accessIdx, int egressIdx, 22 | List transitJourneyIDs) { 23 | access = accessIdx; 24 | egress = egressIdx; 25 | transit = transitJourneyIDs; 26 | } 27 | 28 | //Connection for direct modes 29 | public PointToPointConnection(int accessIndex) { 30 | access = accessIndex; 31 | egress = null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/PolylineGeometry.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | import com.conveyal.r5.model.json_serialization.LineStringDeserializer; 4 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 5 | import org.locationtech.jts.geom.LineString; 6 | 7 | /** 8 | * Created by mabu on 30.10.2015. 9 | */ 10 | public class PolylineGeometry { 11 | 12 | /** 13 | * Polyline encoded geometry 14 | * @notnull 15 | */ 16 | @JsonDeserialize(using = LineStringDeserializer.class) 17 | public LineString points; 18 | 19 | /** 20 | * Length of polyline encoded geometry 21 | * @notnull 22 | */ 23 | public int length; 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/RelativeDirection.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * Represents a turn direction, relative to the current heading. 5 | * 6 | * CIRCLE_CLOCKWISE and CIRCLE_CLOCKWISE are used to represent traffic circles. 7 | * 8 | */ 9 | public enum RelativeDirection { 10 | DEPART, HARD_LEFT, LEFT, SLIGHTLY_LEFT, CONTINUE, SLIGHTLY_RIGHT, RIGHT, HARD_RIGHT, 11 | CIRCLE_CLOCKWISE, CIRCLE_COUNTERCLOCKWISE, ELEVATOR, UTURN_LEFT, UTURN_RIGHT; 12 | 13 | public static RelativeDirection setRelativeDirection(double lastAngle, double thisAngle, boolean roundabout) { 14 | double turn_degree = (((thisAngle - lastAngle) + 360) % 360); 15 | 16 | double ccw_turn_degree = 360 - turn_degree; 17 | 18 | if (roundabout) { 19 | if (turn_degree > ccw_turn_degree) { 20 | return CIRCLE_CLOCKWISE; 21 | } else { 22 | return CIRCLE_COUNTERCLOCKWISE; 23 | } 24 | } 25 | 26 | if (turn_degree < 17 || ccw_turn_degree < 17) { 27 | return CONTINUE; 28 | } else if (turn_degree < 40) { 29 | return SLIGHTLY_RIGHT; 30 | } else if (ccw_turn_degree < 40) { 31 | return SLIGHTLY_LEFT; 32 | } else if (turn_degree < 115) { 33 | return RIGHT; 34 | } else if (ccw_turn_degree < 115) { 35 | return LEFT; 36 | } else if (turn_degree < 180) { 37 | return HARD_RIGHT; 38 | } else { 39 | return HARD_LEFT; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/SearchType.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * Type of plan search 5 | */ 6 | public enum SearchType { 7 | //Search is made for trip that needs to arrive at specific time/date 8 | ARRIVE_BY, 9 | //Search is made for a trip that needs to depart at specific time/date 10 | DEPART_FROM 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/Stats.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * num may be 0 if there are no observations. 5 | * num will become 1 when adding a scalar or another Stats. 6 | */ 7 | public class Stats implements Cloneable { 8 | 9 | /** 10 | * Minimum travel time (seconds) 11 | * @notnull 12 | */ 13 | public int min = Integer.MAX_VALUE; 14 | 15 | /** 16 | * Average travel time (including waiting) (seconds) 17 | * @notnull 18 | */ 19 | public int avg = 0; 20 | 21 | /** 22 | * Maximum travel time (seconds) 23 | * @notnull 24 | */ 25 | public int max = 0; 26 | 27 | /** 28 | * number of options 29 | * @notnull 30 | */ 31 | public int num = 0; 32 | 33 | /** Construct a new empty Stats containing no values. */ 34 | public Stats () { } 35 | 36 | @Override 37 | public String toString() { 38 | return String.format("min=%.1f avg=%.1f max=%.1f", min/60.0, avg/60.0, max/60.0); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/TransitJourneyID.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * Tells which pattern and time in pattern to use for this specific transit 5 | * 6 | * Created by mabu on 21.12.2015. 7 | */ 8 | public class TransitJourneyID { 9 | //Index of segment pattern @notnull 10 | public int pattern; 11 | //index of time in chosen pattern @notnull 12 | public int time; 13 | 14 | public TransitJourneyID(int patternIdx, int timeIdx) { 15 | pattern = patternIdx; 16 | time = timeIdx; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/TransitModes.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * Types of transit mode transport from GTFS 5 | */ 6 | public enum TransitModes { 7 | // Air 8 | AIR, 9 | // Tram, Streetcar, Light rail. Any light rail or street level system within a metropolitan area. 10 | TRAM, 11 | //Subway, Metro. Any underground rail system within a metropolitan area. 12 | SUBWAY, 13 | //Rail. Used for intercity or long-distance travel. 14 | RAIL, 15 | //Bus. Used for short- and long-distance bus routes. 16 | BUS, 17 | //Ferry. Used for short- and long-distance boat service. 18 | FERRY, 19 | //Cable car. Used for street-level cable cars where the cable runs beneath the car. 20 | CABLE_CAR, 21 | // Gondola, Suspended cable car. Typically used for aerial cable cars where the car is suspended from the cable. 22 | GONDOLA, 23 | //Funicular. Any rail system designed for steep inclines. 24 | FUNICULAR, 25 | //All modes 26 | TRANSIT 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/api/util/Trip.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.api.util; 2 | 3 | /** 4 | * One specific GTFS trip 5 | */ 6 | public class Trip { 7 | /** 8 | * GTFS trip ID 9 | * @notnull 10 | */ 11 | public String tripId; 12 | 13 | /** 14 | * Generated Service ID 15 | */ 16 | public String serviceId; 17 | 18 | 19 | public Boolean wheelchairAccessible = false; 20 | 21 | public Boolean bikesAllowed = false; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/common/GeoJsonFeature.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.common; 2 | 3 | import org.locationtech.jts.geom.Coordinate; 4 | import org.locationtech.jts.geom.Geometry; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * GeoJSON Feature class 11 | * 12 | * Written because GeoJSON Feature class from geojson-jackson has different type of Geometry 13 | * and needs a conversion 14 | * 15 | * Currently only used in TransportNetworkVisualizer 16 | */ 17 | public class GeoJsonFeature { 18 | //for serialization 19 | private final String type = "Feature"; 20 | private Map properties; 21 | 22 | private Geometry geometry; 23 | 24 | public GeoJsonFeature(Geometry geometry) { 25 | this.geometry = geometry; 26 | this.properties = new HashMap<>(5); 27 | } 28 | 29 | public GeoJsonFeature(double lon, double lat) { 30 | this(GeometryUtils.geometryFactory.createPoint(new Coordinate(lon, lat))); 31 | } 32 | 33 | public String getType() { 34 | return type; 35 | } 36 | 37 | public Map getProperties() { 38 | return properties; 39 | } 40 | 41 | public Geometry getGeometry() { 42 | return geometry; 43 | } 44 | 45 | public void addProperty(String propertyName, Object propertyValue) { 46 | properties.put(propertyName, propertyValue); 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/labeling/RoadPermission.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.labeling; 2 | 3 | import com.conveyal.r5.streets.EdgeStore; 4 | 5 | import java.util.EnumSet; 6 | 7 | /** 8 | * Class providing a return type for functions in the TraversalPermissionLabeler, which need to return a set of 9 | * permissions in both the forward and backward direction on a single road segment. 10 | */ 11 | public class RoadPermission { 12 | public final EnumSet forward; 13 | public final EnumSet backward; 14 | 15 | public RoadPermission(EnumSet forward, 16 | EnumSet backward) { 17 | this.forward = forward; 18 | this.backward = backward; 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/labeling/USTraversalPermissionLabeler.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.labeling; 2 | 3 | 4 | /** 5 | * Traversal permission labeler for the United States, adding things that differ from the base TraversalPermissionLabeler. 6 | * https://wiki.openstreetmap.org/wiki/OSM_tags_for_routing/Access-Restrictions#United_States_of_America 7 | */ 8 | public class USTraversalPermissionLabeler extends TraversalPermissionLabeler { 9 | static { 10 | addPermissions("pedestrian", "bicycle=yes"); 11 | addPermissions("bridleway", "bicycle=yes;foot=yes"); //horse=yes but we don't support horse 12 | addPermissions("cycleway", "bicycle=yes;foot=yes"); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/labeling/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Labelers set flags or characteristics of network links based on tags in the OSM data they are built from. 3 | */ 4 | package com.conveyal.r5.labeling; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/BitSetDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.core.JsonToken; 6 | import com.fasterxml.jackson.databind.DeserializationContext; 7 | import com.fasterxml.jackson.databind.JsonDeserializer; 8 | 9 | import java.io.IOException; 10 | import java.util.BitSet; 11 | 12 | /** 13 | * Deserialize an array [true, false, true . . .] to a bitset 14 | */ 15 | public class BitSetDeserializer extends JsonDeserializer { 16 | @Override public BitSet deserialize(JsonParser jsonParser, 17 | DeserializationContext deserializationContext) 18 | throws IOException, JsonProcessingException { 19 | BitSet ret = new BitSet(); 20 | 21 | int i = 0; 22 | JsonToken token; 23 | while (!JsonToken.END_ARRAY.equals(token = jsonParser.nextValue())) { 24 | if (JsonToken.VALUE_TRUE.equals(token)) 25 | ret.set(i); 26 | i++; 27 | } 28 | 29 | return ret; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/BitSetSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.core.Version; 6 | import com.fasterxml.jackson.databind.JsonSerializer; 7 | import com.fasterxml.jackson.databind.SerializerProvider; 8 | import com.fasterxml.jackson.databind.module.SimpleModule; 9 | 10 | import java.io.IOException; 11 | import java.util.BitSet; 12 | 13 | /** 14 | * Serialize a BitSet to an array [true, false . . .]. 15 | */ 16 | public class BitSetSerializer extends JsonSerializer { 17 | 18 | @Override public void serialize(BitSet bitSet, JsonGenerator jsonGenerator, 19 | SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 20 | 21 | jsonGenerator.writeStartArray(); 22 | 23 | for (int i = 0; i < bitSet.length(); i++) { 24 | jsonGenerator.writeBoolean(bitSet.get(i)); 25 | } 26 | 27 | jsonGenerator.writeEndArray(); 28 | } 29 | 30 | public static SimpleModule makeModule () { 31 | Version moduleVersion = new Version(1, 0, 0, null, null, null); 32 | SimpleModule module = new SimpleModule("BitSet", moduleVersion); 33 | module.addSerializer(BitSet.class, new BitSetSerializer()); 34 | module.addDeserializer(BitSet.class, new BitSetDeserializer()); 35 | return module; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/JavaLocalDateDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.DeserializationContext; 6 | import com.fasterxml.jackson.databind.JsonDeserializer; 7 | 8 | import java.io.IOException; 9 | import java.time.LocalDate; 10 | import java.time.format.DateTimeFormatter; 11 | 12 | /** serializer/deserializer for LocalDates to ISO dates, YYYY-MM-DD */ 13 | public class JavaLocalDateDeserializer extends JsonDeserializer { 14 | 15 | @Override public LocalDate deserialize(JsonParser jsonParser, 16 | DeserializationContext deserializationContext) 17 | throws IOException, JsonProcessingException { 18 | return LocalDate.parse(jsonParser.getValueAsString(), DateTimeFormatter.ISO_LOCAL_DATE); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/JavaLocalDateSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.core.Version; 6 | import com.fasterxml.jackson.databind.JsonSerializer; 7 | import com.fasterxml.jackson.databind.SerializerProvider; 8 | import com.fasterxml.jackson.databind.module.SimpleModule; 9 | 10 | import java.io.IOException; 11 | import java.time.LocalDate; 12 | import java.time.format.DateTimeFormatter; 13 | 14 | /** 15 | * Serialize localDates to YYYY-MM-DD 16 | */ 17 | public class JavaLocalDateSerializer extends JsonSerializer { 18 | /** Create a module including the serializer and deserializer for local dates */ 19 | public static SimpleModule makeModule () { 20 | Version moduleVersion = new Version(1, 0, 0, null, null, null); 21 | SimpleModule module = new SimpleModule("LocalDate", moduleVersion); 22 | module.addSerializer(LocalDate.class, new JavaLocalDateSerializer()); 23 | module.addDeserializer(LocalDate.class, new JavaLocalDateDeserializer()); 24 | return module; 25 | } 26 | 27 | @Override public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, 28 | SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 29 | jsonGenerator.writeString(localDate.format(DateTimeFormatter.ISO_LOCAL_DATE)); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/LegModeSetDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.conveyal.r5.api.util.LegMode; 4 | import com.fasterxml.jackson.core.JsonParser; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.DeserializationContext; 7 | import com.fasterxml.jackson.databind.JsonDeserializer; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.io.IOException; 12 | import java.util.EnumSet; 13 | import java.util.stream.Stream; 14 | 15 | /** 16 | * Deserialize modesets in the form MODE,MODE,MODE 17 | */ 18 | public class LegModeSetDeserializer extends JsonDeserializer> { 19 | private static final Logger LOG = LoggerFactory.getLogger(LegModeSetDeserializer.class); 20 | 21 | @Override 22 | public EnumSet deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { 23 | String str = jsonParser.getValueAsString(); 24 | EnumSet modes = EnumSet.noneOf(LegMode.class); 25 | Stream.of(str.split(",")).forEach(m -> { 26 | LegMode mode; 27 | try { 28 | mode = LegMode.valueOf(m.toUpperCase().trim()); 29 | } catch (IllegalArgumentException e) { 30 | LOG.info("LegMode {} not found, ignoring (if this is an obscure transit mode, this message is safe to ignore)", m); 31 | return; 32 | } 33 | 34 | modes.add(mode); 35 | }); 36 | return modes; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/LegModeSetSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.conveyal.r5.api.util.LegMode; 4 | import com.fasterxml.jackson.core.JsonGenerator; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.JsonSerializer; 7 | import com.fasterxml.jackson.databind.SerializerProvider; 8 | 9 | import java.io.IOException; 10 | import java.util.EnumSet; 11 | import java.util.stream.Collectors; 12 | 13 | /** 14 | * Serialize a mode set as MODE,MODE,MODE 15 | */ 16 | public class LegModeSetSerializer extends JsonSerializer> { 17 | @Override 18 | public void serialize(EnumSet modes, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 19 | String str = modes.stream().map(LegMode::toString).collect(Collectors.joining(",")); 20 | jsonGenerator.writeString(str); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/LineStringDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.DeserializationContext; 6 | import com.fasterxml.jackson.databind.JsonDeserializer; 7 | import org.locationtech.jts.geom.GeometryFactory; 8 | import org.locationtech.jts.geom.LineString; 9 | 10 | import java.io.IOException; 11 | 12 | /** 13 | * A Jackson serializer module for reading Google encoded polylines into LineStrings. 14 | */ 15 | public class LineStringDeserializer extends JsonDeserializer { 16 | 17 | private static GeometryFactory geometryFactory = new GeometryFactory(); 18 | 19 | @Override 20 | public LineString deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) 21 | throws IOException, JsonProcessingException { 22 | return geometryFactory.createLineString(PolyUtil.decode(jsonParser.getText())); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/LineStringSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.JsonSerializer; 6 | import com.fasterxml.jackson.databind.SerializerProvider; 7 | import org.locationtech.jts.geom.LineString; 8 | 9 | import java.io.IOException; 10 | 11 | /** 12 | * A Jackson serializer module for saving LineStrings as Google encoded polylines. 13 | */ 14 | public class LineStringSerializer extends JsonSerializer { 15 | 16 | @Override 17 | public void serialize(LineString lineString, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) 18 | throws IOException, JsonProcessingException { 19 | jsonGenerator.writeString(PolyUtil.encode(lineString)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/ModeSetSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.conveyal.r5.profile.StreetMode; 4 | import com.fasterxml.jackson.core.JsonGenerator; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.JsonSerializer; 7 | import com.fasterxml.jackson.databind.SerializerProvider; 8 | 9 | import java.io.IOException; 10 | import java.util.EnumSet; 11 | import java.util.stream.Collectors; 12 | 13 | /** 14 | * Serialize a mode set as MODE,MODE,MODE 15 | */ 16 | public class ModeSetSerializer extends JsonSerializer> { 17 | @Override 18 | public void serialize(EnumSet streetModes, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 19 | String str = streetModes.stream().map(StreetMode::toString).collect(Collectors.joining(",")); 20 | jsonGenerator.writeString(str); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/TransitModeSetSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.conveyal.r5.api.util.TransitModes; 4 | import com.fasterxml.jackson.core.JsonGenerator; 5 | import com.fasterxml.jackson.core.JsonProcessingException; 6 | import com.fasterxml.jackson.databind.JsonSerializer; 7 | import com.fasterxml.jackson.databind.SerializerProvider; 8 | 9 | import java.io.IOException; 10 | import java.util.EnumSet; 11 | import java.util.stream.Collectors; 12 | 13 | /** 14 | * Serialize a mode set as MODE,MODE,MODE 15 | */ 16 | public class TransitModeSetSerializer extends JsonSerializer> { 17 | @Override 18 | public void serialize(EnumSet modes, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 19 | String str = modes.stream().map(TransitModes::toString).collect(Collectors.joining(",")); 20 | jsonGenerator.writeString(str); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/ZoneIdDeserializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonParser; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.DeserializationContext; 6 | import com.fasterxml.jackson.databind.JsonDeserializer; 7 | 8 | import java.io.IOException; 9 | import java.time.ZoneId; 10 | 11 | /** 12 | * Deserialize a ZoneId from a string 13 | */ 14 | public class ZoneIdDeserializer extends JsonDeserializer { 15 | @Override public ZoneId deserialize(JsonParser jsonParser, 16 | DeserializationContext deserializationContext) 17 | throws IOException, JsonProcessingException { 18 | return ZoneId.of(jsonParser.getValueAsString()); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/model/json_serialization/ZoneIdSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.model.json_serialization; 2 | 3 | import com.fasterxml.jackson.core.JsonGenerator; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.JsonSerializer; 6 | import com.fasterxml.jackson.databind.SerializerProvider; 7 | 8 | import java.io.IOException; 9 | import java.time.ZoneId; 10 | 11 | /** 12 | * Serialize a ZoneId to a string 13 | */ 14 | public class ZoneIdSerializer extends JsonSerializer { 15 | 16 | @Override public void serialize(ZoneId zoneId, JsonGenerator jsonGenerator, 17 | SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 18 | jsonGenerator.writeString(zoneId.getId()); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/point_to_point/builder/RouterInfo.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.point_to_point.builder; 2 | 3 | import org.locationtech.jts.geom.Envelope; 4 | 5 | /** 6 | * Information about router 7 | * 8 | * Currently only envelope and name 9 | */ 10 | public class RouterInfo { 11 | 12 | public String name = "default"; 13 | public Envelope envelope; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/point_to_point/builder/SpeedUnit.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.point_to_point.builder; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | 6 | /** 7 | * Speeds can be specified in different units 8 | */ 9 | public enum SpeedUnit { 10 | KMH("kmh"), 11 | MPH("mph"), 12 | KNOTS("knots"); 13 | 14 | private String shortUnit; 15 | 16 | SpeedUnit(String shortUnit) { 17 | this.shortUnit = shortUnit; 18 | } 19 | 20 | @JsonValue 21 | @Override 22 | public String toString() { 23 | return this.shortUnit; 24 | } 25 | 26 | @JsonCreator 27 | public static SpeedUnit fromString(String unit) { 28 | if (unit != null) { 29 | unit = unit.toLowerCase(); 30 | switch (unit) { 31 | case "km/h": 32 | case "kmh": 33 | case "kmph": 34 | case "kph": 35 | return KMH; 36 | case "mph": 37 | return MPH; 38 | case "knots": 39 | return KNOTS; 40 | default: 41 | throw new IllegalArgumentException("Unknown unit:" + unit 42 | + " supported units are km/h|kmh|kmph|kph, mph and knots"); 43 | } 44 | } 45 | return null; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/profile/DominatingList.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.profile; 2 | 3 | import java.util.Collection; 4 | 5 | /** 6 | * When performing a multi-criteria search that finds sets of pareto-optimal paths (which is essential for resource 7 | * constraint situations) we must allow for multiple search states at each vertex (in this case transit stops). 8 | * One state is said to dominate another when it is better than that other state in all ways, i.e. it provides a path 9 | * that is so much better that the other path can be pruned or abandoned. 10 | * 11 | * When you add states to this type of list, the state might not actually be added if another state in the list 12 | * dominates it. If the state is optimal and is added to the list, other states are automatically dropped if they 13 | * are no longer co-optimal given the existence of the new state. 14 | * 15 | * It is assumed that all states inserted are comparable, meaning that they are at the same location and part of the 16 | * same search when simultaneously conducting multiple searches e.g. for different access modes. 17 | * 18 | * We only do multi-criteria transit searches, we haven't implemented multi-criteria street searches. 19 | */ 20 | public interface DominatingList { 21 | /** Attempt to add a state to this dominating list, and evict dominated states, returning true if this state is 22 | * undominated */ 23 | boolean add (McRaptorSuboptimalPathProfileRouter.McRaptorState state); 24 | 25 | /** get non-dominated states at this location */ 26 | Collection getNonDominatedStates (); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/profile/HashPath.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.profile; 2 | 3 | import java.util.Arrays; 4 | 5 | /** 6 | * A wrapper around a Path that redefines the hash code and equals functions. 7 | * The functions are changed to compare only the boardStops and alightStops of the Path. 8 | * This is used to group paths by their combination of boardStops and alightStops in the response. 9 | */ 10 | public class HashPath { 11 | 12 | final public Path path; 13 | 14 | public HashPath(Path path) { 15 | this.path = path; 16 | } 17 | 18 | @Override 19 | public boolean equals(Object o) { 20 | if (this == o) 21 | return true; 22 | if (o == null || getClass() != o.getClass()) 23 | return false; 24 | HashPath hashPath = (HashPath) o; 25 | return this == hashPath || Arrays.equals(path.boardStops, hashPath.path.boardStops) 26 | && Arrays.equals(path.alightStops, hashPath.path.alightStops); 27 | } 28 | 29 | @Override 30 | public int hashCode() { 31 | return Arrays.hashCode(path.boardStops) + 2 * Arrays.hashCode(path.alightStops); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/profile/PropagationTimer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.profile; 2 | 3 | /** 4 | * This groups together all the timers recording execution time of various steps of travel time propagation, which 5 | * is performed after the raptor search itself. 6 | * 7 | * TODO constructor that adds stop and target counts to top level message 8 | * LOG.info("Propagating {} iterations from {} stops to {} target points took {}s", 9 | * nIterations, nStops, endTarget - startTarget, (System.currentTimeMillis() - startTimeMillis) / 1000d 10 | * ); 11 | */ 12 | public class PropagationTimer { 13 | 14 | public final ExecutionTimer fullPropagation = new ExecutionTimer("Full travel time propagation"); 15 | 16 | public final ExecutionTimer transposition = new ExecutionTimer(fullPropagation, "Travel time matrix transposition"); 17 | 18 | public final ExecutionTimer propagation = new ExecutionTimer(fullPropagation, "Propagation"); 19 | 20 | public final ExecutionTimer reducer = new ExecutionTimer(fullPropagation, "Travel time reducer"); 21 | 22 | public void log () { 23 | fullPropagation.logWithChildren(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/profile/RaptorTimer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.profile; 2 | 3 | /** 4 | * This groups together all the timers recording execution time of various steps of a range raptor search. 5 | */ 6 | public class RaptorTimer { 7 | 8 | public final ExecutionTimer fullSearch = new ExecutionTimer("Full range-Raptor search"); 9 | 10 | public final ExecutionTimer scheduledSearch = new ExecutionTimer(fullSearch, "Scheduled/bounds search"); 11 | 12 | public final ExecutionTimer scheduledSearchTransit = new ExecutionTimer(scheduledSearch, "Scheduled search"); 13 | public final ExecutionTimer scheduledSearchFrequencyBounds = new ExecutionTimer(scheduledSearch, "Frequency upper bounds"); 14 | public final ExecutionTimer scheduledSearchTransfers = new ExecutionTimer(scheduledSearch, "Transfers"); 15 | 16 | public final ExecutionTimer frequencySearch = new ExecutionTimer(fullSearch, "Frequency search"); 17 | 18 | public final ExecutionTimer frequencySearchFrequency = new ExecutionTimer(frequencySearch, "Frequency component"); 19 | public final ExecutionTimer frequencySearchScheduled = new ExecutionTimer(frequencySearch, "Resulting updates to scheduled component"); 20 | public final ExecutionTimer frequencySearchTransfers = new ExecutionTimer(frequencySearch, "Transfers"); 21 | 22 | public void log () { 23 | fullSearch.logWithChildren(); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/profile/StreetMode.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.profile; 2 | 3 | /** 4 | * Represents a travel mode used to traverse edges in the street graph. 5 | * Permissions on edges will allow or disallow traversal by these modes, and edges may be traversed at different 6 | * speeds depending on the selected mode. 7 | */ 8 | public enum StreetMode { 9 | WALK, 10 | BICYCLE, 11 | CAR 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/streets/BikeRentalBuilder.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.streets; 2 | 3 | import com.conveyal.r5.api.util.BikeRentalStation; 4 | 5 | import java.io.File; 6 | import java.util.List; 7 | 8 | /** 9 | * This used to load capital bikeshare XML from a file. 10 | * TODO implement loading GBFS from a URL 11 | */ 12 | public class BikeRentalBuilder { 13 | 14 | File file; 15 | 16 | public BikeRentalBuilder(File file) { 17 | this.file = file; 18 | } 19 | 20 | List getRentalStations() { 21 | throw new UnsupportedOperationException("IMPLEMENT GBFS!"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/streets/DebugRoutingVisitor.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.streets; 2 | 3 | import com.conveyal.r5.common.GeoJsonFeature; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Callbacks for debugging street routing. 10 | * It accumulates all the steps in routing as GeoJSON. 11 | * Created by mabu on 10.12.2015. 12 | */ 13 | public class DebugRoutingVisitor implements RoutingVisitor { 14 | 15 | private List features; 16 | private final EdgeStore edgeStore; 17 | 18 | /** 19 | * Mode should be in the state itself 20 | * @param edgeStore streetLayer edgeStore 21 | * 22 | */ 23 | public DebugRoutingVisitor(EdgeStore edgeStore) { 24 | this.features = new ArrayList<>(); 25 | this.edgeStore = edgeStore; 26 | } 27 | 28 | /** 29 | * Saves current state geometry mode and weight as geoJSON feature properties 30 | * 31 | * in list of features. It is used in full state graph when debugging 32 | * @param state 33 | */ 34 | @Override 35 | public void visitVertex(StreetRouter.State state) { 36 | Integer edgeIdx = state.backEdge; 37 | if (!(edgeIdx == null || edgeIdx == -1)) { 38 | EdgeStore.Edge edge = edgeStore.getCursor(edgeIdx); 39 | GeoJsonFeature feature = new GeoJsonFeature(edge.getGeometry()); 40 | feature.addProperty("mode", state.streetMode); 41 | feature.addProperty("backEdge", state.backEdge); 42 | features.add(feature); 43 | } 44 | } 45 | 46 | public List getFeatures() { 47 | return features; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/streets/RoutingVisitor.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.streets; 2 | 3 | /** 4 | * A set of callbacks that the street router will invoke while it's routing, allowing you to observe its progress 5 | * and potentially stop the search. 6 | */ 7 | public interface RoutingVisitor { 8 | /** Called after search algorithms dequeue a vertex */ 9 | void visitVertex(StreetRouter.State state); 10 | 11 | /** 12 | * Called right after visitVertex 13 | * @return true if search should stop 14 | */ 15 | default boolean shouldBreakSearch() { 16 | return false; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/streets/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This is a new replacement street layer implementation 3 | */ 4 | package com.conveyal.r5.streets; 5 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transit/DuplicateFeedException.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transit; 2 | 3 | /** 4 | * Thrown when a TransportNetwork is build with two feeds with the same feed ID. 5 | */ 6 | public class DuplicateFeedException extends RuntimeException { 7 | private String feedId; 8 | 9 | public DuplicateFeedException(String feedId) { 10 | this.feedId = feedId; 11 | } 12 | 13 | @Override 14 | public String getMessage () { 15 | return String.format("Bundle contains duplicate feeds with feed ID %s", feedId); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transit/PickDropType.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transit; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * 8 | */ 9 | public enum PickDropType { 10 | 11 | SCHEDULED(0), 12 | NONE(1), 13 | CALL_AGENCY(2), 14 | COORDINATE_WITH_DRIVER(3); 15 | 16 | private static final Logger LOG = LoggerFactory.getLogger(PickDropType.class); 17 | 18 | // Will be initialized after constructor is called on all enum values. 19 | private static PickDropType[] forGtfsCode; 20 | 21 | static { 22 | forGtfsCode = new PickDropType[4]; 23 | for (PickDropType pdt : PickDropType.values()) { 24 | forGtfsCode[pdt.gtfsCode] = pdt; 25 | } 26 | } 27 | 28 | int gtfsCode; 29 | 30 | PickDropType(int gtfsCode) { 31 | this.gtfsCode = gtfsCode; 32 | } 33 | 34 | static PickDropType forGtfsCode (int gtfsCode) { 35 | if (gtfsCode >= forGtfsCode.length) { 36 | LOG.error("Pickup/dropoff code {} is invalid. Defaulting to 0 ('scheduled')", gtfsCode); 37 | gtfsCode = 0; 38 | } 39 | return forGtfsCode[gtfsCode]; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transit/RouteInfo.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transit; 2 | 3 | import com.conveyal.gtfs.model.Agency; 4 | import com.conveyal.gtfs.model.Route; 5 | 6 | import java.io.Serializable; 7 | import java.net.URL; 8 | 9 | /** 10 | * Information about a route. 11 | * FIXME This was originally to copy GTFS Route to get rid of inter-object references. Eliminate it. 12 | */ 13 | public class RouteInfo implements Serializable { 14 | public static final long serialVersionUID = 1L; 15 | 16 | public String agency_id; 17 | public String agency_name; 18 | public String route_id; 19 | public String route_short_name; 20 | public String route_long_name; 21 | public int route_type; 22 | public String color; 23 | public URL agency_url; 24 | 25 | public RouteInfo (Route route, Agency agency) { 26 | this.agency_id = route.agency_id; 27 | this.agency_name = agency.agency_name; 28 | this.route_id = route.route_id; 29 | this.route_short_name = route.route_short_name; 30 | this.route_long_name = route.route_long_name; 31 | this.route_type = route.route_type; 32 | this.color = route.route_color; 33 | this.agency_url = route.route_url; 34 | } 35 | 36 | public RouteInfo () { /* do nothing */ } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transit/TripFlag.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transit; 2 | 3 | /** 4 | * Enums are inherently serializable. 5 | */ 6 | public enum TripFlag { 7 | 8 | BICYCLE(0), 9 | WHEELCHAIR(1); 10 | int flag; 11 | 12 | TripFlag(int bitNumber) { 13 | flag = 1 << bitNumber; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transit/fare/RideType.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transit.fare; 2 | 3 | /** 4 | * Ride types for fares in DCDareCalculator 5 | */ 6 | public enum RideType { 7 | METRO_RAIL, 8 | METRO_BUS_LOCAL, 9 | METRO_BUS_EXPRESS, 10 | METRO_BUS_AIRPORT, 11 | DC_CIRCULATOR_BUS, 12 | ART_BUS, 13 | DASH_BUS, 14 | MARC_RAIL, 15 | MTA_BUS_LOCAL, 16 | MTA_BUS_EXPRESS, 17 | MTA_BUS_COMMUTER, 18 | VRE_RAIL, 19 | MCRO_BUS_LOCAL, 20 | MCRO_BUS_EXPRESS, 21 | FAIRFAX_CONNECTOR_BUS, 22 | PRTC_BUS 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transit/fare/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * This package contains classes implementing fares for Modeify and point-to-point profile routing. 3 | */ 4 | package com.conveyal.r5.transit.fare; 5 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transit/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Classes for the transit layer of an R5 TransportNetwork. 3 | */ 4 | package com.conveyal.r5.transit; 5 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transitive/TransitivePattern.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transitive; 2 | 3 | import com.conveyal.r5.util.EncodedPolylineSerializer; 4 | import com.fasterxml.jackson.databind.annotation.JsonSerialize; 5 | import org.locationtech.jts.geom.LineString; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Represents a transitive pattern. 11 | */ 12 | public class TransitivePattern { 13 | public String pattern_id; 14 | public String pattern_name; 15 | public String route_id; 16 | public List stops; 17 | 18 | // TODO is this level of indirection necessary? 19 | public static class StopIdRef { 20 | /** NB this is the stop index in the R5 graph, not the GTFS stop ID */ 21 | public String stop_id; 22 | 23 | @JsonSerialize(using = EncodedPolylineSerializer.class) 24 | public LineString geometry; 25 | 26 | public StopIdRef (String stop_id, LineString geometry) { 27 | this.stop_id = stop_id; 28 | this.geometry = geometry; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transitive/TransitiveRoute.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transitive; 2 | 3 | /** 4 | * Represents a Transitive route. 5 | */ 6 | public class TransitiveRoute { 7 | public String agency_id; 8 | public String route_id; 9 | public String route_short_name; 10 | public String route_long_name; 11 | public int route_type; 12 | public String route_color; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transitive/TransitiveStop.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.transitive; 2 | 3 | /** 4 | * Represents a Transitive stop. 5 | * @author mattwigway 6 | */ 7 | public class TransitiveStop { 8 | // TODO store stop ID as int? 9 | public String stop_id; 10 | public String stop_name; 11 | public double stop_lat; 12 | public double stop_lon; 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/transitive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Adapter classes to allow a TransitLayer to be represented as a Transitive network. 3 | */ 4 | package com.conveyal.r5.transitive; -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/EncodedPolylineSerializer.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import com.axiomalaska.polylineencoder.PolylineEncoder; 4 | import com.axiomalaska.polylineencoder.UnsupportedGeometryTypeException; 5 | import com.fasterxml.jackson.core.JsonGenerator; 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | import com.fasterxml.jackson.databind.JsonSerializer; 8 | import com.fasterxml.jackson.databind.SerializerProvider; 9 | import org.locationtech.jts.geom.LineString; 10 | 11 | import java.io.IOException; 12 | 13 | /** 14 | * Serialize to Google encoded polyline. 15 | * Hopefully we can get rid of this - it's the only thing still using JTS objects under the vividsolutions package name 16 | * so is pulling in extra dependencies and requiring conversions (toLegacyLineString). 17 | */ 18 | public class EncodedPolylineSerializer extends JsonSerializer { 19 | 20 | @Override 21 | public void serialize(LineString lineString, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { 22 | try { 23 | String points = PolylineEncoder.encode(lineString).getPoints(); 24 | jsonGenerator.writeString(points); 25 | } catch (UnsupportedGeometryTypeException e) { 26 | throw new RuntimeException(e); 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/ExceptionUtils.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import java.io.PrintWriter; 4 | import java.io.StringWriter; 5 | 6 | /** 7 | * Convenience functions for working with exceptions (or more generally throwables). 8 | */ 9 | public abstract class ExceptionUtils { 10 | 11 | public static String asString(Throwable throwable) { 12 | StringWriter sw = new StringWriter(); 13 | sw.append(throwable.getMessage()); 14 | sw.append("\n"); 15 | throwable.printStackTrace(new PrintWriter(sw)); 16 | return sw.toString(); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/InputStreamProvider.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | 6 | /** 7 | * This interface is used in cases where we need to repeatedly request the same input stream, as when loading 8 | * from uploaded CSV files. 9 | */ 10 | public interface InputStreamProvider { 11 | 12 | /** 13 | * @return a new input stream properly wrapped to buffer the input and remove UTF-8 BOM as needed. 14 | */ 15 | InputStream getInputStream() throws IOException; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/P2.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | /** 4 | * Tuple of two elements with same type 5 | */ 6 | public class P2 { 7 | public final E a; 8 | 9 | public final E b; 10 | 11 | /** 12 | * Creates a new pair 13 | * 14 | * @param b The key for this pair 15 | * @param b The value to use for this pair 16 | */ 17 | public P2( 18 | E a, 19 | E b) { 20 | this.a = a; 21 | this.b = b; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return String.format("P2<%s %s>", a, b); 27 | } 28 | 29 | @Override 30 | public int hashCode() { 31 | return (a != null ? a.hashCode() : 0) + 32 | (b != null ? b.hashCode() * 31 : 0); 33 | } 34 | 35 | @Override 36 | public boolean equals(Object o) { 37 | if(!(o instanceof P2)) return false; 38 | P2 other = (P2) o; 39 | boolean aIsEqual = (a == null) ? other.a == null : a.equals(other.a); 40 | boolean bIsEqual = (b == null) ? other.b == null : b.equals(other.b); 41 | return aIsEqual && bIsEqual; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/ProgressListener.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | public interface ProgressListener { 4 | 5 | public void setTotalItems (int nTotal); 6 | 7 | public void setCompletedItems(int nComplete); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/S3Util.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import com.amazonaws.services.s3.AmazonS3; 4 | import com.amazonaws.services.s3.AmazonS3ClientBuilder; 5 | import com.amazonaws.services.s3.model.ObjectMetadata; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import java.io.InputStream; 10 | import java.util.concurrent.ArrayBlockingQueue; 11 | import java.util.concurrent.ThreadPoolExecutor; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | /** 15 | * Created by matthewc on 10/21/16. 16 | */ 17 | public class S3Util { 18 | private static final Logger LOG = LoggerFactory.getLogger(S3Util.class); 19 | public static final AmazonS3 s3 = AmazonS3ClientBuilder.defaultClient(); 20 | 21 | private static ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 256, 60,TimeUnit.SECONDS, new ArrayBlockingQueue<>(255)); 22 | // can't use CallerRunsPolicy as that would cause deadlocks, calling thread is writing to inputstream 23 | static { 24 | executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); 25 | } 26 | 27 | public static void streamToS3 (String bucket, String key, InputStream is, ObjectMetadata metadata) { 28 | // write to S3 in a thread 29 | executor.execute(() -> { 30 | try { 31 | s3.putObject(bucket, key, is, metadata); 32 | is.close(); 33 | } catch (Exception e) { 34 | LOG.error("Exception writing to S3", e); 35 | } 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/TIntIntHashMultimap.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import gnu.trove.TIntCollection; 4 | import gnu.trove.list.TIntList; 5 | import gnu.trove.list.array.TIntArrayList; 6 | import gnu.trove.map.TIntObjectMap; 7 | import gnu.trove.map.hash.TIntObjectHashMap; 8 | 9 | import java.io.Serializable; 10 | 11 | /** 12 | * Created by matthewc on 2/19/16. 13 | */ 14 | public class TIntIntHashMultimap implements TIntIntMultimap, Serializable { 15 | private long serialVersionUID = -1; 16 | 17 | private TIntObjectMap wrapped = new TIntObjectHashMap<>(); 18 | 19 | @Override 20 | public boolean put(int key, int value) { 21 | if (!wrapped.containsKey(key)) wrapped.put(key, new TIntArrayList()); 22 | return wrapped.get(key).add(value); 23 | } 24 | 25 | @Override 26 | public TIntCollection get(int key) { 27 | return wrapped.containsKey(key) ? wrapped.get(key) : EmptyTIntCollection.get(); 28 | } 29 | 30 | @Override 31 | public boolean containsKey(int key) { 32 | return wrapped.containsKey(key); 33 | } 34 | 35 | @Override 36 | public TIntCollection removeAll(int key) { 37 | return wrapped.containsKey(key) ? wrapped.remove(key) : EmptyTIntCollection.get(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/TIntIntMultimap.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import gnu.trove.TIntCollection; 4 | 5 | /** 6 | * Created by matthewc on 2/19/16. 7 | */ 8 | public interface TIntIntMultimap { 9 | boolean put (int key, int value); 10 | TIntCollection get (int key); 11 | boolean containsKey (int key); 12 | TIntCollection removeAll (int key); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/TIntObjectHashMultimap.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import gnu.trove.map.TIntObjectMap; 4 | import gnu.trove.map.hash.TIntObjectHashMap; 5 | import gnu.trove.procedure.TIntObjectProcedure; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Collection; 9 | import java.util.Collections; 10 | import java.util.List; 11 | 12 | /** 13 | * Created by matthewc on 2/19/16. 14 | */ 15 | public class TIntObjectHashMultimap implements TIntObjectMultimap { 16 | private TIntObjectMap> wrapped = new TIntObjectHashMap<>(); 17 | 18 | @Override 19 | public boolean put(int key, V value) { 20 | if (!wrapped.containsKey(key)) wrapped.put(key, new ArrayList<>()); 21 | return wrapped.get(key).add(value); 22 | } 23 | 24 | @Override 25 | public Collection get(int key) { 26 | return wrapped.containsKey(key) ? wrapped.get(key) : Collections.emptyList(); 27 | } 28 | 29 | @Override 30 | public void clear() { 31 | wrapped.clear(); 32 | } 33 | 34 | @Override 35 | public boolean containsKey(int key) { 36 | return wrapped.containsKey(key); 37 | } 38 | 39 | @Override 40 | public void forEachEntry(TIntObjectProcedure> procedure) { 41 | wrapped.forEachEntry(procedure); 42 | } 43 | 44 | @Override 45 | public int size() { 46 | return wrapped.size(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/conveyal/r5/util/TIntObjectMultimap.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.util; 2 | 3 | import gnu.trove.procedure.TIntObjectProcedure; 4 | 5 | import java.util.Collection; 6 | 7 | /** 8 | * A primitive multimap 9 | */ 10 | public interface TIntObjectMultimap { 11 | boolean put (int key, V value); 12 | Collection get (int key); 13 | void clear(); 14 | boolean containsKey (int key); 15 | void forEachEntry (TIntObjectProcedure> procedure); 16 | 17 | /** number of keys */ 18 | int size(); 19 | } 20 | -------------------------------------------------------------------------------- /src/main/resources/debug-plan/debug.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 |
26 |

Flag usages:

Close
27 |

Speed usages:

Close
28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/resources/debug-plan/images/marker-flag-end-shadowed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/main/resources/debug-plan/images/marker-flag-end-shadowed.png -------------------------------------------------------------------------------- /src/main/resources/debug-plan/images/marker-flag-start-shadowed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/main/resources/debug-plan/images/marker-flag-start-shadowed.png -------------------------------------------------------------------------------- /src/main/resources/debug-plan/leaflet_context/leaflet.contextmenu.css: -------------------------------------------------------------------------------- 1 | .leaflet-contextmenu { 2 | display: none; 3 | box-shadow: 0 1px 7px rgba(0,0,0,0.4); 4 | -webkit-border-radius: 4px; 5 | border-radius: 4px; 6 | padding: 4px 0; 7 | background-color: #fff; 8 | cursor: default; 9 | -webkit-user-select: none; 10 | -moz-user-select: none; 11 | user-select: none; 12 | } 13 | 14 | .leaflet-contextmenu a.leaflet-contextmenu-item { 15 | display: block; 16 | color: #222; 17 | font-size: 12px; 18 | line-height: 20px; 19 | text-decoration: none; 20 | padding: 0 12px; 21 | border-top: 1px solid transparent; 22 | border-bottom: 1px solid transparent; 23 | cursor: default; 24 | outline: none; 25 | } 26 | 27 | .leaflet-contextmenu a.leaflet-contextmenu-item-disabled { 28 | opacity: 0.5; 29 | } 30 | 31 | .leaflet-contextmenu a.leaflet-contextmenu-item.over { 32 | background-color: #f4f4f4; 33 | border-top: 1px solid #f0f0f0; 34 | border-bottom: 1px solid #f0f0f0; 35 | } 36 | 37 | .leaflet-contextmenu a.leaflet-contextmenu-item-disabled.over { 38 | background-color: inherit; 39 | border-top: 1px solid transparent; 40 | border-bottom: 1px solid transparent; 41 | } 42 | 43 | .leaflet-contextmenu-icon { 44 | margin: 2px 8px 0 0; 45 | width: 16px; 46 | height: 16px; 47 | float: left; 48 | border: 0; 49 | } 50 | 51 | .leaflet-contextmenu-separator { 52 | border-bottom: 1px solid #ccc; 53 | margin: 5px 0; 54 | } -------------------------------------------------------------------------------- /src/main/resources/debug-plan/oneway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/main/resources/debug-plan/oneway.png -------------------------------------------------------------------------------- /src/main/resources/debug-plan/oneway@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/main/resources/debug-plan/oneway@2x.png -------------------------------------------------------------------------------- /src/main/resources/fares/nyc/lirr/README.txt: -------------------------------------------------------------------------------- 1 | # LIRR Fares 2 | 3 | This directory contains fare information for the LIRR, used to construct LIRRTransferAllowances for the NYCInRoutingFareCalculator. 4 | 5 | - lirr_zonal_fares.csv contains the fares for zone-to-zone journeys that do not require a change in direction. 6 | - via_fares.csv contains the fares for station-to-station journeys that do require a change in direction, but where LIRR will sell you a special "via" ticket. 7 | - descendants.csv contains all the stations that can be reached from a given station using only inbound or outbound trains, and is used to determin transfer allowances since we assume that same-direction transfers are free. 8 | -------------------------------------------------------------------------------- /src/main/resources/fares/nyc/mta/express_bus_routes.csv: -------------------------------------------------------------------------------- 1 | agency_id,route_id 2 | MTABC,BM1 3 | MTABC,BM2 4 | MTABC,BM3 5 | MTABC,BM4 6 | MTABC,BM5 7 | MTABC,BXM1 8 | MTABC,BXM10 9 | MTABC,BXM11 10 | MTABC,BXM18 11 | MTABC,BXM2 12 | MTABC,BXM3 13 | MTABC,BXM4 14 | MTABC,BXM6 15 | MTABC,BXM7 16 | MTABC,BXM8 17 | MTABC,BXM9 18 | MTA NYCT,SIM1 19 | MTA NYCT,SIM1C 20 | MTA NYCT,SIM2 21 | MTA NYCT,SIM3 22 | MTA NYCT,SIM3C 23 | MTA NYCT,SIM4 24 | MTA NYCT,SIM4X 25 | MTA NYCT,SIM4C 26 | MTA NYCT,SIM5 27 | MTA NYCT,SIM6 28 | MTA NYCT,SIM7 29 | MTA NYCT,SIM8 30 | MTA NYCT,SIM8X 31 | MTA NYCT,SIM9 32 | MTA NYCT,SIM10 33 | MTA NYCT,SIM11 34 | MTA NYCT,SIM15 35 | MTA NYCT,SIM22 36 | MTA NYCT,SIM23 37 | MTA NYCT,SIM24 38 | MTA NYCT,SIM25 39 | MTA NYCT,SIM26 40 | MTA NYCT,SIM30 41 | MTA NYCT,SIM31 42 | MTA NYCT,SIM32 43 | MTA NYCT,SIM33 44 | MTA NYCT,SIM33C 45 | MTA NYCT,SIM34 46 | MTA NYCT,SIM35 47 | MTA NYCT,X27 48 | MTA NYCT,X28 49 | MTA NYCT,X37 50 | MTA NYCT,X38 51 | MTA NYCT,X63 52 | MTA NYCT,X64 53 | MTA NYCT,X68 54 | MTABC,QM1 55 | MTABC,QM10 56 | MTABC,QM11 57 | MTABC,QM12 58 | MTABC,QM15 59 | MTABC,QM16 60 | MTABC,QM17 61 | MTABC,QM18 62 | MTABC,QM2 63 | MTABC,QM20 64 | MTABC,QM21 65 | MTABC,QM24 66 | MTABC,QM25 67 | MTABC,QM3 68 | MTABC,QM31 69 | MTABC,QM32 70 | MTABC,QM34 71 | MTABC,QM35 72 | MTABC,QM36 73 | MTABC,QM4 74 | MTABC,QM40 75 | MTABC,QM42 76 | MTABC,QM44 77 | MTABC,QM5 78 | MTABC,QM6 79 | MTABC,QM7 80 | MTABC,QM8 81 | -------------------------------------------------------------------------------- /src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/gtfs/GeometriesTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs; 2 | 3 | import org.junit.Test; 4 | import org.locationtech.jts.geom.Coordinate; 5 | import org.locationtech.jts.geom.Geometry; 6 | 7 | import static com.conveyal.gtfs.Geometries.geometryFactory; 8 | import static com.conveyal.gtfs.Geometries.getNetherlandsWithoutTexel; 9 | import static org.hamcrest.CoreMatchers.equalTo; 10 | import static org.hamcrest.MatcherAssert.assertThat; 11 | 12 | /** 13 | * Makes tests for the Netherlands geometry utils. 14 | * I added tests here because it substantially increases the coverage of the library since the file it's testing is so big. 15 | */ 16 | public class GeometriesTest { 17 | 18 | /** 19 | * Verify that a proper geometry is created using the getNetherlandsWithoutTexel method. 20 | * This method also calls the getNetherlands and getTexel methods, so we kill 3 birds with one stone here. 21 | */ 22 | @Test 23 | public void canGetNetherlandsWithoutTexel() { 24 | Geometry geom = getNetherlandsWithoutTexel(); 25 | assertThat( 26 | geom.contains(geometryFactory.createPoint(new Coordinate(4.907812, 52.317809))), 27 | equalTo(true) 28 | ); 29 | assertThat( 30 | geom.contains(geometryFactory.createPoint(new Coordinate(4.816163, 53.099519))), 31 | equalTo(false) 32 | ); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/gtfs/util/UtilTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.gtfs.util; 2 | 3 | import org.junit.Test; 4 | 5 | import static com.conveyal.gtfs.util.Util.human; 6 | import static org.hamcrest.MatcherAssert.assertThat; 7 | import static org.hamcrest.Matchers.is; 8 | 9 | /** 10 | * A test suite to verify the functionality of methods in the Util class. 11 | */ 12 | public class UtilTest { 13 | 14 | /** 15 | * Assert that the human function returns strings that are properly formatted. 16 | */ 17 | @Test 18 | public void canHumanize() { 19 | assertThat(human(123), is("123")); 20 | assertThat(human(1234), is("1k")); 21 | assertThat(human(1234567), is("1.2M")); 22 | assertThat(human(1234567890), is("1.2G")); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/osmlib/NodeTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class NodeTest extends TestCase { 6 | public void testNode(){ 7 | Node node = new Node(); 8 | assertEquals( node.getLat(), 0.0 ); 9 | assertEquals( node.getLon(), 0.0 ); 10 | 11 | node.setLatLon( 47.1, -122.2 ); 12 | assertEquals( node.getLat(), 47.1 ); 13 | assertEquals( node.getLon(), -122.2 ); 14 | 15 | Node node2 = new Node(-45.5, 122.2); 16 | assertEquals( node2.getLat(), -45.5 ); 17 | assertEquals( node2.getLon(), 122.2 ); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/osmlib/OSMEntityTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class OSMEntityTest extends TestCase{ 6 | /** 7 | * Create the test case 8 | * 9 | * @param testName name of the test case 10 | */ 11 | public OSMEntityTest( String testName ) 12 | { 13 | super( testName ); 14 | } 15 | 16 | public void testCreateTag() 17 | { 18 | OSMEntity.Tag tag = new OSMEntity.Tag("key","value"); 19 | assertEquals( tag.key, "key" ); 20 | assertEquals( tag.value, "value" ); 21 | } 22 | 23 | public void testTagged(){ 24 | class TaggedTester extends OSMEntity{ 25 | private static final long serialVersionUID = 1L; 26 | 27 | @Override 28 | public Type getType() { 29 | // TODO Auto-generated method stub 30 | return null; 31 | }} 32 | 33 | TaggedTester tt = new TaggedTester(); 34 | assertTrue( tt.hasNoTags() ); 35 | 36 | tt.addTag("key", "value"); 37 | 38 | assertFalse( tt.hasNoTags() ); 39 | assertTrue( tt.hasTag("key") ); 40 | assertTrue( tt.hasTag("key", "value") ); 41 | 42 | tt.setTagsFromString("foo=true;bar=false"); 43 | 44 | assertTrue( tt.hasTag("foo","true") ); 45 | assertTrue( tt.tagIsTrue("foo" ) ); 46 | assertTrue( tt.tagIsFalse("bar") ); 47 | 48 | assertEquals( tt.getTag("key"), "value" ); 49 | assertEquals( tt.getTag("foo"), "true" ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/osmlib/OSMTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | import junit.framework.TestCase; 4 | import org.mapdb.Fun; 5 | 6 | import java.io.IOException; 7 | import java.nio.file.Files; 8 | import java.nio.file.Paths; 9 | import java.util.Map; 10 | 11 | public class OSMTest extends TestCase { 12 | public void testOSM(){ 13 | OSM osm = new OSM("./src/test/resources/tmp"); 14 | osm.readFromFile("./src/test/resources/bangor_maine.osm.pbf"); 15 | assertEquals( osm.nodes.size(), 12030 ); 16 | assertEquals( osm.ways.size(), 1828 ); 17 | assertEquals( osm.relations.size(), 2 ); 18 | 19 | // make sure the indices work 20 | for (Map.Entry e : osm.relations.entrySet()) { 21 | Relation relation = e.getValue(); 22 | long id = e.getKey(); 23 | // Tested: Bangor contains relations with way, node, and relation members 24 | for (Relation.Member member : relation.members) { 25 | if (member.type == OSMEntity.Type.NODE) 26 | assertTrue(osm.relationsByNode.contains(Fun.t2(member.id, id))); 27 | else if (member.type == OSMEntity.Type.WAY) 28 | assertTrue(osm.relationsByWay.contains(Fun.t2(member.id, id))); 29 | else if (member.type == OSMEntity.Type.RELATION) 30 | assertTrue(osm.relationsByRelation.contains(Fun.t2(member.id, id))); 31 | } 32 | } 33 | } 34 | 35 | public void tearDown() throws IOException{ 36 | Files.delete( Paths.get("./src/test/resources/tmp") ); 37 | Files.delete( Paths.get("./src/test/resources/tmp.p") ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/osmlib/RelationTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class RelationTest extends TestCase { 6 | public void testRelation(){ 7 | assertNotNull( new Relation() ); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/osmlib/WayTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.osmlib; 2 | 3 | import junit.framework.TestCase; 4 | 5 | public class WayTest extends TestCase { 6 | public void testWay(){ 7 | Way way = new Way(); 8 | assertNotNull( way ); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/r5/analyst/core/LocalDateSerialization.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.analyst.core; 2 | 3 | import com.conveyal.r5.common.JsonUtilities; 4 | import org.junit.Test; 5 | 6 | import java.time.LocalDate; 7 | 8 | import static org.junit.Assert.assertEquals; 9 | 10 | /** 11 | * Tests correct LocalDate Serialization 12 | */ 13 | public class LocalDateSerialization { 14 | 15 | @Test 16 | public void testSerializationDeserialization() throws Exception { 17 | LocalDate date = LocalDate.now(); 18 | 19 | String jsonDate = JsonUtilities.objectMapper.writeValueAsString(date); 20 | 21 | LocalDate deserializedDate = JsonUtilities.objectMapper.readValue(jsonDate, LocalDate.class); 22 | assertEquals(date, deserializedDate); 23 | 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/r5/labeling/TestPermissionsLabeler.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.labeling; 2 | 3 | /** 4 | * This is used for tests. It adds new highway tag highway=nobikenoped which forbids cycling and walking. But allows other things. 5 | * Created by mabu on 27.11.2015. 6 | */ 7 | public class TestPermissionsLabeler extends USTraversalPermissionLabeler { 8 | static { 9 | addPermissions("highway=nobikenoped", "access=yes;bicycle=no;foot=no"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/test/java/com/conveyal/r5/profile/PropagatedTimesStoreTest.java: -------------------------------------------------------------------------------- 1 | package com.conveyal.r5.profile; 2 | 3 | import junit.framework.TestCase; 4 | import org.junit.Test; 5 | 6 | /** 7 | * Test the propagated times store. 8 | */ 9 | public class PropagatedTimesStoreTest extends TestCase { 10 | /** 11 | * Test that changing the reachability threshold works (i.e. averages are computed properly when destinations are 12 | * only reachable part of the time). 13 | */ 14 | @Test 15 | public static void testReachability () throws Exception { 16 | /* 17 | ProfileRequest pr = new ProfileRequest(); 18 | // old default: no restrictions o 19 | pr.reachabilityThreshold = 0; 20 | 21 | PropagatedTimesStore pts = new PropagatedTimesStore(pr, 1); 22 | // accessible one-third of the time 23 | int[][] times = new int[][] { 24 | new int[] { 1 }, 25 | new int[] { RaptorWorker.UNREACHED }, 26 | new int[] { RaptorWorker.UNREACHED } 27 | }; 28 | 29 | pts.setFromArray(times, PropagatedTimesStore.ConfidenceCalculationMethod.MIN_MAX); 30 | 31 | // it is reachable at least 0% of the time 32 | assertEquals(1, pts.avgs[0]); 33 | 34 | pr.reachabilityThreshold = 0.5f; 35 | pts = new PropagatedTimesStore(g, pr, 1); 36 | pts.setFromArray(times, PropagatedTimesStore.ConfidenceCalculationMethod.MIN_MAX); 37 | 38 | // it is not reachable 50% of the time 39 | assertEquals(RaptorWorker.UNREACHED, pts.avgs[0]); 40 | */ 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/resources/bangor_maine.osm.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/bangor_maine.osm.pbf -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/data/census/integrationTest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/com/conveyal/data/census/integrationTest.zip -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/gtfs/null-island-ferry/agency.txt: -------------------------------------------------------------------------------- 1 | agency_id,agency_name,agency_url,agency_timezone,agency_lang 2 | NullFerry,Null Island Ferry Authority,"https://www.ndbc.noaa.gov/station_page.php?station=13010",Etc/UTC,en 3 | -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/gtfs/null-island-ferry/calendar.txt: -------------------------------------------------------------------------------- 1 | service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date 2 | all,1,1,1,1,1,1,1,20200901,20201231 3 | -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/gtfs/null-island-ferry/feed_info.txt: -------------------------------------------------------------------------------- 1 | feed_id,feed_publisher_name,feed_publisher_url,feed_lang,feed_start_date,feed_end_date,feed_version,feed_contact_email 2 | NIF,Conveyal LLC,http://conveyal.com,en,20200901,20201231,1,contact@conveyal.com 3 | -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/gtfs/null-island-ferry/routes.txt: -------------------------------------------------------------------------------- 1 | route_id,agency_id,route_short_name,route_long_name,route_desc,route_type 2 | NIF,NullFerry,NF1,Null Island Ferry,The Ferry operates between two PIRATA weather buoys,4 3 | -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/gtfs/null-island-ferry/stop_times.txt: -------------------------------------------------------------------------------- 1 | trip_id,arrival_time,departure_time,stop_id,stop_sequence 2 | out,00:00:00,00:00:00,0,1 3 | out,11:59:00,12:00:00,1,2 4 | back,11:59:00,12:00:00,1,1 5 | back,23:59:00,24:00:00,0,2 6 | -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/gtfs/null-island-ferry/stops.txt: -------------------------------------------------------------------------------- 1 | stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,location_type,stop_url 2 | 0,13010,Soul,Null Island,0,0,,https://www.ndbc.noaa.gov/station_page.php?station=13010 3 | 1,15002,Java,PIRATA Atlas Buoy,0,-10,,https://www.ndbc.noaa.gov/station_page.php?station=15002 4 | -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/gtfs/null-island-ferry/trips.txt: -------------------------------------------------------------------------------- 1 | route_id,service_id,trip_id,trip_headsign,direction_id 2 | NIF,all,out,Outbound,0 3 | NIF,all,back,Inbound,1 4 | -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/r5/analyst/scenario/columbus.osm.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/com/conveyal/r5/analyst/scenario/columbus.osm.pbf -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/r5/streets/cathedral-no-left.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/com/conveyal/r5/streets/cathedral-no-left.pbf -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/r5/streets/reisterstown-via-restriction.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/com/conveyal/r5/streets/reisterstown-via-restriction.pbf -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/r5/streets/snake-rd.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/com/conveyal/r5/streets/snake-rd.pbf -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/r5/streets/speedFlagsTest.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/com/conveyal/r5/streets/speedFlagsTest.pbf -------------------------------------------------------------------------------- /src/test/resources/com/conveyal/r5/streets/subgraph.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/com/conveyal/r5/streets/subgraph.pbf -------------------------------------------------------------------------------- /src/test/resources/fake-agency.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/fake-agency.zip -------------------------------------------------------------------------------- /src/test/resources/fake-agency/agency.txt: -------------------------------------------------------------------------------- 1 | agency_id,agency_name,agency_url,agency_lang,agency_phone,agency_email,agency_timezone,agency_fare_url,agency_branding_url 2 | 1,Fake Transit,,,,,America/Los_Angeles,, 3 | -------------------------------------------------------------------------------- /src/test/resources/fake-agency/calendar.txt: -------------------------------------------------------------------------------- 1 | service_id,monday,tuesday,wednesday,thursday,friday,saturday,sunday,start_date,end_date 2 | 04100312-8fe1-46a5-a9f2-556f39478f57,1,1,1,1,1,1,1,20170915,20170917 3 | -------------------------------------------------------------------------------- /src/test/resources/fake-agency/calendar_dates.txt: -------------------------------------------------------------------------------- 1 | service_id,date,exception_type 2 | 04100312-8fe1-46a5-a9f2-556f39478f57,20200220,2 -------------------------------------------------------------------------------- /src/test/resources/fake-agency/fare_attributes.txt: -------------------------------------------------------------------------------- 1 | fare_id,price,currency_type,payment_method,transfers,transfer_duration 2 | route_based_fare,1.23,USD,0,0,0 -------------------------------------------------------------------------------- /src/test/resources/fake-agency/fare_rules.txt: -------------------------------------------------------------------------------- 1 | fare_id,route_id,origin_id,destination_id,contains_id 2 | route_based_fare,1,,, -------------------------------------------------------------------------------- /src/test/resources/fake-agency/feed_info.txt: -------------------------------------------------------------------------------- 1 | feed_publisher_name,feed_publisher_url,feed_lang,feed_version 2 | Conveyal,http://www.conveyal.com,en,1.0 -------------------------------------------------------------------------------- /src/test/resources/fake-agency/frequencies.txt: -------------------------------------------------------------------------------- 1 | trip_id,start_time,end_time,headway_secs,exact_times 2 | frequency-trip,08:00:00,09:00:00,1800,0 -------------------------------------------------------------------------------- /src/test/resources/fake-agency/routes.txt: -------------------------------------------------------------------------------- 1 | agency_id,route_id,route_short_name,route_long_name,route_desc,route_type,route_url,route_color,route_text_color,route_branding_url 2 | 1,1,1,Route 1,,3,,7CE6E7,FFFFFF, 3 | -------------------------------------------------------------------------------- /src/test/resources/fake-agency/shapes.txt: -------------------------------------------------------------------------------- 1 | shape_id,shape_pt_lat,shape_pt_lon,shape_pt_sequence,shape_dist_traveled 2 | 5820f377-f947-4728-ac29-ac0102cbc34e,37.046495,-122.075212,1,0 3 | 5820f377-f947-4728-ac29-ac0102cbc34e,37.0611720,-122.0075000,2,400 4 | 5820f377-f947-4728-ac29-ac0102cbc34e,37.047819,-122.074137,3,730 5 | -------------------------------------------------------------------------------- /src/test/resources/fake-agency/stop_times.txt: -------------------------------------------------------------------------------- 1 | trip_id,arrival_time,departure_time,stop_id,stop_sequence,stop_headsign,pickup_type,drop_off_type,shape_dist_traveled,timepoint 2 | a30277f8-e50a-4a85-9141-b1e0da9d429d,07:00:00,07:00:00,4u6g,1,,0,0,0.0000000, 3 | a30277f8-e50a-4a85-9141-b1e0da9d429d,07:01:00,07:01:00,johv,2,,0,0,341.4491961, 4 | frequency-trip,08:00:00,08:00:00,4u6g,1,,0,0,0.0000000, 5 | frequency-trip,08:01:00,08:01:00,johv,2,,0,0,341.4491961, 6 | -------------------------------------------------------------------------------- /src/test/resources/fake-agency/stops.txt: -------------------------------------------------------------------------------- 1 | stop_id,stop_code,stop_name,stop_desc,stop_lat,stop_lon,zone_id,stop_url,location_type,parent_station,stop_timezone,wheelchair_boarding 2 | 4u6g,,Laurel Dr,,37.046495,-122.075212,,,0,,, 3 | johv,,Gushee St,,37.047819,-122.074137,,,0,,, 4 | -------------------------------------------------------------------------------- /src/test/resources/fake-agency/transfers.txt: -------------------------------------------------------------------------------- 1 | from_stop_id,to_stop_id,transfer_type,min_transfer_time 2 | -------------------------------------------------------------------------------- /src/test/resources/fake-agency/trips.txt: -------------------------------------------------------------------------------- 1 | route_id,trip_id,trip_headsign,trip_short_name,direction_id,block_id,shape_id,bikes_allowed,wheelchair_accessible,service_id 2 | 1,a30277f8-e50a-4a85-9141-b1e0da9d429d,,,0,,5820f377-f947-4728-ac29-ac0102cbc34e,0,0,04100312-8fe1-46a5-a9f2-556f39478f57 3 | 1,frequency-trip,,,0,,5820f377-f947-4728-ac29-ac0102cbc34e,0,0,04100312-8fe1-46a5-a9f2-556f39478f57 -------------------------------------------------------------------------------- /src/test/resources/felton.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/felton.pbf -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | %d{HH:mm:ss.SSS} %level \(%F:%L\) %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/test/resources/porto_portugal.osm.pbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/conveyal/analysis-backend/d14d1a2375f1596d29d6706b40bb02bd15a07614/src/test/resources/porto_portugal.osm.pbf --------------------------------------------------------------------------------