From a8bdda3e538116213dbd526dcc758ce5cd4a2800 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Thu, 19 Dec 2019 16:33:09 +0100 Subject: [PATCH 01/18] Fix connections selectors --- .../connections/ConnectionSelectors.ts | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/fetcher/connections/ConnectionSelectors.ts diff --git a/src/fetcher/connections/ConnectionSelectors.ts b/src/fetcher/connections/ConnectionSelectors.ts new file mode 100644 index 00000000..313d6ef3 --- /dev/null +++ b/src/fetcher/connections/ConnectionSelectors.ts @@ -0,0 +1,41 @@ +import IConnection from "../../entities/connections/connections"; + +export function forwardsConnectionSelector(connections: IConnection[]): number { + if (connections.length === 1) { + return 0; + } + + let earliestIndex = 0; + let earliest = connections[earliestIndex]; + + for (let i = 1; i < connections.length; i++) { + const connection = connections[i]; + + if (connection.departureTime < earliest.departureTime) { + earliestIndex = i; + earliest = connection; + } + } + + return earliestIndex; +} + +export function backwardsConnectionsSelector(connections: IConnection[]): number { + if (connections.length === 1) { + return 0; + } + + let latestIndex = 0; + let latest = connections[latestIndex]; + + for (let i = 1; i < connections.length; i++) { + const connection = connections[i]; + + if (connection.departureTime > latest.departureTime) { + latestIndex = i; + latest = connection; + } + } + + return latestIndex; +} From e2cdb866e310a7512a9783082c0c0f81c875c3d0 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Thu, 19 Dec 2019 16:33:30 +0100 Subject: [PATCH 02/18] Commit missing files --- .../connections/ConnectionsProviderDefault.ts | 43 ++----------------- .../public-transport/CSAEarliestArrival.ts | 22 +--------- src/planner/public-transport/CSAProfile.ts | 21 +-------- 3 files changed, 7 insertions(+), 79 deletions(-) diff --git a/src/fetcher/connections/ConnectionsProviderDefault.ts b/src/fetcher/connections/ConnectionsProviderDefault.ts index 7b5cf012..359a6bf5 100644 --- a/src/fetcher/connections/ConnectionsProviderDefault.ts +++ b/src/fetcher/connections/ConnectionsProviderDefault.ts @@ -6,6 +6,7 @@ import { LinkedConnectionsPage } from "../../entities/connections/page"; import TYPES, { ConnectionsFetcherFactory } from "../../types"; import MergeIterator from "../../util/iterators/MergeIterator"; import IHydraTemplateFetcher from "../hydra/IHydraTemplateFetcher"; +import { backwardsConnectionsSelector, forwardsConnectionSelector } from "./ConnectionSelectors"; import ConnectionsProviderSingle from "./ConnectionsProviderSingle"; import IConnectionsIteratorOptions from "./IConnectionsIteratorOptions"; import IConnectionsProvider from "./IConnectionsProvider"; @@ -13,44 +14,6 @@ import IConnectionsProvider from "./IConnectionsProvider"; @injectable() export default class ConnectionsProviderDefault implements IConnectionsProvider { - private static forwardsConnectionSelector(connections: IConnection[]): number { - if (connections.length === 1) { - return 0; - } - - let earliestIndex = 0; - const earliest = connections[earliestIndex]; - - for (let i = 1; i < connections.length; i++) { - const connection = connections[i]; - - if (connection.departureTime < earliest.departureTime) { - earliestIndex = i; - } - } - - return earliestIndex; - } - - private static backwardsConnectionsSelector(connections: IConnection[]): number { - if (connections.length === 1) { - return 0; - } - - let latestIndex = 0; - const latest = connections[latestIndex]; - - for (let i = 1; i < connections.length; i++) { - const connection = connections[i]; - - if (connection.departureTime > latest.departureTime) { - latestIndex = i; - } - } - - return latestIndex; - } - private singleProviders: ConnectionsProviderSingle[]; private connectionsFetcherFactory: ConnectionsFetcherFactory; private templateFetcher: IHydraTemplateFetcher; @@ -86,9 +49,9 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider .map((provider) => provider.createIterator(options))); const selector = options.backward ? - ConnectionsProviderDefault.backwardsConnectionsSelector + backwardsConnectionsSelector : - ConnectionsProviderDefault.forwardsConnectionSelector; + forwardsConnectionSelector; if (options.excludedModes) { return new MergeIterator(iterators, selector, true).filter((item) => { diff --git a/src/planner/public-transport/CSAEarliestArrival.ts b/src/planner/public-transport/CSAEarliestArrival.ts index 967431ad..e99f7d41 100644 --- a/src/planner/public-transport/CSAEarliestArrival.ts +++ b/src/planner/public-transport/CSAEarliestArrival.ts @@ -9,6 +9,7 @@ import ReachableStopsSearchPhase from "../../enums/ReachableStopsSearchPhase"; import TravelMode from "../../enums/TravelMode"; import EventBus from "../../events/EventBus"; import EventType from "../../events/EventType"; +import { forwardsConnectionSelector } from "../../fetcher/connections/ConnectionSelectors"; import IConnectionsProvider from "../../fetcher/connections/IConnectionsProvider"; import IStop from "../../fetcher/stops/IStop"; import ILocation from "../../interfaces/ILocation"; @@ -43,25 +44,6 @@ interface IQueryState { @injectable() export default class CSAEarliestArrival implements IPublicTransportPlanner { - private static forwardsConnectionSelector(connections: IConnection[]): number { - if (connections.length === 1) { - return 0; - } - - let earliestIndex = 0; - const earliest = connections[earliestIndex]; - - for (let i = 1; i < connections.length; i++) { - const connection = connections[i]; - - if (connection && connection.departureTime < earliest.departureTime) { - earliestIndex = i; - } - } - - return earliestIndex; - } - protected readonly connectionsProvider: IConnectionsProvider; protected readonly locationResolver: ILocationResolver; protected readonly transferReachableStopsFinder: IReachableStopsFinder; @@ -110,7 +92,7 @@ export default class CSAEarliestArrival implements IPublicTransportPlanner { const connectionsQueue = new MergeIterator( [connectionsIterator, footpathsQueue], - CSAEarliestArrival.forwardsConnectionSelector, + forwardsConnectionSelector, true, ); diff --git a/src/planner/public-transport/CSAProfile.ts b/src/planner/public-transport/CSAProfile.ts index f858808b..6032ab98 100644 --- a/src/planner/public-transport/CSAProfile.ts +++ b/src/planner/public-transport/CSAProfile.ts @@ -9,6 +9,7 @@ import ReachableStopsSearchPhase from "../../enums/ReachableStopsSearchPhase"; import TravelMode from "../../enums/TravelMode"; import EventBus from "../../events/EventBus"; import EventType from "../../events/EventType"; +import { backwardsConnectionsSelector } from "../../fetcher/connections/ConnectionSelectors"; import IConnectionsProvider from "../../fetcher/connections/IConnectionsProvider"; import IStop from "../../fetcher/stops/IStop"; import ILocation from "../../interfaces/ILocation"; @@ -60,24 +61,6 @@ interface IQueryState { */ @injectable() export default class CSAProfile implements IPublicTransportPlanner { - private static backwardsConnectionsSelector(connections: IConnection[]): number { - if (connections.length === 1) { - return 0; - } - - let latestIndex = 0; - const latest = connections[latestIndex]; - - for (let i = 1; i < connections.length; i++) { - const connection = connections[i]; - - if (connection.departureTime > latest.departureTime) { - latestIndex = i; - } - } - - return latestIndex; - } private readonly connectionsProvider: IConnectionsProvider; private readonly locationResolver: ILocationResolver; @@ -129,7 +112,7 @@ export default class CSAProfile implements IPublicTransportPlanner { const mergedIterator = new MergeIterator( [connectionsIterator, footpathQueue], - CSAProfile.backwardsConnectionsSelector, + backwardsConnectionsSelector, true, ); From b73d34d377ec608c62ddcb22215682c483d005ce Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Fri, 27 Dec 2019 15:03:23 +0100 Subject: [PATCH 03/18] Improve linked connection compliance --- src/configs/flexible_transit.ts | 11 +++++---- .../connections/ConnectionsFetcherRaw.ts | 23 ++++++++++++++----- .../configurations/FlexibleTransitPlanner.ts | 2 +- .../public-transport/CSAEarliestArrival.ts | 7 ++++-- .../stops/ReachableStopsFinderDelaunay.ts | 17 ++++++++------ 5 files changed, 39 insertions(+), 21 deletions(-) diff --git a/src/configs/flexible_transit.ts b/src/configs/flexible_transit.ts index cfdb1bf0..f342a4f6 100644 --- a/src/configs/flexible_transit.ts +++ b/src/configs/flexible_transit.ts @@ -18,6 +18,7 @@ import ProfileProviderDefault from "../fetcher/profiles/ProfileProviderDefault"; import IStopsFetcher from "../fetcher/stops/IStopsFetcher"; import IStopsProvider from "../fetcher/stops/IStopsProvider"; import StopsFetcherLDFetch from "../fetcher/stops/ld-fetch/StopsFetcherLDFetch"; +import StopsFetcherRaw from "../fetcher/stops/StopsFetcherRaw"; import StopsProviderDefault from "../fetcher/stops/StopsProviderDefault"; import IRoutableTileFetcher from "../fetcher/tiles/IRoutableTileFetcher"; import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; @@ -28,7 +29,7 @@ import { BidirDijkstra } from "../pathfinding/bidirdijkstra/BidirDijkstra"; import DijkstraTree from "../pathfinding/dijkstra-tree/DijkstraTree"; import { IShortestPathAlgorithm, IShortestPathTreeAlgorithm } from "../pathfinding/pathfinder"; import PathfinderProvider from "../pathfinding/PathfinderProvider"; -import CSAProfile from "../planner/public-transport/CSAProfile"; +import CSAEarliestArrival from "../planner/public-transport/CSAEarliestArrival"; import IJourneyExtractor from "../planner/public-transport/IJourneyExtractor"; import IPublicTransportPlanner from "../planner/public-transport/IPublicTransportPlanner"; import JourneyExtractorProfile from "../planner/public-transport/JourneyExtractorProfile"; @@ -37,15 +38,15 @@ import RoadPlannerPathfinding from "../planner/road/RoadPlannerPathfinding"; import IReachableStopsFinder from "../planner/stops/IReachableStopsFinder"; import ReachableStopsFinderBirdsEyeCached from "../planner/stops/ReachableStopsFinderBirdsEyeCached"; import ReachableStopsFinderDelaunay from "../planner/stops/ReachableStopsFinderDelaunay"; -import QueryRunnerExponential from "../query-runner/exponential/QueryRunnerExponential"; import ILocationResolver from "../query-runner/ILocationResolver"; import IQueryRunner from "../query-runner/IQueryRunner"; import LocationResolverConvenience from "../query-runner/LocationResolverConvenience"; +import QueryRunnerDefault from "../query-runner/QueryRunnerDefault"; import TYPES from "../types"; const container = new Container(); container.bind(TYPES.Context).to(Context).inSingletonScope(); -container.bind(TYPES.QueryRunner).to(QueryRunnerExponential); +container.bind(TYPES.QueryRunner).to(QueryRunnerDefault); container.bind(TYPES.LocationResolver).to(LocationResolverConvenience); container.bind(TYPES.HydraTemplateFetcher).to(HydraTemplateFetcherDefault).inSingletonScope(); @@ -55,7 +56,7 @@ container.bind(TYPES.JourneyExtractor) .to(JourneyExtractorProfile); container.bind(TYPES.PublicTransportPlanner) - .to(CSAProfile); + .to(CSAEarliestArrival); container.bind>(TYPES.PublicTransportPlannerFactory) .toAutoFactory(TYPES.PublicTransportPlanner); @@ -90,7 +91,7 @@ container.bind>(TYPES.ConnectionsFetcher ); container.bind(TYPES.StopsProvider).to(StopsProviderDefault).inSingletonScope(); -container.bind(TYPES.StopsFetcher).to(StopsFetcherLDFetch); +container.bind(TYPES.StopsFetcher).to(StopsFetcherRaw); container.bind>(TYPES.StopsFetcherFactory) .toFactory( (context: interfaces.Context) => diff --git a/src/fetcher/connections/ConnectionsFetcherRaw.ts b/src/fetcher/connections/ConnectionsFetcherRaw.ts index bfe3671a..75d56ac9 100644 --- a/src/fetcher/connections/ConnectionsFetcherRaw.ts +++ b/src/fetcher/connections/ConnectionsFetcherRaw.ts @@ -61,11 +61,15 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { const departureStop = context.resolveIdentifier(entity[DEPARTURE_STOP]); const departureDelay = entity[DEPARTURE_DELAY] ? parseFloat(entity[DEPARTURE_DELAY]) : 0; - const tripId = context.resolveIdentifier(entity[TRIP]) || null; - const route = context.resolveIdentifier(entity[ROUTE]) || null; - - const dropOffType = context.resolveIdentifier(entity[DROP_OFF_TYPE]) as DropOffType; - const pickupType = context.resolveIdentifier(entity[PICKUP_TYPE]) as PickupType; + const tripId = entity[TRIP] ? context.resolveIdentifier(entity[TRIP]) : null; + const route = entity[ROUTE] ? context.resolveIdentifier(entity[ROUTE]) : null; + + const dropOffType = entity[DROP_OFF_TYPE] ? + context.resolveIdentifier(entity[DROP_OFF_TYPE]) as DropOffType : + DropOffType.Regular; + const pickupType = entity[PICKUP_TYPE] ? + context.resolveIdentifier(entity[PICKUP_TYPE]) as PickupType : + PickupType.Regular; const headsign = entity[HEADSIGN] || null; const connection: IConnection = { id: connectionId, @@ -83,7 +87,10 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { headsign, }; - connections.push(connection); + if (connection.departureTime < connection.arrivalTime) { + // safety precaution + connections.push(connection); + } } const pageId = blob["@id"]; @@ -96,6 +103,10 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { EventBus.getInstance().emit(EventType.ConnectionPrefetch, connections[connections.length - 1].departureTime); + connections.sort((a, b) => { + return a.departureTime.getTime() - b.departureTime.getTime(); + }); + return new LinkedConnectionsPage(pageId, connections, previousPageUrl, nextPageUrl); } else { return new LinkedConnectionsPage(url, [], undefined, undefined); diff --git a/src/planner/configurations/FlexibleTransitPlanner.ts b/src/planner/configurations/FlexibleTransitPlanner.ts index a550b4a6..7ce0c013 100644 --- a/src/planner/configurations/FlexibleTransitPlanner.ts +++ b/src/planner/configurations/FlexibleTransitPlanner.ts @@ -1,7 +1,7 @@ import flexibleTransit from "../../configs/flexible_transit"; import Planner from "./Planner"; -export default class DissectPlanner extends Planner { +export default class FlexibleTransitPlanner extends Planner { constructor() { super(flexibleTransit); } diff --git a/src/planner/public-transport/CSAEarliestArrival.ts b/src/planner/public-transport/CSAEarliestArrival.ts index e99f7d41..0fcbfdaa 100644 --- a/src/planner/public-transport/CSAEarliestArrival.ts +++ b/src/planner/public-transport/CSAEarliestArrival.ts @@ -258,11 +258,14 @@ export default class CSAEarliestArrival implements IPublicTransportPlanner { const newArrivalTime = new Date(sourceConnection.arrivalTime.getTime() + duration); if (transferTentativeArrival > newArrivalTime.getTime() && newArrivalTime <= query.maximumArrivalTime) { + + const tripId = `TRANSFER_TO:${sourceConnection.arrivalStop}@${sourceConnection.arrivalTime.getTime()}`; + // create a connection that resembles a footpath // TODO, ditch the IReachbleStop and IConnection interfaces and make these proper objects const transferConnection: IConnection = { - id: `TRANSFER_TO:${stop.id}`, - tripId: `TRANSFER_TO:${stop.id}`, + id: `${tripId}-${stop.id}`, + tripId, travelMode: TravelMode.Walking, // TODO, this should be part of the reachable stop object departureTime: sourceConnection.arrivalTime, departureStop: sourceConnection.arrivalStop, diff --git a/src/planner/stops/ReachableStopsFinderDelaunay.ts b/src/planner/stops/ReachableStopsFinderDelaunay.ts index c02dc94e..e3eea7fd 100644 --- a/src/planner/stops/ReachableStopsFinderDelaunay.ts +++ b/src/planner/stops/ReachableStopsFinderDelaunay.ts @@ -77,15 +77,18 @@ export default class ReachableStopsFinderDelaunay implements IReachableStopsFind } private async getNearbyStops(location: ILocation): Promise { - const triangles = await this.triangles; - const cell = triangles.find(location.longitude, location.latitude); + if (!this.triangles) { + await this.prepare(); + } + + const cell = this.triangles.find(location.longitude, location.latitude); const result = [this.trianglePoints[cell]]; // not including these for now // may result in large route network queries if the stops network is sparse - const neighbors = triangles.neighbors(cell); + const neighbors = this.triangles.neighbors(cell); for (const neighbor of neighbors) { const neighborLocation = this.trianglePoints[neighbor]; if (Geo.getDistanceBetweenLocations(location, neighborLocation) < 2500) { @@ -96,9 +99,9 @@ export default class ReachableStopsFinderDelaunay implements IReachableStopsFind } private async prepare() { - this.triangles = this.stopsProvider.getAllStops().then((stops) => { - this.trianglePoints = stops; + this.trianglePoints = await this.stopsProvider.getAllStops(); + if (this.trianglePoints && this.trianglePoints.length) { function getX(p: ILocation) { return p.longitude; } @@ -107,7 +110,7 @@ export default class ReachableStopsFinderDelaunay implements IReachableStopsFind return p.latitude; } - return Delaunay.from(stops, getX, getY); - }); + this.triangles = Delaunay.from(this.trianglePoints, getX, getY); + } } } From c5cfa55fcd136b09da527e5e5035e4f0b399dc79 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Thu, 9 Jan 2020 13:49:44 +0100 Subject: [PATCH 04/18] Add support for geospatially fragmented linked connections --- package-lock.json | 1452 ++++++++++++++++- package.json | 4 +- src/configs/flexible_transit.ts | 11 +- src/configs/geospatial_fragment.ts | 130 ++ src/entities/tree/geometry.ts | 21 + src/entities/tree/relation.ts | 20 + src/entities/tree/tree.ts | 14 + src/events/EventType.ts | 2 + .../connections/ConnectionsFetcherRaw.ts | 5 +- .../connections/ConnectionsProviderDefault.ts | 37 +- .../connections/ConnectionsProviderSingle.ts | 70 +- .../connections/ForwardConnectionIterator.ts | 8 + .../IConnectionsIteratorOptions.ts | 2 + .../connections/IConnectionsProvider.ts | 7 +- .../tests/ConnectionsProviderNMBSTest.ts | 7 + .../tree/HypermediaTreeFetcherDefault.ts | 74 + .../tree/HypermediaTreeProviderDeault.ts | 40 + src/fetcher/tree/IHeadermediaTreeProvider.ts | 6 + src/fetcher/tree/IHypermediaTreeFetcher.ts | 5 + src/index.ts | 3 + src/loader/ldloader.ts | 28 +- .../GeospatialFragmentedPlanner.ts | 19 + .../public-transport/CSA/FootpathQueue.ts | 2 + .../public-transport/CSAEarliestArrival.ts | 1 + .../CSAEarliestArrivalDynamic.ts | 459 ++++++ src/planner/public-transport/CSAProfile.ts | 1 + src/types.ts | 6 +- src/uri/constants.ts | 2 + src/util/iterators/MergeIterator.ts | 2 + 29 files changed, 2387 insertions(+), 51 deletions(-) create mode 100644 src/configs/geospatial_fragment.ts create mode 100644 src/entities/tree/geometry.ts create mode 100644 src/entities/tree/relation.ts create mode 100644 src/entities/tree/tree.ts create mode 100644 src/fetcher/tree/HypermediaTreeFetcherDefault.ts create mode 100644 src/fetcher/tree/HypermediaTreeProviderDeault.ts create mode 100644 src/fetcher/tree/IHeadermediaTreeProvider.ts create mode 100644 src/fetcher/tree/IHypermediaTreeFetcher.ts create mode 100644 src/planner/configurations/GeospatialFragmentedPlanner.ts create mode 100644 src/planner/public-transport/CSAEarliestArrivalDynamic.ts diff --git a/package-lock.json b/package-lock.json index 3fb50a6e..d525a209 100644 --- a/package-lock.json +++ b/package-lock.json @@ -434,6 +434,1292 @@ } } }, + "@turf/along": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/along/-/along-5.1.5.tgz", + "integrity": "sha1-YdbmplhKzdq1asVYTge/jL5fi+s=", + "requires": { + "@turf/bearing": "^5.1.5", + "@turf/destination": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/area": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/area/-/area-5.1.5.tgz", + "integrity": "sha1-79iZv9Jgzb0VQbKjwVX4pdLu+h0=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/bbox": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-5.1.5.tgz", + "integrity": "sha1-MFHfUUrUxQ9KT5uKLRX9i2hA7aM=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/bbox-clip": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/bbox-clip/-/bbox-clip-5.1.5.tgz", + "integrity": "sha1-M2S1Mo3/nzz0HZ4C7a/zdNFQzIQ=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "lineclip": "^1.1.5" + } + }, + "@turf/bbox-polygon": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/bbox-polygon/-/bbox-polygon-5.1.5.tgz", + "integrity": "sha1-auuk7VHYXSluD3w4uIwznwHu4CQ=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/bearing": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/bearing/-/bearing-5.1.5.tgz", + "integrity": "sha1-egt5ATbE70eX8CRjBdRcvi0ns/c=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/bezier-spline": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/bezier-spline/-/bezier-spline-5.1.5.tgz", + "integrity": "sha1-WaJ7ul17l+8Vqz/VpA+9I4cEm8o=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/boolean-clockwise": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-clockwise/-/boolean-clockwise-5.1.5.tgz", + "integrity": "sha1-MwK32sYsXikaB4nimvcoM4f6nes=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/boolean-contains": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-contains/-/boolean-contains-5.1.5.tgz", + "integrity": "sha1-WW1jruY2961T7pn5/yTJaZSg7xQ=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/boolean-point-on-line": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/boolean-crosses": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-crosses/-/boolean-crosses-5.1.5.tgz", + "integrity": "sha1-Ab+uollvFk3kpNMlCU3HwlXHFdY=", + "requires": { + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-intersect": "^5.1.5", + "@turf/polygon-to-line": "^5.1.5" + } + }, + "@turf/boolean-disjoint": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@turf/boolean-disjoint/-/boolean-disjoint-5.1.6.tgz", + "integrity": "sha512-KHvUS6SBNYHBCLIJEJrg04pF5Oy+Fqn8V5G9U+9pti5vI9tyX7Ln2g7RSB7iJ1Cxsz8QAi6OukhXjEF2/8ZpGg==", + "requires": { + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/line-intersect": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/polygon-to-line": "^5.1.5" + } + }, + "@turf/boolean-equal": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-equal/-/boolean-equal-5.1.5.tgz", + "integrity": "sha1-Kfj21gu4RQff12WzIlTbjnLJOKQ=", + "requires": { + "@turf/clean-coords": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "geojson-equality": "0.1.6" + } + }, + "@turf/boolean-overlap": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-overlap/-/boolean-overlap-5.1.5.tgz", + "integrity": "sha1-DU5kxSx3CijpPZ7834qLg3OsznU=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-intersect": "^5.1.5", + "@turf/line-overlap": "^5.1.5", + "@turf/meta": "^5.1.5", + "geojson-equality": "0.1.6" + } + }, + "@turf/boolean-parallel": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-parallel/-/boolean-parallel-5.1.5.tgz", + "integrity": "sha1-c5NYR16ltlx+GCejw+DopofTqF0=", + "requires": { + "@turf/clean-coords": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/line-segment": "^5.1.5", + "@turf/rhumb-bearing": "^5.1.5" + } + }, + "@turf/boolean-point-in-polygon": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-in-polygon/-/boolean-point-in-polygon-5.1.5.tgz", + "integrity": "sha1-8BzBlNHgMKVIv9qYHLpDz9YpQbc=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/boolean-point-on-line": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-point-on-line/-/boolean-point-on-line-5.1.5.tgz", + "integrity": "sha1-9jPF/4Aq0ku48Vja269v9KAj3Xs=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/boolean-within": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/boolean-within/-/boolean-within-5.1.5.tgz", + "integrity": "sha1-RxBdVtB1Kp0Pv81Dw2pfkUnchpc=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/boolean-point-on-line": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/buffer": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/buffer/-/buffer-5.1.5.tgz", + "integrity": "sha1-hByWJ8+5dLEirE4alW8EZrwCMcQ=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/center": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/projection": "^5.1.5", + "d3-geo": "1.7.1", + "turf-jsts": "*" + } + }, + "@turf/center": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/center/-/center-5.1.5.tgz", + "integrity": "sha1-RKss2VT2PA03dX9xWKmcPvURS4A=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/center-mean": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/center-mean/-/center-mean-5.1.5.tgz", + "integrity": "sha1-jI6YdTkeXwnw5uePXWYbiLIQigo=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/center-median": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/center-median/-/center-median-5.1.5.tgz", + "integrity": "sha1-u0Yb/noqSGAdikcnaFcYcjoUqHI=", + "requires": { + "@turf/center-mean": "^5.1.5", + "@turf/centroid": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/center-of-mass": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/center-of-mass/-/center-of-mass-5.1.5.tgz", + "integrity": "sha1-TTvXnYhJjbq4Mk1PafAyL2Uguco=", + "requires": { + "@turf/centroid": "^5.1.5", + "@turf/convex": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/centroid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-5.1.5.tgz", + "integrity": "sha1-d4radCFjNQIa2P0OemWoNJ1Tx2k=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/circle": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/circle/-/circle-5.1.5.tgz", + "integrity": "sha1-mxV3g1UIq1L7HBCypQZcuiuHtqU=", + "requires": { + "@turf/destination": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/clean-coords": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/clean-coords/-/clean-coords-5.1.5.tgz", + "integrity": "sha1-EoAKmKeMmkUqcuxChJPEOs8q2h8=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/clone": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-5.1.5.tgz", + "integrity": "sha1-JT6NNUdxgZduM636tQoPAqfw42c=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/clusters": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/clusters/-/clusters-5.1.5.tgz", + "integrity": "sha1-ZzpeXxsZycq6vFfJCO6t1oIiTdQ=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/clusters-dbscan": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/clusters-dbscan/-/clusters-dbscan-5.1.5.tgz", + "integrity": "sha1-V4H7TmVsdHoLjpk333MYHAMJ4m8=", + "requires": { + "@turf/clone": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "density-clustering": "1.3.0" + } + }, + "@turf/clusters-kmeans": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/clusters-kmeans/-/clusters-kmeans-5.1.5.tgz", + "integrity": "sha1-/W3+qLEzuovcI3CsPKzuFYejAvE=", + "requires": { + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "skmeans": "0.9.7" + } + }, + "@turf/collect": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/collect/-/collect-5.1.5.tgz", + "integrity": "sha1-/pjJqMIY7PJP/DPXApUXt8GbKj4=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/helpers": "^5.1.5", + "rbush": "^2.0.1" + } + }, + "@turf/combine": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/combine/-/combine-5.1.5.tgz", + "integrity": "sha1-uxS976VVBDVxlfwaEkzX1TqMiQU=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/concave": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/concave/-/concave-5.1.5.tgz", + "integrity": "sha1-I7uqw4fQNLlldKG9cNBZI3qdIRA=", + "requires": { + "@turf/clone": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/tin": "^5.1.5", + "topojson-client": "3.x", + "topojson-server": "3.x" + } + }, + "@turf/convex": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/convex/-/convex-5.1.5.tgz", + "integrity": "sha1-Dfk3fdACIWzpghsH9wXgN9rj4B0=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5", + "concaveman": "*" + } + }, + "@turf/destination": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/destination/-/destination-5.1.5.tgz", + "integrity": "sha1-7TU4G9zoO73cvQei4rzivd/7zCY=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/difference": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/difference/-/difference-5.1.5.tgz", + "integrity": "sha1-ok1pCnvKgD8QkKnuO52Qb8Q3H0I=", + "requires": { + "@turf/area": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "turf-jsts": "*" + } + }, + "@turf/dissolve": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/dissolve/-/dissolve-5.1.5.tgz", + "integrity": "sha1-LPEzqQIdIWODHD16lY1lB/nYGTg=", + "requires": { + "@turf/boolean-overlap": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-intersect": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/union": "^5.1.5", + "geojson-rbush": "2.1.0", + "get-closest": "*" + } + }, + "@turf/distance": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-5.1.5.tgz", + "integrity": "sha1-Oc8YIEu/h1h9cH5gmmARiQkVZAk=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/ellipse": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/ellipse/-/ellipse-5.1.5.tgz", + "integrity": "sha1-1XyrhTmFkgzeYCKKeNgEWAJcVL4=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/rhumb-destination": "^5.1.5", + "@turf/transform-rotate": "^5.1.5" + } + }, + "@turf/envelope": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/envelope/-/envelope-5.1.5.tgz", + "integrity": "sha1-UBMwnFP91D369LWIplw/7X28EIo=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/bbox-polygon": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/explode": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/explode/-/explode-5.1.5.tgz", + "integrity": "sha1-sSsvd0AEobSPYrqVsgocZVo94Rg=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/flatten": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/flatten/-/flatten-5.1.5.tgz", + "integrity": "sha1-2iknBnEz7WFpsLnWB7khVoiqE1g=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/flip": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/flip/-/flip-5.1.5.tgz", + "integrity": "sha1-Q29kOnIvDKU7n85jjkaT2zYIpoo=", + "requires": { + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/great-circle": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/great-circle/-/great-circle-5.1.5.tgz", + "integrity": "sha1-3r+2cc5HVQnLY3MBwV/PzPo1mpM=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/helpers": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-5.1.5.tgz", + "integrity": "sha1-FTQFInq5M9AEpbuWQantmZ/L4M8=" + }, + "@turf/hex-grid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/hex-grid/-/hex-grid-5.1.5.tgz", + "integrity": "sha1-m3ul/s9QUfHoWJL3E/zlxVBQKmo=", + "requires": { + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/intersect": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/interpolate": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/interpolate/-/interpolate-5.1.5.tgz", + "integrity": "sha1-DxLwq3VtbdEK+ykMpuh3ve8BPqo=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/centroid": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/hex-grid": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/point-grid": "^5.1.5", + "@turf/square-grid": "^5.1.5", + "@turf/triangle-grid": "^5.1.5" + } + }, + "@turf/intersect": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@turf/intersect/-/intersect-5.1.6.tgz", + "integrity": "sha512-KXyNv/GXdoGAOy03qZF53rgtXC2tNhF/4jLwTKiVRrBQH6kcEpipGStdJ+QkYIlarQPa8f7I9UlVAB19et4MfQ==", + "requires": { + "@turf/clean-coords": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/truncate": "^5.1.5", + "turf-jsts": "*" + } + }, + "@turf/invariant": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-5.1.5.tgz", + "integrity": "sha1-9Z9P76CSJLFdzhZR+QPIaNV6JOE=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/isobands": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/isobands/-/isobands-5.1.5.tgz", + "integrity": "sha1-a0TO9YTVUaMTBBh68jtKFYLj8I0=", + "requires": { + "@turf/area": "^5.1.5", + "@turf/bbox": "^5.1.5", + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/explode": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/isolines": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/isolines/-/isolines-5.1.5.tgz", + "integrity": "sha1-irTn9Cuz38VGFOW/FVln9+VdLeE=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/kinks": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/kinks/-/kinks-5.1.5.tgz", + "integrity": "sha1-irtpYdm7AQchO63fLCwmQNAlaYA=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/length": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/length/-/length-5.1.5.tgz", + "integrity": "sha1-86X4ZMK5lqi7RxeUU1ofrxLuvvs=", + "requires": { + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/line-arc": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-arc/-/line-arc-5.1.5.tgz", + "integrity": "sha1-AHinRHg1oSrkFKIR+aZNEYYVDhU=", + "requires": { + "@turf/circle": "^5.1.5", + "@turf/destination": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/line-chunk": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-chunk/-/line-chunk-5.1.5.tgz", + "integrity": "sha1-kQqFwFwG2dD5w4l3oF4IGNUIXEI=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/length": "^5.1.5", + "@turf/line-slice-along": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/line-intersect": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-intersect/-/line-intersect-5.1.5.tgz", + "integrity": "sha1-DikHGuQDKV5JFyO8SfXPrI0R3fM=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-segment": "^5.1.5", + "@turf/meta": "^5.1.5", + "geojson-rbush": "2.1.0" + } + }, + "@turf/line-offset": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-offset/-/line-offset-5.1.5.tgz", + "integrity": "sha1-KrWy8In4yRPiMdmUN4553KkLWh4=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/line-overlap": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-overlap/-/line-overlap-5.1.5.tgz", + "integrity": "sha1-lDxvh6A4bcQ9+sEdKz/5wRLNP2A=", + "requires": { + "@turf/boolean-point-on-line": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-segment": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/nearest-point-on-line": "^5.1.5", + "geojson-rbush": "2.1.0" + } + }, + "@turf/line-segment": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-segment/-/line-segment-5.1.5.tgz", + "integrity": "sha1-Mgeq7lRqskw9jcPMY/kcdwuAE+U=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/line-slice": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-slice/-/line-slice-5.1.5.tgz", + "integrity": "sha1-Hs/OFGKjeFeXVM7fRGTN4mgp8rU=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/nearest-point-on-line": "^5.1.5" + } + }, + "@turf/line-slice-along": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-slice-along/-/line-slice-along-5.1.5.tgz", + "integrity": "sha1-7drQoh70efKWihG9LdcomiEy6aU=", + "requires": { + "@turf/bearing": "^5.1.5", + "@turf/destination": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/line-split": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-split/-/line-split-5.1.5.tgz", + "integrity": "sha1-Wy30w3YZty73JbUWPPmSbVVArLc=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-intersect": "^5.1.5", + "@turf/line-segment": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/nearest-point-on-line": "^5.1.5", + "@turf/square": "^5.1.5", + "@turf/truncate": "^5.1.5", + "geojson-rbush": "2.1.0" + } + }, + "@turf/line-to-polygon": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/line-to-polygon/-/line-to-polygon-5.1.5.tgz", + "integrity": "sha1-ITz0Gmj4Ikd4ujnTGH3sPouBhlo=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/mask": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/mask/-/mask-5.1.5.tgz", + "integrity": "sha1-mrD+8aJyyY/j70kvn/thggayQtU=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/union": "^5.1.5", + "rbush": "^2.0.1" + } + }, + "@turf/meta": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-5.1.6.tgz", + "integrity": "sha1-wgqGPt7Qhp+yhUje6Ik0G8y0akY=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/midpoint": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/midpoint/-/midpoint-5.1.5.tgz", + "integrity": "sha1-4mH2srDqgSTM7/VSomLdRlydBfA=", + "requires": { + "@turf/bearing": "^5.1.5", + "@turf/destination": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/nearest-point": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/nearest-point/-/nearest-point-5.1.5.tgz", + "integrity": "sha1-EgUN5Bw5hEMiTHl43g9iE5ANNPs=", + "requires": { + "@turf/clone": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/nearest-point-on-line": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/nearest-point-on-line/-/nearest-point-on-line-5.1.5.tgz", + "integrity": "sha1-VgauKX8VlHUkvqUaKp71HsG/nDY=", + "requires": { + "@turf/bearing": "^5.1.5", + "@turf/destination": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-intersect": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/nearest-point-to-line": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@turf/nearest-point-to-line/-/nearest-point-to-line-5.1.6.tgz", + "integrity": "sha512-ZSvDIEiHhifn/vNwLXZI/E8xmEz5yBPqfUR7BVHRZrB1cP7jLhKZvkbidjG//uW8Fr1Ulc+PFOXczLspIcx/lw==", + "requires": { + "@turf/helpers": "6.x", + "@turf/invariant": "6.x", + "@turf/meta": "6.x", + "@turf/point-to-line-distance": "^5.1.5", + "object-assign": "*" + }, + "dependencies": { + "@turf/helpers": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.1.4.tgz", + "integrity": "sha512-vJvrdOZy1ngC7r3MDA7zIGSoIgyrkWcGnNIEaqn/APmw+bVLF2gAW7HIsdTxd12s5wQMqEpqIQrmrbRRZ0xC7g==" + }, + "@turf/invariant": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.1.2.tgz", + "integrity": "sha512-WU08Ph8j0J2jVGlQCKChXoCtI50BB3yEH21V++V0T4cR1T27HKCxkehV2sYMwTierfMBgjwSwDIsxnR4/2mWXg==", + "requires": { + "@turf/helpers": "6.x" + } + }, + "@turf/meta": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.0.2.tgz", + "integrity": "sha512-VA7HJkx7qF1l3+GNGkDVn2oXy4+QoLP6LktXAaZKjuT1JI0YESat7quUkbCMy4zP9lAUuvS4YMslLyTtr919FA==", + "requires": { + "@turf/helpers": "6.x" + } + } + } + }, + "@turf/planepoint": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/planepoint/-/planepoint-5.1.5.tgz", + "integrity": "sha1-GLvfAG91ne9eQsagBsn53oGyt/8=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/point-grid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/point-grid/-/point-grid-5.1.5.tgz", + "integrity": "sha1-MFFBJI9Quv42zn5mukuX56sjaIc=", + "requires": { + "@turf/boolean-within": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/point-on-feature": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/point-on-feature/-/point-on-feature-5.1.5.tgz", + "integrity": "sha1-MMfwMkMCd8ZBjZbSieRba/shP+c=", + "requires": { + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/center": "^5.1.5", + "@turf/explode": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/nearest-point": "^5.1.5" + } + }, + "@turf/point-to-line-distance": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@turf/point-to-line-distance/-/point-to-line-distance-5.1.6.tgz", + "integrity": "sha512-PE3hiTeeDEi4ZLPtI8XAzFYW9nHo1EVsZGm/4ZVV8jo39d3X1oLVHxY3e1PkCmWwRapXy4QLqvnTQ7nU4wspNw==", + "requires": { + "@turf/bearing": "6.x", + "@turf/distance": "6.x", + "@turf/helpers": "6.x", + "@turf/invariant": "6.x", + "@turf/meta": "6.x", + "@turf/projection": "6.x", + "@turf/rhumb-bearing": "6.x", + "@turf/rhumb-distance": "6.x" + }, + "dependencies": { + "@turf/bearing": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@turf/bearing/-/bearing-6.0.1.tgz", + "integrity": "sha512-mXY1NozqV9EFfBTbUItujwfqfQF0G/Xe2fzvnZle90ekPEUfhi4Dgf5JswJTd96J9LiT8kcd6Jonp5khnx0wIg==", + "requires": { + "@turf/helpers": "6.x", + "@turf/invariant": "6.x" + } + }, + "@turf/clone": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@turf/clone/-/clone-6.0.2.tgz", + "integrity": "sha512-UVpYPnW3wRj3bPncR6Z2PRbowBk+nEdVWgGewPxrKKLfvswtVtG9n/OIyvbU3E3ZOadBVxTH2uAMEMOz4800FA==", + "requires": { + "@turf/helpers": "6.x" + } + }, + "@turf/distance": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@turf/distance/-/distance-6.0.1.tgz", + "integrity": "sha512-q7t7rWIWfkg7MP1Vt4uLjSEhe5rPfCO2JjpKmk7JC+QZKEQkuvHEqy3ejW1iC7Kw5ZcZNR3qdMGGz+6HnVwqvg==", + "requires": { + "@turf/helpers": "6.x", + "@turf/invariant": "6.x" + } + }, + "@turf/helpers": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.1.4.tgz", + "integrity": "sha512-vJvrdOZy1ngC7r3MDA7zIGSoIgyrkWcGnNIEaqn/APmw+bVLF2gAW7HIsdTxd12s5wQMqEpqIQrmrbRRZ0xC7g==" + }, + "@turf/invariant": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@turf/invariant/-/invariant-6.1.2.tgz", + "integrity": "sha512-WU08Ph8j0J2jVGlQCKChXoCtI50BB3yEH21V++V0T4cR1T27HKCxkehV2sYMwTierfMBgjwSwDIsxnR4/2mWXg==", + "requires": { + "@turf/helpers": "6.x" + } + }, + "@turf/meta": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.0.2.tgz", + "integrity": "sha512-VA7HJkx7qF1l3+GNGkDVn2oXy4+QoLP6LktXAaZKjuT1JI0YESat7quUkbCMy4zP9lAUuvS4YMslLyTtr919FA==", + "requires": { + "@turf/helpers": "6.x" + } + }, + "@turf/projection": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-6.0.1.tgz", + "integrity": "sha512-Y3RvGT6I53MjYKLG69e9sMk45wJXcLbrEO1t6P3WQQQGqA2gYhhMJyV41vE2Z2llrJpvs2dDx/tIeQzGd0HHMQ==", + "requires": { + "@turf/clone": "6.x", + "@turf/helpers": "6.x", + "@turf/meta": "6.x" + } + }, + "@turf/rhumb-bearing": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@turf/rhumb-bearing/-/rhumb-bearing-6.0.1.tgz", + "integrity": "sha512-MVBra8OVfjM4+/N0B3o6cBIYg9p/uRKzA9uk05RfrzasEbUL1vdD23LkTooVL74Yw4UxL8BQD9hS5Re2COJFDA==", + "requires": { + "@turf/helpers": "6.x", + "@turf/invariant": "6.x" + } + }, + "@turf/rhumb-distance": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@turf/rhumb-distance/-/rhumb-distance-6.0.1.tgz", + "integrity": "sha512-3G45DQtQByzzfHFPcCyJdUZFwsd45zfZ7sAb1ddF7mhEj4G70+T2G3GKjInymqDNrbyh2gbG6wQiZSToC8Uf9g==", + "requires": { + "@turf/helpers": "6.x", + "@turf/invariant": "6.x" + } + } + } + }, + "@turf/points-within-polygon": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/points-within-polygon/-/points-within-polygon-5.1.5.tgz", + "integrity": "sha1-K4VaXfOq2lfC7oIKB1SrlJKKIzc=", + "requires": { + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/polygon-tangents": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/polygon-tangents/-/polygon-tangents-5.1.5.tgz", + "integrity": "sha1-K/AJkUcwJbF44lDcfLmuVAm71lI=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/polygon-to-line": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/polygon-to-line/-/polygon-to-line-5.1.5.tgz", + "integrity": "sha1-I7tEjYTcTGUZmaxhGjbZHFklA2o=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/polygonize": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/polygonize/-/polygonize-5.1.5.tgz", + "integrity": "sha1-BJP6EYefOdELmtAs5qI+lC0IqjI=", + "requires": { + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/envelope": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/projection": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/projection/-/projection-5.1.5.tgz", + "integrity": "sha1-JFF+7rLzaBa6n3EueubWo2jt91c=", + "requires": { + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/random": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/random/-/random-5.1.5.tgz", + "integrity": "sha1-sy78k0Vgroulfo67UfJBw5+6Lns=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/rewind": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/rewind/-/rewind-5.1.5.tgz", + "integrity": "sha1-nqPbSmi3PB/R3RH1djGxQ8/vock=", + "requires": { + "@turf/boolean-clockwise": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/rhumb-bearing": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/rhumb-bearing/-/rhumb-bearing-5.1.5.tgz", + "integrity": "sha1-rPalAkJ+uMSeGM2mrg7/qwxd3NI=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/rhumb-destination": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/rhumb-destination/-/rhumb-destination-5.1.5.tgz", + "integrity": "sha1-sbKuuSFUfyrAwamUtqEw+SRjx0I=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/rhumb-distance": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/rhumb-distance/-/rhumb-distance-5.1.5.tgz", + "integrity": "sha1-GAaFdiX0IlOE2tQT5p85U4/192U=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/sample": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/sample/-/sample-5.1.5.tgz", + "integrity": "sha1-6ctEikeJzFbuPeLdZ4HiNDQ1tBE=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/sector": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/sector/-/sector-5.1.5.tgz", + "integrity": "sha1-rCu5TBPt1gNPb9wrZwCBNdIPXgc=", + "requires": { + "@turf/circle": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/line-arc": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/shortest-path": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/shortest-path/-/shortest-path-5.1.5.tgz", + "integrity": "sha1-hUroCW9rw+EwD6ynfz6PZ9j5Nas=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/bbox-polygon": "^5.1.5", + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/clean-coords": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/transform-scale": "^5.1.5" + } + }, + "@turf/simplify": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/simplify/-/simplify-5.1.5.tgz", + "integrity": "sha1-Csjyei60IYGD7dmZjDJ1q+QIuSY=", + "requires": { + "@turf/clean-coords": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/square": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/square/-/square-5.1.5.tgz", + "integrity": "sha1-qnsh5gM8ySUsOlvW89iNq9b+0YA=", + "requires": { + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5" + } + }, + "@turf/square-grid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/square-grid/-/square-grid-5.1.5.tgz", + "integrity": "sha1-G9X3uesU8LYLwjH+/nNR0aMvGlE=", + "requires": { + "@turf/boolean-contains": "^5.1.5", + "@turf/boolean-overlap": "^5.1.5", + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/intersect": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/standard-deviational-ellipse": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/standard-deviational-ellipse/-/standard-deviational-ellipse-5.1.5.tgz", + "integrity": "sha1-hc0oO14ayljyG9ZkEuQUtW2FIyQ=", + "requires": { + "@turf/center-mean": "^5.1.5", + "@turf/ellipse": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/points-within-polygon": "^5.1.5" + } + }, + "@turf/tag": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/tag/-/tag-5.1.5.tgz", + "integrity": "sha1-0e4aUIjs/UoUEQGcmCOczypJfSA=", + "requires": { + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/tesselate": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/tesselate/-/tesselate-5.1.5.tgz", + "integrity": "sha1-MqWU6cIaAEIKn5DSxD3z4RZgYc0=", + "requires": { + "@turf/helpers": "^5.1.5", + "earcut": "^2.0.0" + } + }, + "@turf/tin": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/tin/-/tin-5.1.5.tgz", + "integrity": "sha1-KCI+r8X76a6azKgc3P6l0UJMkX0=", + "requires": { + "@turf/helpers": "^5.1.5" + } + }, + "@turf/transform-rotate": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/transform-rotate/-/transform-rotate-5.1.5.tgz", + "integrity": "sha1-0Jbt2eMA/jFQadVNjkWMQJIh7fs=", + "requires": { + "@turf/centroid": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/rhumb-bearing": "^5.1.5", + "@turf/rhumb-destination": "^5.1.5", + "@turf/rhumb-distance": "^5.1.5" + } + }, + "@turf/transform-scale": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/transform-scale/-/transform-scale-5.1.5.tgz", + "integrity": "sha1-cP064BhWz3uunxWtVhzf6PiQAbk=", + "requires": { + "@turf/bbox": "^5.1.5", + "@turf/center": "^5.1.5", + "@turf/centroid": "^5.1.5", + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/rhumb-bearing": "^5.1.5", + "@turf/rhumb-destination": "^5.1.5", + "@turf/rhumb-distance": "^5.1.5" + } + }, + "@turf/transform-translate": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/transform-translate/-/transform-translate-5.1.5.tgz", + "integrity": "sha1-Uwolf7Hccmja3Ks05nkB6yo97GM=", + "requires": { + "@turf/clone": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "@turf/meta": "^5.1.5", + "@turf/rhumb-destination": "^5.1.5" + } + }, + "@turf/triangle-grid": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/triangle-grid/-/triangle-grid-5.1.5.tgz", + "integrity": "sha1-ezZ2IQhVTBTyjK/zxIsc/ILI3IE=", + "requires": { + "@turf/distance": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/intersect": "^5.1.5", + "@turf/invariant": "^5.1.5" + } + }, + "@turf/truncate": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/truncate/-/truncate-5.1.5.tgz", + "integrity": "sha1-nu37Oxi6gfLJjT6tCUMcyhiErYk=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5" + } + }, + "@turf/turf": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@turf/turf/-/turf-5.1.6.tgz", + "integrity": "sha1-wxIlkoh+0jS3VGi4qMRb+Ib7+PY=", + "requires": { + "@turf/along": "5.1.x", + "@turf/area": "5.1.x", + "@turf/bbox": "5.1.x", + "@turf/bbox-clip": "5.1.x", + "@turf/bbox-polygon": "5.1.x", + "@turf/bearing": "5.1.x", + "@turf/bezier-spline": "5.1.x", + "@turf/boolean-clockwise": "5.1.x", + "@turf/boolean-contains": "5.1.x", + "@turf/boolean-crosses": "5.1.x", + "@turf/boolean-disjoint": "5.1.x", + "@turf/boolean-equal": "5.1.x", + "@turf/boolean-overlap": "5.1.x", + "@turf/boolean-parallel": "5.1.x", + "@turf/boolean-point-in-polygon": "5.1.x", + "@turf/boolean-point-on-line": "5.1.x", + "@turf/boolean-within": "5.1.x", + "@turf/buffer": "5.1.x", + "@turf/center": "5.1.x", + "@turf/center-mean": "5.1.x", + "@turf/center-median": "5.1.x", + "@turf/center-of-mass": "5.1.x", + "@turf/centroid": "5.1.x", + "@turf/circle": "5.1.x", + "@turf/clean-coords": "5.1.x", + "@turf/clone": "5.1.x", + "@turf/clusters": "5.1.x", + "@turf/clusters-dbscan": "5.1.x", + "@turf/clusters-kmeans": "5.1.x", + "@turf/collect": "5.1.x", + "@turf/combine": "5.1.x", + "@turf/concave": "5.1.x", + "@turf/convex": "5.1.x", + "@turf/destination": "5.1.x", + "@turf/difference": "5.1.x", + "@turf/dissolve": "5.1.x", + "@turf/distance": "5.1.x", + "@turf/ellipse": "5.1.x", + "@turf/envelope": "5.1.x", + "@turf/explode": "5.1.x", + "@turf/flatten": "5.1.x", + "@turf/flip": "5.1.x", + "@turf/great-circle": "5.1.x", + "@turf/helpers": "5.1.x", + "@turf/hex-grid": "5.1.x", + "@turf/interpolate": "5.1.x", + "@turf/intersect": "5.1.x", + "@turf/invariant": "5.1.x", + "@turf/isobands": "5.1.x", + "@turf/isolines": "5.1.x", + "@turf/kinks": "5.1.x", + "@turf/length": "5.1.x", + "@turf/line-arc": "5.1.x", + "@turf/line-chunk": "5.1.x", + "@turf/line-intersect": "5.1.x", + "@turf/line-offset": "5.1.x", + "@turf/line-overlap": "5.1.x", + "@turf/line-segment": "5.1.x", + "@turf/line-slice": "5.1.x", + "@turf/line-slice-along": "5.1.x", + "@turf/line-split": "5.1.x", + "@turf/line-to-polygon": "5.1.x", + "@turf/mask": "5.1.x", + "@turf/meta": "5.1.x", + "@turf/midpoint": "5.1.x", + "@turf/nearest-point": "5.1.x", + "@turf/nearest-point-on-line": "5.1.x", + "@turf/nearest-point-to-line": "5.1.x", + "@turf/planepoint": "5.1.x", + "@turf/point-grid": "5.1.x", + "@turf/point-on-feature": "5.1.x", + "@turf/point-to-line-distance": "5.1.x", + "@turf/points-within-polygon": "5.1.x", + "@turf/polygon-tangents": "5.1.x", + "@turf/polygon-to-line": "5.1.x", + "@turf/polygonize": "5.1.x", + "@turf/projection": "5.1.x", + "@turf/random": "5.1.x", + "@turf/rewind": "5.1.x", + "@turf/rhumb-bearing": "5.1.x", + "@turf/rhumb-destination": "5.1.x", + "@turf/rhumb-distance": "5.1.x", + "@turf/sample": "5.1.x", + "@turf/sector": "5.1.x", + "@turf/shortest-path": "5.1.x", + "@turf/simplify": "5.1.x", + "@turf/square": "5.1.x", + "@turf/square-grid": "5.1.x", + "@turf/standard-deviational-ellipse": "5.1.x", + "@turf/tag": "5.1.x", + "@turf/tesselate": "5.1.x", + "@turf/tin": "5.1.x", + "@turf/transform-rotate": "5.1.x", + "@turf/transform-scale": "5.1.x", + "@turf/transform-translate": "5.1.x", + "@turf/triangle-grid": "5.1.x", + "@turf/truncate": "5.1.x", + "@turf/union": "5.1.x", + "@turf/unkink-polygon": "5.1.x", + "@turf/voronoi": "5.1.x" + } + }, + "@turf/union": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/union/-/union-5.1.5.tgz", + "integrity": "sha1-UyhbYJQEf8WNlqrA6pCGXsNNRUs=", + "requires": { + "@turf/helpers": "^5.1.5", + "turf-jsts": "*" + } + }, + "@turf/unkink-polygon": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/unkink-polygon/-/unkink-polygon-5.1.5.tgz", + "integrity": "sha1-ewGEfFD7V0riV54Z5Ey6hSbSE8M=", + "requires": { + "@turf/area": "^5.1.5", + "@turf/boolean-point-in-polygon": "^5.1.5", + "@turf/helpers": "^5.1.5", + "@turf/meta": "^5.1.5", + "rbush": "^2.0.1" + } + }, + "@turf/voronoi": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@turf/voronoi/-/voronoi-5.1.5.tgz", + "integrity": "sha1-6FbpQG3MLyXWbdyJhYTifC6/ymY=", + "requires": { + "@turf/helpers": "^5.1.5", + "@turf/invariant": "^5.1.5", + "d3-voronoi": "1.1.2" + } + }, "@types/babel__core": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.3.tgz", @@ -2372,6 +3658,11 @@ "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", "dev": true }, + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==" + }, "d3-delaunay": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-4.1.5.tgz", @@ -2380,6 +3671,19 @@ "delaunator": "^2.0.0" } }, + "d3-geo": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.7.1.tgz", + "integrity": "sha512-O4AempWAr+P5qbk2bC2FuN/sDW4z+dN2wDf9QV3bxQt4M5HfOEeXLgJ/UKQW0+o1Dj8BE+L5kiDbdWUMjsmQpw==", + "requires": { + "d3-array": "1" + } + }, + "d3-voronoi": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.2.tgz", + "integrity": "sha1-Fodmfo8TotFYyAwUgMWinLDYlzw=" + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -2441,7 +3745,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz", "integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==", - "dev": true, "requires": { "is-arguments": "^1.0.4", "is-date-object": "^1.0.1", @@ -2470,7 +3773,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -2570,6 +3872,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "density-clustering": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/density-clustering/-/density-clustering-1.3.0.tgz", + "integrity": "sha1-3J9ZyPCrl+FiSsZJMP0xlIF9ysU=" + }, "depd": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", @@ -2684,6 +3991,11 @@ "stream-shift": "^1.0.0" } }, + "earcut": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.1.tgz", + "integrity": "sha512-5jIMi2RB3HtGPHcYd9Yyl0cczo84y+48lgKPxMijliNQaKAHEZJbdzLmKmdxG/mCdS/YD9DQ1gihL8mxzR0F9w==" + }, "ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -3946,8 +5258,25 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "geojson-equality": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/geojson-equality/-/geojson-equality-0.1.6.tgz", + "integrity": "sha1-oXE3TvBD5dR5eZWEC65GSOB1LXI=", + "requires": { + "deep-equal": "^1.0.0" + } + }, + "geojson-rbush": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/geojson-rbush/-/geojson-rbush-2.1.0.tgz", + "integrity": "sha1-O9c745H8ELCuaT2bis6iquC4Oo0=", + "requires": { + "@turf/helpers": "*", + "@turf/meta": "*", + "rbush": "*" + } }, "get-caller-file": { "version": "1.0.3", @@ -3955,6 +5284,11 @@ "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, + "get-closest": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/get-closest/-/get-closest-0.0.4.tgz", + "integrity": "sha1-JprHdtHmAiqg/Vht1wjop9Miaa8=" + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -4129,7 +5463,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -4418,8 +5751,7 @@ "inherits": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, "ini": { "version": "1.3.5", @@ -4499,8 +5831,7 @@ "is-arguments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" }, "is-arrayish": { "version": "0.2.1", @@ -4550,8 +5881,7 @@ "is-date-object": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", - "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", - "dev": true + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=" }, "is-descriptor": { "version": "0.1.6", @@ -4659,7 +5989,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", - "dev": true, "requires": { "has": "^1.0.1" } @@ -4698,8 +6027,7 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "isexe": { "version": "2.0.0", @@ -5656,6 +6984,11 @@ "type-check": "~0.3.2" } }, + "lineclip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/lineclip/-/lineclip-1.1.5.tgz", + "integrity": "sha1-K/JgZ9lDVP6r+R5CdoI221YW/RM=" + }, "load-json-file": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", @@ -6289,8 +7622,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -6323,14 +7655,12 @@ "object-is": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz", - "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=", - "dev": true + "integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY=" }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -7408,7 +8738,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "dev": true, "requires": { "define-properties": "^1.1.2" } @@ -7914,6 +9243,11 @@ "integrity": "sha512-SbEG75TzH8G7eVXFSN5f9EExILKfly7SUvVY5DhhYLvfhKqhDFY0OzevWa/zwak0RLRfWS5AvfMWpd9gJvr5Yg==", "dev": true }, + "skmeans": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/skmeans/-/skmeans-0.9.7.tgz", + "integrity": "sha512-hNj1/oZ7ygsfmPZ7ZfN5MUBRoGg1gtpnImuJBgLO0ljQ67DtJuiQaiYdS4lUA6s0KCwnPhGivtC/WRwIZLkHyg==" + }, "slash": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", @@ -8635,6 +9969,22 @@ "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", "dev": true }, + "topojson-client": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz", + "integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==", + "requires": { + "commander": "2" + } + }, + "topojson-server": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/topojson-server/-/topojson-server-3.0.1.tgz", + "integrity": "sha512-/VS9j/ffKr2XAOjlZ9CgyyeLmgJ9dMwq6Y0YEON8O7p/tGGk+dCWnrE03zEdu7i4L7YsFZLEPZPzCvcB7lEEXw==", + "requires": { + "commander": "2" + } + }, "tough-cookie": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", @@ -9050,6 +10400,11 @@ "safe-buffer": "^5.0.1" } }, + "turf-jsts": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/turf-jsts/-/turf-jsts-1.2.3.tgz", + "integrity": "sha512-Ja03QIJlPuHt4IQ2FfGex4F4JAr8m3jpaHbFbQrgwr7s7L6U8ocrHiF3J1+wf9jzhGKxvDeaCAnGDot8OjGFyA==" + }, "tweetnacl": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", @@ -9103,8 +10458,7 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typedoc": { "version": "0.15.0", @@ -9342,8 +10696,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "util.promisify": { "version": "1.0.0", @@ -9817,6 +11170,55 @@ "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "dev": true }, + "wellknown": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wellknown/-/wellknown-0.5.0.tgz", + "integrity": "sha1-Ca6YcfqCbPCm7BU37wDDedeNcQE=", + "requires": { + "concat-stream": "~1.5.0", + "minimist": "~1.2.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.5.2.tgz", + "integrity": "sha1-cIl4Yk2FavQaWnQd790mHadSwmY=", + "requires": { + "inherits": "~2.0.1", + "readable-stream": "~2.0.0", + "typedarray": "~0.0.5" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" + }, + "readable-stream": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.6.tgz", + "integrity": "sha1-j5A0HmilPMySh4jaz80Rs265t44=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "~1.0.0", + "process-nextick-args": "~1.0.6", + "string_decoder": "~0.10.x", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, "whatwg-encoding": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", diff --git a/package.json b/package.json index 2086390c..29e007ac 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "start": "webpack-dev-server --open" }, "dependencies": { + "@turf/turf": "^5.1.6", "@types/concaveman": "^1.1.3", "@types/node": "^12.7.8", "asynciterator": "^2.0.1", @@ -45,7 +46,8 @@ "tiles-in-bbox": "^1.0.2", "tinyqueue": "^2.0.2", "uri-templates": "^0.2.0", - "uritemplate": "^0.3.4" + "uritemplate": "^0.3.4", + "wellknown": "^0.5.0" }, "pre-commit": [ "lint" diff --git a/src/configs/flexible_transit.ts b/src/configs/flexible_transit.ts index f342a4f6..e9dc932f 100644 --- a/src/configs/flexible_transit.ts +++ b/src/configs/flexible_transit.ts @@ -24,6 +24,10 @@ import IRoutableTileFetcher from "../fetcher/tiles/IRoutableTileFetcher"; import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; +import HypermediaTreeFetcherDefault from "../fetcher/tree/HypermediaTreeFetcherDefault"; +import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDeault"; +import IHypermediaTreeProvider from "../fetcher/tree/IHeadermediaTreeProvider"; +import IHypermediaTreeFetcher from "../fetcher/tree/IHypermediaTreeFetcher"; import { LDLoader } from "../loader/ldloader"; import { BidirDijkstra } from "../pathfinding/bidirdijkstra/BidirDijkstra"; import DijkstraTree from "../pathfinding/dijkstra-tree/DijkstraTree"; @@ -49,8 +53,6 @@ container.bind(TYPES.Context).to(Context).inSingletonScope(); container.bind(TYPES.QueryRunner).to(QueryRunnerDefault); container.bind(TYPES.LocationResolver).to(LocationResolverConvenience); -container.bind(TYPES.HydraTemplateFetcher).to(HydraTemplateFetcherDefault).inSingletonScope(); - // TODO, make this a fixed property of the planner itself container.bind(TYPES.JourneyExtractor) .to(JourneyExtractorProfile); @@ -63,6 +65,11 @@ container.bind>(TYPES.PublicTranspor container.bind(TYPES.RoadPlanner) .to(RoadPlannerPathfinding); +container.bind(TYPES.HydraTemplateFetcher).to(HydraTemplateFetcherDefault).inSingletonScope(); +container.bind(TYPES.HypermediaTreeFetcher).to(HypermediaTreeFetcherDefault).inSingletonScope(); +container.bind(TYPES.HypermediaTreeProvider) + .to(HypermediaTreeProviderDefault).inSingletonScope(); + container.bind(TYPES.ShortestPathTreeAlgorithm).to(DijkstraTree).inSingletonScope(); container.bind(TYPES.ShortestPathAlgorithm).to(BidirDijkstra).inSingletonScope(); container.bind(TYPES.PathfinderProvider).to(PathfinderProvider).inSingletonScope(); diff --git a/src/configs/geospatial_fragment.ts b/src/configs/geospatial_fragment.ts new file mode 100644 index 00000000..5a43c345 --- /dev/null +++ b/src/configs/geospatial_fragment.ts @@ -0,0 +1,130 @@ +import { Container, interfaces } from "inversify"; +import Catalog from "../Catalog"; +import Context from "../Context"; +import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; +import RoutingPhase from "../enums/RoutingPhase"; +import TravelMode from "../enums/TravelMode"; +import ConnectionsFetcherRaw from "../fetcher/connections/ConnectionsFetcherRaw"; +import ConnectionsProviderDefault from "../fetcher/connections/ConnectionsProviderDefault"; +import IConnectionsFetcher from "../fetcher/connections/IConnectionsFetcher"; +import IConnectionsProvider from "../fetcher/connections/IConnectionsProvider"; +import HydraTemplateFetcherDefault from "../fetcher/hydra/HydraTemplateFetcherDefault"; +import IHydraTemplateFetcher from "../fetcher/hydra/IHydraTemplateFetcher"; +import LDFetch from "../fetcher/LDFetch"; +import IProfileFetcher from "../fetcher/profiles/IProfileFetcher"; +import IProfileProvider from "../fetcher/profiles/IProfileProvider"; +import ProfileFetcherDefault from "../fetcher/profiles/ProfileFetcherDefault"; +import ProfileProviderDefault from "../fetcher/profiles/ProfileProviderDefault"; +import IStopsFetcher from "../fetcher/stops/IStopsFetcher"; +import IStopsProvider from "../fetcher/stops/IStopsProvider"; +import StopsFetcherRaw from "../fetcher/stops/StopsFetcherRaw"; +import StopsProviderDefault from "../fetcher/stops/StopsProviderDefault"; +import IRoutableTileFetcher from "../fetcher/tiles/IRoutableTileFetcher"; +import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; +import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; +import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; +import HypermediaTreeFetcherDefault from "../fetcher/tree/HypermediaTreeFetcherDefault"; +import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDeault"; +import IHypermediaTreeProvider from "../fetcher/tree/IHeadermediaTreeProvider"; +import IHypermediaTreeFetcher from "../fetcher/tree/IHypermediaTreeFetcher"; +import { LDLoader } from "../loader/ldloader"; +import { BidirDijkstra } from "../pathfinding/bidirdijkstra/BidirDijkstra"; +import DijkstraTree from "../pathfinding/dijkstra-tree/DijkstraTree"; +import { IShortestPathAlgorithm, IShortestPathTreeAlgorithm } from "../pathfinding/pathfinder"; +import PathfinderProvider from "../pathfinding/PathfinderProvider"; +import CSAEarliestArrivalDynamic from "../planner/public-transport/CSAEarliestArrivalDynamic"; +import IJourneyExtractor from "../planner/public-transport/IJourneyExtractor"; +import IPublicTransportPlanner from "../planner/public-transport/IPublicTransportPlanner"; +import JourneyExtractorProfile from "../planner/public-transport/JourneyExtractorProfile"; +import IRoadPlanner from "../planner/road/IRoadPlanner"; +import RoadPlannerPathfinding from "../planner/road/RoadPlannerPathfinding"; +import IReachableStopsFinder from "../planner/stops/IReachableStopsFinder"; +import ReachableStopsFinderBirdsEyeCached from "../planner/stops/ReachableStopsFinderBirdsEyeCached"; +import ReachableStopsFinderOnlySelf from "../planner/stops/ReachableStopsFinderOnlySelf"; +import ILocationResolver from "../query-runner/ILocationResolver"; +import IQueryRunner from "../query-runner/IQueryRunner"; +import LocationResolverConvenience from "../query-runner/LocationResolverConvenience"; +import QueryRunnerDefault from "../query-runner/QueryRunnerDefault"; +import TYPES from "../types"; + +import FootpathsProviderRaw from "../fetcher/footpaths/FootpathsProviderRaw"; +import IFootpathsFetcher from "../fetcher/footpaths/IFootpathsProvider"; + +const container = new Container(); +container.bind(TYPES.Context).to(Context).inSingletonScope(); +container.bind(TYPES.QueryRunner).to(QueryRunnerDefault); +container.bind(TYPES.LocationResolver).to(LocationResolverConvenience); + +container.bind(TYPES.HydraTemplateFetcher).to(HydraTemplateFetcherDefault).inSingletonScope(); +container.bind(TYPES.HypermediaTreeFetcher).to(HypermediaTreeFetcherDefault).inSingletonScope(); +container.bind(TYPES.HypermediaTreeProvider) + .to(HypermediaTreeProviderDefault).inSingletonScope(); + +// TODO, make this a fixed property of the planner itself +container.bind(TYPES.JourneyExtractor) + .to(JourneyExtractorProfile); + +container.bind(TYPES.PublicTransportPlanner) + .to(CSAEarliestArrivalDynamic); +container.bind>(TYPES.PublicTransportPlannerFactory) + .toAutoFactory(TYPES.PublicTransportPlanner); + +container.bind(TYPES.RoadPlanner) + .to(RoadPlannerPathfinding); + +container.bind(TYPES.ShortestPathTreeAlgorithm).to(DijkstraTree).inSingletonScope(); +container.bind(TYPES.ShortestPathAlgorithm).to(BidirDijkstra).inSingletonScope(); +container.bind(TYPES.PathfinderProvider).to(PathfinderProvider).inSingletonScope(); +container.bind(TYPES.ProfileFetcher).to(ProfileFetcherDefault).inSingletonScope(); +container.bind(TYPES.ProfileProvider).to(ProfileProviderDefault).inSingletonScope(); + +container.bind(TYPES.FootpathsProvider).to(FootpathsProviderRaw).inSingletonScope(); + +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderOnlySelf).whenTargetTagged("phase", ReachableStopsSearchPhase.Initial); +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderBirdsEyeCached).whenTargetTagged("phase", ReachableStopsSearchPhase.Transfer); +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderOnlySelf).whenTargetTagged("phase", ReachableStopsSearchPhase.Final); + +container.bind(TYPES.ConnectionsProvider).to(ConnectionsProviderDefault).inSingletonScope(); +container.bind(TYPES.ConnectionsFetcher).to(ConnectionsFetcherRaw); +container.bind>(TYPES.ConnectionsFetcherFactory) + .toFactory( + (context: interfaces.Context) => + (travelMode: TravelMode) => { + const fetcher = context.container.get(TYPES.ConnectionsFetcher); + + fetcher.setTravelMode(travelMode); + + return fetcher; + }, + ); + +container.bind(TYPES.StopsProvider).to(StopsProviderDefault).inSingletonScope(); +container.bind(TYPES.StopsFetcher).to(StopsFetcherRaw); +container.bind>(TYPES.StopsFetcherFactory) + .toFactory( + (context: interfaces.Context) => + (accessUrl: string) => { + const fetcher = context.container.get(TYPES.StopsFetcher); + fetcher.setAccessUrl(accessUrl); + return fetcher; + }, + ); + +container.bind(TYPES.RoutableTileFetcher).to(RoutableTileFetcherRaw).inSingletonScope(); +container.bind(TYPES.RoutableTileProvider) + .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Base); +container.bind(TYPES.RoutableTileProvider) + .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); + +// Bind empty catalog +container.bind(TYPES.Catalog).toConstantValue(new Catalog()); + +// Init LDFetch +container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); + +container.bind(TYPES.LDLoader).to(LDLoader); + +export default container; diff --git a/src/entities/tree/geometry.ts b/src/entities/tree/geometry.ts new file mode 100644 index 00000000..e58ebe5b --- /dev/null +++ b/src/entities/tree/geometry.ts @@ -0,0 +1,21 @@ +import * as turf from "@turf/turf"; +import { MultiPolygon, Polygon } from "@turf/turf"; +import ILocation from "../../interfaces/ILocation"; + +export default class GeometryValue { + public static create(id?: string) { + return new GeometryValue(id); + } + + public id: string; + public area: Polygon | MultiPolygon; + + constructor(id?: string) { + this.id = id; + } + + public contains(location: ILocation): boolean { + const pt = turf.point([location.longitude, location.latitude]); // x, y format + return turf.booleanPointInPolygon(pt, this.area); + } +} diff --git a/src/entities/tree/relation.ts b/src/entities/tree/relation.ts new file mode 100644 index 00000000..a3277f92 --- /dev/null +++ b/src/entities/tree/relation.ts @@ -0,0 +1,20 @@ +import GeometryValue from "./geometry"; + +enum RelationTypes { + GEOSPATIALLYC_CONTAINS = "https://w3id.org/tree#GeospatiallyContainsRelation", +} + +export default class HypermediaTreeRelation { + public static create(id?: string) { + return new HypermediaTreeRelation(id); + } + + public id?: string; + public type: RelationTypes; + public geoValue: GeometryValue; + public node: string; + + constructor(id?: string) { + this.id = id; + } +} diff --git a/src/entities/tree/tree.ts b/src/entities/tree/tree.ts new file mode 100644 index 00000000..9bc8c4f8 --- /dev/null +++ b/src/entities/tree/tree.ts @@ -0,0 +1,14 @@ +import HypermediaTreeRelation from "./relation"; + +export default class HypermediaTree { + public static create(id?: string) { + return new HypermediaTree(id); + } + + public id?: string; + public relations: HypermediaTreeRelation[]; + + constructor(id?: string) { + this.id = id; + } +} diff --git a/src/events/EventType.ts b/src/events/EventType.ts index 1b03246a..03662115 100644 --- a/src/events/EventType.ts +++ b/src/events/EventType.ts @@ -21,6 +21,8 @@ enum EventType { ReachableStop = "ReachableStop", ReachableTile = "ReachableTile", + + Downloaded = "Downloaded", } export default EventType; diff --git a/src/fetcher/connections/ConnectionsFetcherRaw.ts b/src/fetcher/connections/ConnectionsFetcherRaw.ts index 75d56ac9..8c058229 100644 --- a/src/fetcher/connections/ConnectionsFetcherRaw.ts +++ b/src/fetcher/connections/ConnectionsFetcherRaw.ts @@ -36,6 +36,8 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { const beginTime = new Date(); const response = await fetch(url); + const size = parseInt(response.headers.get("content-length"), 10); + EventBus.getInstance().emit(EventType.Downloaded, size); const responseText = await response.text(); if (response.status !== 200) { EventBus.getInstance().emit(EventType.Warning, `${url} responded with status code ${response.status}`); @@ -99,9 +101,6 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { const duration = (new Date()).getTime() - beginTime.getTime(); EventBus.getInstance().emit(EventType.LDFetchGet, url, duration); - EventBus.getInstance().emit(EventType.ConnectionPrefetch, connections[0].departureTime); - EventBus.getInstance().emit(EventType.ConnectionPrefetch, - connections[connections.length - 1].departureTime); connections.sort((a, b) => { return a.departureTime.getTime() - b.departureTime.getTime(); diff --git a/src/fetcher/connections/ConnectionsProviderDefault.ts b/src/fetcher/connections/ConnectionsProviderDefault.ts index 359a6bf5..2c9748c0 100644 --- a/src/fetcher/connections/ConnectionsProviderDefault.ts +++ b/src/fetcher/connections/ConnectionsProviderDefault.ts @@ -14,6 +14,7 @@ import IConnectionsProvider from "./IConnectionsProvider"; @injectable() export default class ConnectionsProviderDefault implements IConnectionsProvider { + private accessUrls: string[]; private singleProviders: ConnectionsProviderSingle[]; private connectionsFetcherFactory: ConnectionsFetcherFactory; private templateFetcher: IHydraTemplateFetcher; @@ -23,6 +24,7 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider @inject(TYPES.Catalog) catalog: Catalog, @inject(TYPES.HydraTemplateFetcher) templateFetcher: IHydraTemplateFetcher, ) { + this.accessUrls = []; this.singleProviders = []; this.connectionsFetcherFactory = connectionsFetcherFactory; this.templateFetcher = templateFetcher; @@ -33,6 +35,7 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider } public addConnectionSource(source: IConnectionsSourceConfig) { + this.accessUrls.push(source.accessUrl); this.singleProviders.push( new ConnectionsProviderSingle(this.connectionsFetcherFactory, source, this.templateFetcher), ); @@ -48,10 +51,7 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider const iterators = await Promise.all(this.singleProviders .map((provider) => provider.createIterator(options))); - const selector = options.backward ? - backwardsConnectionsSelector - : - forwardsConnectionSelector; + const selector = options.backward ? backwardsConnectionsSelector : forwardsConnectionSelector; if (options.excludedModes) { return new MergeIterator(iterators, selector, true).filter((item) => { @@ -62,6 +62,35 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider } } + public async appendIterator( + options: IConnectionsIteratorOptions, + existingIterator: AsyncIterator, + ): Promise> { + const iterators = await Promise.all(this.singleProviders + .map((provider) => provider.createIterator(options))); + + const selector = options.backward ? backwardsConnectionsSelector : forwardsConnectionSelector; + + const dataListeners = existingIterator.listeners("data"); + const readListeners = existingIterator.listeners("readable"); + const endListeners = existingIterator.listeners("end"); + + existingIterator.removeAllListeners(); + + const mergedIterator = new MergeIterator([...iterators, existingIterator], selector, true); + for (const listener of dataListeners) { + mergedIterator.addListener("data", listener as (...args: any[]) => void); + } + for (const listener of readListeners) { + mergedIterator.addListener("readable", listener as (...args: any[]) => void); + } + for (const listener of endListeners) { + mergedIterator.addListener("end", listener as (...args: any[]) => void); + } + + return mergedIterator; + } + public getByUrl(url: string): Promise { // TODO, if needed this can delegate the call to one of the sub providers throw new Error("Not implemented yet"); diff --git a/src/fetcher/connections/ConnectionsProviderSingle.ts b/src/fetcher/connections/ConnectionsProviderSingle.ts index 5c0e89f9..caf701ab 100644 --- a/src/fetcher/connections/ConnectionsProviderSingle.ts +++ b/src/fetcher/connections/ConnectionsProviderSingle.ts @@ -5,10 +5,13 @@ import { IConnectionsSourceConfig } from "../../Catalog"; import IConnection from "../../entities/connections/connections"; import { ILinkedConnectionsPageIndex, LinkedConnectionsPage } from "../../entities/connections/page"; import { HydraTemplate } from "../../entities/hydra/search"; +import GeometryValue from "../../entities/tree/geometry"; import EventBus from "../../events/EventBus"; import { ConnectionsFetcherFactory } from "../../types"; +import MergeIterator from "../../util/iterators/MergeIterator"; import IHydraTemplateFetcher from "../hydra/IHydraTemplateFetcher"; import BackwardConnectionIterator from "./BackwardConnectionIterator"; +import { backwardsConnectionsSelector, forwardsConnectionSelector } from "./ConnectionSelectors"; import ForwardConnectionIterator from "./ForwardConnectionIterator"; import IConnectionsFetcher from "./IConnectionsFetcher"; import IConnectionsIteratorOptions from "./IConnectionsIteratorOptions"; @@ -44,23 +47,31 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { return await this.pages[url]; } - public async getByTime(date: Date): Promise { + public async getByTime(date: Date, region?: GeometryValue): Promise { // TODO, look up in the index -- use lower/upper bounds of each page - const url = await this.getIdForTime(date); + const url = await this.getIdForTime(date, region); return this.getByUrl(url); } - public async getIdForTime(date: Date): Promise { + public async getIdForTime(date: Date, region?: GeometryValue): Promise { const template = await this.getTemplate(); - return template.fill({ - "http://semweb.mmlab.be/ns/linkedconnections#departureTimeQuery": date.toISOString(), - }); + if (region) { + return template.fill({ + "http://www.opengis.net/ont/geosparql#hasGeometry": region.id, + "http://semweb.mmlab.be/ns/linkedconnections#departureTimeQuery": date.toISOString(), + }); + } else { + return template.fill({ + "http://semweb.mmlab.be/ns/linkedconnections#departureTimeQuery": date.toISOString(), + }); + } } public prefetchConnections(lowerBound: Date, upperBound: Date): void { this.createIterator({ upperBoundDate: upperBound, lowerBoundDate: lowerBound, + region: null, }).then((iterator) => { iterator.on("readable", () => { while (iterator.read()) { @@ -70,6 +81,49 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { }); } + public async appendIterator( + options: IConnectionsIteratorOptions, + existingIterator: AsyncIterator, + ): Promise> { + EventBus.getInstance().emit( + EventType.ConnectionIteratorView, + options.lowerBoundDate, + options.upperBoundDate, + ); + + const selector = options.backward ? backwardsConnectionsSelector : forwardsConnectionSelector; + + let iterator: AsyncIterator; + if (options.backward) { + const beginTime = options.upperBoundDate; + const beginUrl = await this.getIdForTime(beginTime, options.region); + iterator = new BackwardConnectionIterator(this, options, beginUrl); + } else { + const beginTime = options.lowerBoundDate; + const beginUrl = await this.getIdForTime(beginTime, options.region); + iterator = new ForwardConnectionIterator(this, options, beginUrl); + } + + const dataListeners = existingIterator.listeners("data"); + const readListeners = existingIterator.listeners("readable"); + const endListeners = existingIterator.listeners("end"); + + existingIterator.removeAllListeners(); + + const mergedIterator = new MergeIterator([iterator, existingIterator], selector, true); + for (const listener of dataListeners) { + mergedIterator.addListener("data", listener as (...args: any[]) => void); + } + for (const listener of readListeners) { + mergedIterator.addListener("readable", listener as (...args: any[]) => void); + } + for (const listener of endListeners) { + mergedIterator.addListener("end", listener as (...args: any[]) => void); + } + + return mergedIterator; + } + public async createIterator(options: IConnectionsIteratorOptions): Promise> { EventBus.getInstance().emit( EventType.ConnectionIteratorView, @@ -80,11 +134,11 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { let iterator: AsyncIterator; if (options.backward) { const beginTime = options.upperBoundDate; - const beginUrl = await this.getIdForTime(beginTime); + const beginUrl = await this.getIdForTime(beginTime, options.region); iterator = new BackwardConnectionIterator(this, options, beginUrl); } else { const beginTime = options.lowerBoundDate; - const beginUrl = await this.getIdForTime(beginTime); + const beginUrl = await this.getIdForTime(beginTime, options.region); iterator = new ForwardConnectionIterator(this, options, beginUrl); } diff --git a/src/fetcher/connections/ForwardConnectionIterator.ts b/src/fetcher/connections/ForwardConnectionIterator.ts index 0954b3fd..944387d5 100644 --- a/src/fetcher/connections/ForwardConnectionIterator.ts +++ b/src/fetcher/connections/ForwardConnectionIterator.ts @@ -13,6 +13,8 @@ export default class ForwardConnectionIterator extends AsyncIterator 25) { + this.close(); + return null; + } + if (this.currentIndex >= this.currentPage.getConnections().length) { // end of this page, fetch the next one this.fetchPage(this.currentPage.getNextPageId()); diff --git a/src/fetcher/connections/IConnectionsIteratorOptions.ts b/src/fetcher/connections/IConnectionsIteratorOptions.ts index 01ffec4e..ff552891 100644 --- a/src/fetcher/connections/IConnectionsIteratorOptions.ts +++ b/src/fetcher/connections/IConnectionsIteratorOptions.ts @@ -1,3 +1,4 @@ +import GeometryValue from "../../entities/tree/geometry"; import TravelMode from "../../enums/TravelMode"; /** @@ -9,4 +10,5 @@ export default interface IConnectionsIteratorOptions { lowerBoundDate?: Date; backward?: boolean; excludedModes?: Set; + region: GeometryValue; } diff --git a/src/fetcher/connections/IConnectionsProvider.ts b/src/fetcher/connections/IConnectionsProvider.ts index 6f1a282e..9ce0d9e0 100644 --- a/src/fetcher/connections/IConnectionsProvider.ts +++ b/src/fetcher/connections/IConnectionsProvider.ts @@ -2,14 +2,19 @@ import { AsyncIterator } from "asynciterator"; import { IConnectionsSourceConfig } from "../../Catalog"; import IConnection from "../../entities/connections/connections"; import { LinkedConnectionsPage } from "../../entities/connections/page"; +import GeometryValue from "../../entities/tree/geometry"; import IConnectionsIteratorOptions from "./IConnectionsIteratorOptions"; export default interface IConnectionsProvider { addConnectionSource(source: IConnectionsSourceConfig); prefetchConnections(lowerBound: Date, upperBound: Date): void; + appendIterator( + options: IConnectionsIteratorOptions, + existingIterator: AsyncIterator, + ): Promise>; createIterator(options: IConnectionsIteratorOptions): Promise>; getByUrl(url: string): Promise; - getByTime(date: Date): Promise; + getByTime(date: Date, region?: GeometryValue): Promise; } diff --git a/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts b/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts index 75ac9ad6..364247f8 100644 --- a/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts +++ b/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts @@ -15,6 +15,13 @@ export default class ConnectionsProviderNMBSTest implements IConnectionsProvider this.connections = connections; } + public appendIterator( + options: IConnectionsIteratorOptions, + existingIterator: AsyncIterator, + ): Promise> { + throw new Error("Method not implemented."); + } + public addConnectionSource(source: IConnectionsSourceConfig) { throw new Error("Method not implemented."); } diff --git a/src/fetcher/tree/HypermediaTreeFetcherDefault.ts b/src/fetcher/tree/HypermediaTreeFetcherDefault.ts new file mode 100644 index 00000000..0ee9a675 --- /dev/null +++ b/src/fetcher/tree/HypermediaTreeFetcherDefault.ts @@ -0,0 +1,74 @@ +import { inject, injectable } from "inversify"; +import LDFetch from "ldfetch"; +import { LDLoader } from "../../loader/ldloader"; +import { ThingView } from "../../loader/views/single"; +import TYPES from "../../types"; +import { GEOSPARQL, RDF, TREE } from "../../uri/constants"; +import URI from "../../uri/uri"; + +import GeoFragment from "../../entities/tree/geometry"; +import HypermediaTreeRelation from "../../entities/tree/relation"; +import HypermediaTree from "../../entities/tree/tree"; +import IHypermediaTreeFetcher from "./IHypermediaTreeFetcher"; + +@injectable() +export default class HypermediaTreeFetcherDefault implements IHypermediaTreeFetcher { + + protected ldFetch: LDFetch; + protected ldLoader: LDLoader; + + constructor( + @inject(TYPES.LDFetch) ldFetch: LDFetch, + ) { + this.ldFetch = ldFetch; + this.ldLoader = new LDLoader(); + this.ldLoader.defineCollection(URI.inNS(TREE, "relation")); + } + + public async get(url: string): Promise { + const rdfThing = await this.ldFetch.get(url); + const triples = rdfThing.triples; + + const [fragment] = this.ldLoader.process(triples, [ + this.getView(), + ]); + + fragment.id = url; + + return fragment; + } + + protected getView() { + const view = new ThingView(HypermediaTree.create); + view.addFilter( + (entity) => { + return entity[URI.inNS(TREE, "relation")] !== undefined; + }, + ); + view.addMapping(URI.inNS(TREE, "relation"), "relations", this.getRelationView()); + return view; + } + + protected getRelationView() { + const view = new ThingView(HypermediaTreeRelation.create); + view.addFilter( + (entity) => { + return entity[URI.inNS(RDF, "type")] === URI.inNS(TREE, "GeospatiallyContainsRelation"); + }, + ); + view.addMapping(URI.inNS(TREE, "node"), "node"); + view.addMapping(URI.inNS(TREE, "value"), "geoValue", this.getFragmentView()); + return view; + } + + protected getFragmentView() { + const view = new ThingView(GeoFragment.create); + view.addFilter( + (entity) => { + return entity[URI.inNS(RDF, "type")] === URI.inNS(GEOSPARQL, "Geometry"); + }, + ); + view.addMapping(URI.inNS(GEOSPARQL, "asWKT"), "area"); + return view; + } +} diff --git a/src/fetcher/tree/HypermediaTreeProviderDeault.ts b/src/fetcher/tree/HypermediaTreeProviderDeault.ts new file mode 100644 index 00000000..60524dc0 --- /dev/null +++ b/src/fetcher/tree/HypermediaTreeProviderDeault.ts @@ -0,0 +1,40 @@ +import { inject, injectable } from "inversify"; +import Catalog from "../../Catalog"; +import HypermediaTree from "../../entities/tree/tree"; +import TYPES from "../../types"; +import IHypermediaTreeProvider from "./IHeadermediaTreeProvider"; +import IHypermediaTreeFetcher from "./IHypermediaTreeFetcher"; + +@injectable() +export default class HypermediaTreeProviderDefault implements IHypermediaTreeProvider { + private accessUrls: string[]; + private allTrees: Promise; + private treeFetcher: IHypermediaTreeFetcher; + + constructor( + @inject(TYPES.HypermediaTreeFetcher) treeFetcher: IHypermediaTreeFetcher, + @inject(TYPES.Catalog) catalog: Catalog, + ) { + this.accessUrls = []; + this.treeFetcher = treeFetcher; + + for (const { accessUrl } of catalog.connectionsSourceConfigs) { + this.addTreeSource(accessUrl); + } + } + + public addTreeSource(accessUrl: string) { + this.allTrees = null; + this.accessUrls.push(accessUrl); + } + + public async getAllTrees(): Promise { + if (!this.allTrees) { + this.allTrees = Promise.all(this.accessUrls + .map((url: string) => this.treeFetcher.get(url)), + ); + } + + return this.allTrees; + } +} diff --git a/src/fetcher/tree/IHeadermediaTreeProvider.ts b/src/fetcher/tree/IHeadermediaTreeProvider.ts new file mode 100644 index 00000000..17196a3d --- /dev/null +++ b/src/fetcher/tree/IHeadermediaTreeProvider.ts @@ -0,0 +1,6 @@ +import HypermediaTree from "../../entities/tree/tree"; + +export default interface IHypermediaTreeProvider { + addTreeSource(accessUrl: string); + getAllTrees(): Promise; +} diff --git a/src/fetcher/tree/IHypermediaTreeFetcher.ts b/src/fetcher/tree/IHypermediaTreeFetcher.ts new file mode 100644 index 00000000..8735319c --- /dev/null +++ b/src/fetcher/tree/IHypermediaTreeFetcher.ts @@ -0,0 +1,5 @@ +import HypermediaTree from "../../entities/tree/tree"; + +export default interface IHypermediaTreeFetcher { + get(url: string): Promise; +} diff --git a/src/index.ts b/src/index.ts index ec10d29e..f62037a8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,6 +11,7 @@ import BasicTrainPlanner from "./planner/configurations/BasicTrainPlanner"; import DelijnNmbsPlanner from "./planner/configurations/DelijnNmbsPlanner"; import DissectPlanner from "./planner/configurations/DissectPlanner"; import FlexibleTransitPlanner from "./planner/configurations/FlexibleTransitPlanner"; +import GeospatialFragmentedPlanner from "./planner/configurations/GeospatialFragmentedPlanner"; import TransitCarPlanner from "./planner/configurations/TransitCarPlanner"; import TriangleDemoPlanner from "./planner/configurations/TriangleDemoPlanner"; import Units from "./util/Units"; @@ -24,6 +25,7 @@ export { default as DelijnNmbsPlanner } from "./planner/configurations/DelijnNmb export { default as DissectPlanner } from "./planner/configurations/DissectPlanner"; export { default as TransitCarPlanner } from "./planner/configurations/TransitCarPlanner"; export { default as FlexibleTransitPlanner } from "./planner/configurations/FlexibleTransitPlanner"; +export { default as GeospatialFragmentedPlanner } from "./planner/configurations/GeospatialFragmentedPlanner"; export { default as TriangleDemoPlanner } from "./planner/configurations/TriangleDemoPlanner"; export { default as TravelMode } from "./enums/TravelMode"; @@ -44,4 +46,5 @@ export default { TriangleDemoPlanner, RoutableTileRegistry, FlexibleTransitPlanner, + GeospatialFragmentedPlanner, }; diff --git a/src/loader/ldloader.ts b/src/loader/ldloader.ts index 00a2adc0..c111b4cc 100644 --- a/src/loader/ldloader.ts +++ b/src/loader/ldloader.ts @@ -1,6 +1,7 @@ import { injectable } from "inversify"; import { Triple } from "rdf-js"; -import { XMLS } from "../uri/constants"; +import parse = require("wellknown"); +import { GEOSPARQL, XMLS } from "../uri/constants"; import URI from "../uri/uri"; import { IEntity, IEntityMap } from "./common"; import { ThingView } from "./views/single"; @@ -44,12 +45,13 @@ export class LDLoader { const tripleObject = triple.object; const rawValue = tripleObject.value; if (tripleObject.termType === "BlankNode") { - if (!entities[rawValue]) { - entities[rawValue] = { id: rawValue }; - } - return entities[rawValue]; } + if (tripleObject.termType === "NamedNode") { + if (entities[rawValue]) { + return entities[rawValue]; + } + } if (tripleObject.termType === "Literal") { const valueType = tripleObject.datatype.value; if (valueType === URI.inNS(XMLS, "string")) { @@ -64,19 +66,33 @@ export class LDLoader { if (valueType === URI.inNS(XMLS, "integer")) { return parseInt(rawValue, 10); } + if (valueType === URI.inNS(GEOSPARQL, "wktLiteral")) { + return this.parseWktLiteral(rawValue); + } } return rawValue; } + private parseWktLiteral(raw: string) { + const [reference, ...rest] = raw.split(" "); + if (reference === "") { + return parse(rest.join(" ")); + } + return parse(raw); + } + private _extractEntities(triples): IEntityMap { const entities = {}; for (const triple of triples) { - const { subject: { value: subject }, predicate: { value: predicate } } = triple; + const { subject: { value: subject } } = triple; if (!(subject in entities)) { entities[subject] = { id: subject }; } + } + for (const triple of triples) { + const { subject: { value: subject }, predicate: { value: predicate } } = triple; const entity = entities[subject]; const parsedValue = this._parseValue(entities, triple); diff --git a/src/planner/configurations/GeospatialFragmentedPlanner.ts b/src/planner/configurations/GeospatialFragmentedPlanner.ts new file mode 100644 index 00000000..7706a122 --- /dev/null +++ b/src/planner/configurations/GeospatialFragmentedPlanner.ts @@ -0,0 +1,19 @@ +import config from "../../configs/geospatial_fragment"; +import TravelMode from "../../enums/TravelMode"; +import IHypermediaTreeProvider from "../../fetcher/tree/IHeadermediaTreeProvider"; +import TYPES from "../../types"; +import Planner from "./Planner"; + +export default class GeospatialFragmentedPlanner extends Planner { + private treeProvider: IHypermediaTreeProvider; + + constructor() { + super(config); + this.treeProvider = config.get(TYPES.HypermediaTreeProvider); + } + + public addConnectionSource(accessUrl: string, travelMode = TravelMode.Train) { + super.addConnectionSource(accessUrl, travelMode); + this.treeProvider.addTreeSource(accessUrl); + } +} diff --git a/src/planner/public-transport/CSA/FootpathQueue.ts b/src/planner/public-transport/CSA/FootpathQueue.ts index 27b88229..08e61ad9 100644 --- a/src/planner/public-transport/CSA/FootpathQueue.ts +++ b/src/planner/public-transport/CSA/FootpathQueue.ts @@ -22,6 +22,8 @@ export default class FootpathQueue extends AsyncIterator { this.readable = true; this.shouldClose = false; + + this.setMaxListeners(100); } public read(): IConnection { diff --git a/src/planner/public-transport/CSAEarliestArrival.ts b/src/planner/public-transport/CSAEarliestArrival.ts index 0fcbfdaa..0a3f42eb 100644 --- a/src/planner/public-transport/CSAEarliestArrival.ts +++ b/src/planner/public-transport/CSAEarliestArrival.ts @@ -88,6 +88,7 @@ export default class CSAEarliestArrival implements IPublicTransportPlanner { upperBoundDate, lowerBoundDate, excludedModes: query.excludedTravelModes, + region: null, }); const connectionsQueue = new MergeIterator( diff --git a/src/planner/public-transport/CSAEarliestArrivalDynamic.ts b/src/planner/public-transport/CSAEarliestArrivalDynamic.ts new file mode 100644 index 00000000..00e7511a --- /dev/null +++ b/src/planner/public-transport/CSAEarliestArrivalDynamic.ts @@ -0,0 +1,459 @@ +import { ArrayIterator, AsyncIterator } from "asynciterator"; +import { EventEmitter } from "events"; +import { inject, injectable, tagged } from "inversify"; +import IConnection from "../../entities/connections/connections"; +import GeometryValue from "../../entities/tree/geometry"; +import HypermediaTree from "../../entities/tree/tree"; +import DropOffType from "../../enums/DropOffType"; +import PickupType from "../../enums/PickupType"; +import ReachableStopsFinderMode from "../../enums/ReachableStopsFinderMode"; +import ReachableStopsSearchPhase from "../../enums/ReachableStopsSearchPhase"; +import TravelMode from "../../enums/TravelMode"; +import EventBus from "../../events/EventBus"; +import EventType from "../../events/EventType"; +import { forwardsConnectionSelector } from "../../fetcher/connections/ConnectionSelectors"; +import IConnectionsProvider from "../../fetcher/connections/IConnectionsProvider"; +import IStop from "../../fetcher/stops/IStop"; +import IStopsProvider from "../../fetcher/stops/IStopsProvider"; +import IHypermediaTreeProvider from "../../fetcher/tree/IHeadermediaTreeProvider"; +import ILocation from "../../interfaces/ILocation"; +import IPath from "../../interfaces/IPath"; +import ILocationResolver from "../../query-runner/ILocationResolver"; +import IResolvedQuery from "../../query-runner/IResolvedQuery"; +import TYPES from "../../types"; +import Geo from "../../util/Geo"; +import MergeIterator from "../../util/iterators/MergeIterator"; +import IReachableStopsFinder, { IReachableStop } from "../stops/IReachableStopsFinder"; +import IProfileByStop from "./CSA/data-structure/stops/IProfileByStop"; +import ITransferProfile from "./CSA/data-structure/stops/ITransferProfile"; +import IEnterConnectionByTrip from "./CSA/data-structure/trips/IEnterConnectionByTrip"; +import FootpathQueue from "./CSA/FootpathQueue"; +import IJourneyExtractor from "./IJourneyExtractor"; +import IPublicTransportPlanner from "./IPublicTransportPlanner"; +import JourneyExtractorEarliestArrival from "./JourneyExtractorEarliestArrival"; + +interface IFinalReachableStops { + [stop: string]: IReachableStop; +} + +interface IQueryState { + finalReachableStops: IFinalReachableStops; + profilesByStop: IProfileByStop; // S + enterConnectionByTrip: IEnterConnectionByTrip; // T + footpathsQueue: FootpathQueue; + connectionsIterator: AsyncIterator; + mergedQueue: AsyncIterator; + clusterStops: object; + lowerBoundDate: Date; +} + +// Implementation is as close as possible to the original paper: https://arxiv.org/pdf/1703.05997.pdf + +@injectable() +export default class CSAEarliestArrivalDynamic implements IPublicTransportPlanner { + protected readonly connectionsProvider: IConnectionsProvider; + protected readonly locationResolver: ILocationResolver; + protected readonly treeProvider: IHypermediaTreeProvider; + protected readonly transferReachableStopsFinder: IReachableStopsFinder; + protected readonly initialReachableStopsFinder: IReachableStopsFinder; + protected readonly finalReachableStopsFinder: IReachableStopsFinder; + protected readonly eventBus: EventEmitter; + + protected journeyExtractor: IJourneyExtractor; + protected reachedClusters: Set; + protected stopsProvider: IStopsProvider; + + constructor( + @inject(TYPES.ConnectionsProvider) + connectionsProvider: IConnectionsProvider, + @inject(TYPES.LocationResolver) + locationResolver: ILocationResolver, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Transfer) + transferReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Initial) + initialReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Final) + finalReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.HypermediaTreeProvider) + treeProvider: IHypermediaTreeProvider, + @inject(TYPES.StopsProvider) + stopsProvider: IStopsProvider, + ) { + this.reachedClusters = new Set(); + this.treeProvider = treeProvider; + this.connectionsProvider = connectionsProvider; + this.locationResolver = locationResolver; + this.transferReachableStopsFinder = transferReachableStopsFinder; + this.initialReachableStopsFinder = initialReachableStopsFinder; + this.finalReachableStopsFinder = finalReachableStopsFinder; + this.eventBus = EventBus.getInstance(); + this.journeyExtractor = new JourneyExtractorEarliestArrival(locationResolver); + this.stopsProvider = stopsProvider; + } + + public async plan(query: IResolvedQuery): Promise> { + const { + minimumDepartureTime: lowerBoundDate, + maximumArrivalTime: upperBoundDate, + } = query; + + const trees = await this.treeProvider.getAllTrees(); + const clusterStops = await this.clusterStops(trees); + const startLocation = clusterStops[Geo.getId(query.from[0])]; + this.reachedClusters.add(startLocation.id); + + const footpathsQueue = new FootpathQueue(); + const connectionsIterator = await this.connectionsProvider.createIterator({ + upperBoundDate, + lowerBoundDate, + excludedModes: query.excludedTravelModes, + region: startLocation, + }); + + const mergedQueue = new MergeIterator( + [connectionsIterator, footpathsQueue], + forwardsConnectionSelector, + true, + ); + + const queryState: IQueryState = { + finalReachableStops: {}, + profilesByStop: {}, + enterConnectionByTrip: {}, + footpathsQueue, + connectionsIterator, + clusterStops, + mergedQueue, + lowerBoundDate, + }; + + const [hasInitialReachableStops, hasFinalReachableStops] = await Promise.all([ + this.initInitialReachableStops(queryState, query), + this.initFinalReachableStops(queryState, query), + ]); + + if (!hasInitialReachableStops || !hasFinalReachableStops) { + return Promise.resolve(new ArrayIterator([])); + } + + const self = this; + return new Promise((resolve, reject) => { + let isDone: boolean = false; + + const done = () => { + if (!isDone) { + mergedQueue.close(); + + self.extractJourneys(queryState, query) + .then((resultIterator) => { + resolve(resultIterator); + }); + + isDone = true; + } + }; + + connectionsIterator.on("readable", () => + self.processConnections(queryState, query, done), + ); + + connectionsIterator.on("end", () => done()); + + // iterator may have become readable before the listener was attached + self.processConnections(queryState, query, done); + + }) as Promise>; + } + + protected async clusterStops(trees: HypermediaTree[]): Promise { + const stops = await this.stopsProvider.getAllStops(); + const result = {}; + for (const stop of stops) { + const cluster = this.placeLocation(stop, trees); + result[Geo.getId(stop)] = cluster; + } + return result; + } + + protected placeLocation(location: ILocation, trees: HypermediaTree[]): GeometryValue { + for (const tree of trees) { + for (const relation of tree.relations) { + if (relation.geoValue.contains(location)) { + return relation.geoValue; + } + } + } + + } + + protected async updateProfile(state: IQueryState, query: IResolvedQuery, connection: IConnection) { + /* + Call this ONLY if the given connection is known to improve the arrival stop's profile + */ + + const tripId = connection.tripId; + const departureTime = connection.departureTime.getTime(); + const arrivalTime = connection.arrivalTime.getTime(); + + // update profile of arrival stop + const arrivalProfile: ITransferProfile = { + departureTime, + arrivalTime, + exitConnection: connection, + enterConnection: state.enterConnectionByTrip[tripId], + }; + state.profilesByStop[connection.arrivalStop] = arrivalProfile; + + const cluster = state.clusterStops[connection.arrivalStop]; + if (cluster && !this.reachedClusters.has(cluster.id)) { + const { + maximumArrivalTime: upperBoundDate, + } = query; + + // console.log("REACHED", cluster.id); + + this.reachedClusters.add(cluster.id); + + const newConnectionIterator = await this.connectionsProvider.appendIterator({ + upperBoundDate, + lowerBoundDate: connection.departureTime, + excludedModes: query.excludedTravelModes, + region: cluster, + }, state.connectionsIterator); + + state.connectionsIterator = newConnectionIterator; + state.mergedQueue = new MergeIterator( + [newConnectionIterator, state.footpathsQueue], + forwardsConnectionSelector, + true, + ); + } + } + + private async extractJourneys(state: IQueryState, query: IResolvedQuery): Promise> { + return this.journeyExtractor.extractJourneys(state.profilesByStop, query); + } + + private async processConnections(state: IQueryState, query: IResolvedQuery, resolve: () => void) { + const { from, to, minimumDepartureTime } = query; + const departureStopId: string = from[0].id; + const arrivalStopId: string = to[0].id; + + let connection: IConnection = state.mergedQueue.read(); + + while (connection && !state.connectionsIterator.closed) { + if (connection.departureTime < state.lowerBoundDate && !state.connectionsIterator.closed) { + // starting criterion + // skip connections before the minimum departure time + connection = state.mergedQueue.read(); + continue; + } + + state.lowerBoundDate = connection.departureTime; + // console.log(connection.id, connection.departureTime) + + if (this.getProfile(state, arrivalStopId).arrivalTime <= connection.departureTime.getTime()) { + // stopping criterion + // we cannot improve the tentative arrival time anymore + return resolve(); + } + + const tripId = connection.tripId; + const departureTime = connection.departureTime.getTime(); + + const canRemainSeated = state.enterConnectionByTrip[tripId]; + const canTakeTransfer = ( + ( + connection.departureStop === departureStopId || + this.getProfile(state, connection.departureStop).arrivalTime <= departureTime + ) && + connection.pickupType !== PickupType.NotAvailable + ); + + if (canRemainSeated || canTakeTransfer) { + // enterConnectionByTrip should point to the first reachable connection + if (!state.enterConnectionByTrip[tripId]) { + state.enterConnectionByTrip[tripId] = connection; + } + + // limited walking optimization + const canImprove = connection.arrivalTime.getTime() < + this.getProfile(state, connection.arrivalStop).arrivalTime; + const canLeave = connection.dropOffType !== DropOffType.NotAvailable; + + if (canLeave && canImprove) { + this.updateProfile(state, query, connection); + await this.scheduleExtraConnections(state, query, connection); + } + } + + if (!state.connectionsIterator.closed) { + connection = state.mergedQueue.read(); + continue; + } + + connection = undefined; + } + } + + private getProfile(state: IQueryState, stopId: string): ITransferProfile { + if (!state.profilesByStop[stopId]) { + state.profilesByStop[stopId] = { + departureTime: Infinity, + arrivalTime: Infinity, + }; + } + return state.profilesByStop[stopId]; + } + + private async scheduleExtraConnections(state: IQueryState, query: IResolvedQuery, sourceConnection: IConnection) { + try { + const arrivalStop: ILocation = await this.locationResolver.resolve(sourceConnection.arrivalStop); + const reachableStops: IReachableStop[] = await this.transferReachableStopsFinder.findReachableStops( + arrivalStop as IStop, + ReachableStopsFinderMode.Source, + query.maximumTransferDuration, + query.minimumWalkingSpeed, + query.profileID, + ); + + if (state.finalReachableStops[arrivalStop.id]) { + reachableStops.push(state.finalReachableStops[arrivalStop.id]); + } + + for (const reachableStop of reachableStops) { + const { stop: stop, duration: duration } = reachableStop; + + if (duration && stop.id) { + const transferTentativeArrival = this.getProfile(state, stop.id).arrivalTime; + const newArrivalTime = new Date(sourceConnection.arrivalTime.getTime() + duration); + + if (transferTentativeArrival > newArrivalTime.getTime() && newArrivalTime <= query.maximumArrivalTime) { + + const tripId = `TRANSFER_TO:${sourceConnection.arrivalStop}@${sourceConnection.arrivalTime.getTime()}`; + + // create a connection that resembles a footpath + // TODO, ditch the IReachbleStop and IConnection interfaces and make these proper objects + const transferConnection: IConnection = { + id: `${tripId}-${stop.id}`, + tripId, + travelMode: TravelMode.Walking, // TODO, this should be part of the reachable stop object + departureTime: sourceConnection.arrivalTime, + departureStop: sourceConnection.arrivalStop, + arrivalTime: new Date(sourceConnection.arrivalTime.getTime() + duration), + arrivalStop: stop.id, + dropOffType: DropOffType.Regular, + pickupType: PickupType.Regular, + headsign: stop.id, + }; + + state.footpathsQueue.write(transferConnection); + } + } + } + } catch (e) { + if (this.eventBus) { + this.eventBus.emit(EventType.Warning, (e)); + } + } + } + + private async initInitialReachableStops(state: IQueryState, query: IResolvedQuery): Promise { + const fromLocation: ILocation = query.from[0]; + + // Making sure the departure location has an id + const geoId = Geo.getId(fromLocation); + if (!fromLocation.id) { + query.from[0].id = geoId; + query.from[0].name = "Departure location"; + } + + const reachableStops = await this.initialReachableStopsFinder.findReachableStops( + fromLocation, + ReachableStopsFinderMode.Source, + query.maximumWalkingDuration, + query.minimumWalkingSpeed, + query.profileID, + ); + + // Abort when we can't reach a single stop. + if (reachableStops.length === 0) { + this.eventBus.emit(EventType.AbortQuery, "No reachable stops at departure location"); + + return false; + } + + if (this.eventBus) { + this.eventBus.emit(EventType.InitialReachableStops, reachableStops); + } + + for (const reachableStop of reachableStops) { + const { stop: stop, duration: duration } = reachableStop; + + if (duration) { + // create a connection that resembles a footpath + // TODO, ditch the IReachbleStop and IConnection interfaces and make these proper objects + const transferConnection: IConnection = { + id: `MOVE_TO:${stop.id}`, + tripId: `MOVE_TO:${stop.id}`, + travelMode: TravelMode.Walking, // TODO, this should be part of the reachable stop object + departureTime: query.minimumDepartureTime, + departureStop: fromLocation.id, + arrivalTime: new Date(query.minimumDepartureTime.getTime() + duration), + arrivalStop: stop.id, + dropOffType: DropOffType.Regular, + pickupType: PickupType.Regular, + headsign: stop.id, + }; + + state.footpathsQueue.write(transferConnection); + } + } + + return true; + } + + private async initFinalReachableStops(state: IQueryState, query: IResolvedQuery): Promise { + const toLocation: ILocation = query.to[0]; + + // Making sure the departure location has an id + const geoId = Geo.getId(toLocation); + if (!toLocation.id) { + query.to[0].id = geoId; + query.to[0].name = "Arrival location"; + } + + const reachableStops = await this.finalReachableStopsFinder.findReachableStops( + toLocation, + ReachableStopsFinderMode.Target, + query.maximumWalkingDuration, + query.minimumWalkingSpeed, + query.profileID, + ); + + // Abort when we can't reach a single stop. + if (reachableStops.length === 0) { + this.eventBus.emit(EventType.AbortQuery, "No reachable stops at arrival location"); + + return false; + } + + if (this.eventBus) { + this.eventBus.emit(EventType.FinalReachableStops, reachableStops); + } + + for (const reachableStop of reachableStops) { + if (reachableStop.duration > 0) { + state.finalReachableStops[reachableStop.stop.id] = { + stop: toLocation as IStop, + duration: reachableStop.duration, + }; + } + } + + return true; + } +} diff --git a/src/planner/public-transport/CSAProfile.ts b/src/planner/public-transport/CSAProfile.ts index 6032ab98..80017463 100644 --- a/src/planner/public-transport/CSAProfile.ts +++ b/src/planner/public-transport/CSAProfile.ts @@ -108,6 +108,7 @@ export default class CSAProfile implements IPublicTransportPlanner { upperBoundDate, lowerBoundDate, excludedModes: query.excludedTravelModes, + region: null, }); const mergedIterator = new MergeIterator( diff --git a/src/types.ts b/src/types.ts index 516285b8..ad4c502f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,7 +1,7 @@ import TravelMode from "./enums/TravelMode"; import IConnectionsFetcher from "./fetcher/connections/IConnectionsFetcher"; import IStopsFetcher from "./fetcher/stops/IStopsFetcher"; -import IRoutableTileFetcher from "./fetcher/tiles/IRoutableTileFetcher"; +import IHypermediaTreeFetcher from "./fetcher/tree/IHypermediaTreeFetcher"; const TYPES = { EventBus: Symbol("EventBus"), @@ -10,6 +10,9 @@ const TYPES = { LocationResolver: Symbol("LocationResolver"), HydraTemplateFetcher: Symbol("HydraTemplateFetcher"), + HypermediaTreeFetcher: Symbol("HypermediaTreeFetcher"), + HypermediaTreeProvider: Symbol("HypermediaTreeProvider"), + HypermediaTreeFetcherFactory: Symbol("HypermediaTreeFetcherFactory"), ConnectionsProvider: Symbol("ConnectionsProvider"), ConnectionsFetcher: Symbol("ConnectionsFetcher"), @@ -44,5 +47,6 @@ const TYPES = { export default TYPES; +export type HypermediaTreeFetcherFactory = (accessUrl: string) => IHypermediaTreeFetcher; export type StopsFetcherFactory = (accessUrl: string) => IStopsFetcher; export type ConnectionsFetcherFactory = (travelMode: TravelMode) => IConnectionsFetcher; diff --git a/src/uri/constants.ts b/src/uri/constants.ts index 4984889e..1494cdc5 100644 --- a/src/uri/constants.ts +++ b/src/uri/constants.ts @@ -2,8 +2,10 @@ export const XMLS = "http://www.w3.org/2001/XMLSchema"; export const HYDRA = "http://www.w3.org/ns/hydra/core"; export const OSM = "https://w3id.org/openstreetmap/terms"; export const GEO = "http://www.w3.org/2003/01/geo/wgs84_pos"; +export const GEOSPARQL = "http://www.opengis.net/ont/geosparql#"; export const RDF = "http://www.w3.org/1999/02/22-rdf-syntax-ns"; export const RDFS = "http://www.w3.org/2000/01/rdf-schema"; export const ROUTE = "https://w3id.org/routabletiles/terms#"; export const PLANNER = "https://planner.js.org/terms#"; export const PROFILE = "https://w3id.org/openplannerteam/profile#"; +export const TREE = "https://w3id.org/tree#"; diff --git a/src/util/iterators/MergeIterator.ts b/src/util/iterators/MergeIterator.ts index d8d56201..5623751d 100644 --- a/src/util/iterators/MergeIterator.ts +++ b/src/util/iterators/MergeIterator.ts @@ -26,6 +26,8 @@ export default class MergeIterator extends AsyncIterator { this.sourceIterators = sourceIterators; this.selector = selector; + this.setMaxListeners(1000); + this.values = Array(this.sourceIterators.length).fill(undefined); this.waitingForFill = Array(this.sourceIterators.length).fill(false); this.readable = true; From 966b79925b5afd3a0f8a78844d9c86959601eecc Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Thu, 9 Jan 2020 13:55:09 +0100 Subject: [PATCH 05/18] Optimize the stopsfinder birdseye --- src/planner/stops/ReachableStopsFinderBirdsEye.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/planner/stops/ReachableStopsFinderBirdsEye.ts b/src/planner/stops/ReachableStopsFinderBirdsEye.ts index da79b84c..2372224c 100644 --- a/src/planner/stops/ReachableStopsFinderBirdsEye.ts +++ b/src/planner/stops/ReachableStopsFinderBirdsEye.ts @@ -31,16 +31,19 @@ export default class ReachableStopsFinderBirdsEye implements IReachableStopsFind // Mode can be ignored since birds eye view distance is identical - const reachableStops: IReachableStop[] = [{stop: sourceOrTargetStop, duration: 0}]; + const reachableStops: IReachableStop[] = [{ stop: sourceOrTargetStop, duration: 0 }]; const allStops = await this.stopsProvider.getAllStops(); allStops.forEach((possibleTarget: IStop) => { - const distance = Geo.getDistanceBetweenStops(sourceOrTargetStop, possibleTarget); - const duration = Units.toDuration(distance, minimumSpeed); - - if (duration >= 0 && duration <= maximumDuration) { - reachableStops.push({stop: possibleTarget, duration}); + if (Math.abs(sourceOrTargetStop.latitude - possibleTarget.latitude) < 0.05 && + Math.abs(sourceOrTargetStop.longitude - possibleTarget.longitude) < 0.05) { + const distance = Geo.getDistanceBetweenStops(sourceOrTargetStop, possibleTarget); + const duration = Units.toDuration(distance, minimumSpeed); + + if (duration >= 0 && duration <= maximumDuration) { + reachableStops.push({ stop: possibleTarget, duration }); + } } }); From 2f6eff7e3257f6d577eafc8ac023ddd6e4a2fc0f Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Thu, 9 Jan 2020 14:08:24 +0100 Subject: [PATCH 06/18] Expose a profile CSA planner --- src/configs/flexible_profile_transit.ts | 126 ++++++++++++++++++ src/demo.ts | 6 +- src/index.ts | 3 + .../FlexibleProfileTransitPlanner.ts | 8 ++ 4 files changed, 140 insertions(+), 3 deletions(-) create mode 100644 src/configs/flexible_profile_transit.ts create mode 100644 src/planner/configurations/FlexibleProfileTransitPlanner.ts diff --git a/src/configs/flexible_profile_transit.ts b/src/configs/flexible_profile_transit.ts new file mode 100644 index 00000000..f56d6f1f --- /dev/null +++ b/src/configs/flexible_profile_transit.ts @@ -0,0 +1,126 @@ +import { Container, interfaces } from "inversify"; +import Catalog from "../Catalog"; +import Context from "../Context"; +import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; +import RoutingPhase from "../enums/RoutingPhase"; +import TravelMode from "../enums/TravelMode"; +import ConnectionsFetcherRaw from "../fetcher/connections/ConnectionsFetcherRaw"; +import ConnectionsProviderDefault from "../fetcher/connections/ConnectionsProviderDefault"; +import IConnectionsFetcher from "../fetcher/connections/IConnectionsFetcher"; +import IConnectionsProvider from "../fetcher/connections/IConnectionsProvider"; +import HydraTemplateFetcherDefault from "../fetcher/hydra/HydraTemplateFetcherDefault"; +import IHydraTemplateFetcher from "../fetcher/hydra/IHydraTemplateFetcher"; +import LDFetch from "../fetcher/LDFetch"; +import IProfileFetcher from "../fetcher/profiles/IProfileFetcher"; +import IProfileProvider from "../fetcher/profiles/IProfileProvider"; +import ProfileFetcherDefault from "../fetcher/profiles/ProfileFetcherDefault"; +import ProfileProviderDefault from "../fetcher/profiles/ProfileProviderDefault"; +import IStopsFetcher from "../fetcher/stops/IStopsFetcher"; +import IStopsProvider from "../fetcher/stops/IStopsProvider"; +import StopsFetcherLDFetch from "../fetcher/stops/ld-fetch/StopsFetcherLDFetch"; +import StopsFetcherRaw from "../fetcher/stops/StopsFetcherRaw"; +import StopsProviderDefault from "../fetcher/stops/StopsProviderDefault"; +import IRoutableTileFetcher from "../fetcher/tiles/IRoutableTileFetcher"; +import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; +import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; +import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; +import HypermediaTreeFetcherDefault from "../fetcher/tree/HypermediaTreeFetcherDefault"; +import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDeault"; +import IHypermediaTreeProvider from "../fetcher/tree/IHeadermediaTreeProvider"; +import IHypermediaTreeFetcher from "../fetcher/tree/IHypermediaTreeFetcher"; +import { LDLoader } from "../loader/ldloader"; +import { BidirDijkstra } from "../pathfinding/bidirdijkstra/BidirDijkstra"; +import DijkstraTree from "../pathfinding/dijkstra-tree/DijkstraTree"; +import { IShortestPathAlgorithm, IShortestPathTreeAlgorithm } from "../pathfinding/pathfinder"; +import PathfinderProvider from "../pathfinding/PathfinderProvider"; +import CSAProfile from "../planner/public-transport/CSAProfile"; +import IJourneyExtractor from "../planner/public-transport/IJourneyExtractor"; +import IPublicTransportPlanner from "../planner/public-transport/IPublicTransportPlanner"; +import JourneyExtractorProfile from "../planner/public-transport/JourneyExtractorProfile"; +import IRoadPlanner from "../planner/road/IRoadPlanner"; +import RoadPlannerPathfinding from "../planner/road/RoadPlannerPathfinding"; +import IReachableStopsFinder from "../planner/stops/IReachableStopsFinder"; +import ReachableStopsFinderBirdsEyeCached from "../planner/stops/ReachableStopsFinderBirdsEyeCached"; +import ReachableStopsFinderDelaunay from "../planner/stops/ReachableStopsFinderDelaunay"; +import QueryRunnerExponential from "../query-runner/exponential/QueryRunnerExponential"; +import ILocationResolver from "../query-runner/ILocationResolver"; +import IQueryRunner from "../query-runner/IQueryRunner"; +import LocationResolverConvenience from "../query-runner/LocationResolverConvenience"; +import TYPES from "../types"; + +const container = new Container(); +container.bind(TYPES.Context).to(Context).inSingletonScope(); +container.bind(TYPES.QueryRunner).to(QueryRunnerExponential); +container.bind(TYPES.LocationResolver).to(LocationResolverConvenience); + +// TODO, make this a fixed property of the planner itself +container.bind(TYPES.JourneyExtractor) + .to(JourneyExtractorProfile); + +container.bind(TYPES.PublicTransportPlanner) + .to(CSAProfile); +container.bind>(TYPES.PublicTransportPlannerFactory) + .toAutoFactory(TYPES.PublicTransportPlanner); + +container.bind(TYPES.RoadPlanner) + .to(RoadPlannerPathfinding); + +container.bind(TYPES.HydraTemplateFetcher).to(HydraTemplateFetcherDefault).inSingletonScope(); +container.bind(TYPES.HypermediaTreeFetcher).to(HypermediaTreeFetcherDefault).inSingletonScope(); +container.bind(TYPES.HypermediaTreeProvider) + .to(HypermediaTreeProviderDefault).inSingletonScope(); + +container.bind(TYPES.ShortestPathTreeAlgorithm).to(DijkstraTree).inSingletonScope(); +container.bind(TYPES.ShortestPathAlgorithm).to(BidirDijkstra).inSingletonScope(); +container.bind(TYPES.PathfinderProvider).to(PathfinderProvider).inSingletonScope(); +container.bind(TYPES.ProfileFetcher).to(ProfileFetcherDefault).inSingletonScope(); +container.bind(TYPES.ProfileProvider).to(ProfileProviderDefault).inSingletonScope(); + +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderDelaunay).whenTargetTagged("phase", ReachableStopsSearchPhase.Initial); +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderBirdsEyeCached).whenTargetTagged("phase", ReachableStopsSearchPhase.Transfer); +container.bind(TYPES.ReachableStopsFinder) + .to(ReachableStopsFinderDelaunay).whenTargetTagged("phase", ReachableStopsSearchPhase.Final); + +container.bind(TYPES.ConnectionsProvider).to(ConnectionsProviderDefault).inSingletonScope(); +container.bind(TYPES.ConnectionsFetcher).to(ConnectionsFetcherRaw); +container.bind>(TYPES.ConnectionsFetcherFactory) + .toFactory( + (context: interfaces.Context) => + (travelMode: TravelMode) => { + const fetcher = context.container.get(TYPES.ConnectionsFetcher); + + fetcher.setTravelMode(travelMode); + + return fetcher; + }, + ); + +container.bind(TYPES.StopsProvider).to(StopsProviderDefault).inSingletonScope(); +container.bind(TYPES.StopsFetcher).to(StopsFetcherRaw); +container.bind>(TYPES.StopsFetcherFactory) + .toFactory( + (context: interfaces.Context) => + (accessUrl: string) => { + const fetcher = context.container.get(TYPES.StopsFetcher); + fetcher.setAccessUrl(accessUrl); + return fetcher; + }, + ); + +container.bind(TYPES.RoutableTileFetcher).to(RoutableTileFetcherRaw).inSingletonScope(); +container.bind(TYPES.RoutableTileProvider) + .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Base); +container.bind(TYPES.RoutableTileProvider) + .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); + +// Bind empty catalog +container.bind(TYPES.Catalog).toConstantValue(new Catalog()); + +// Init LDFetch +container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); + +container.bind(TYPES.LDLoader).to(LDLoader); + +export default container; diff --git a/src/demo.ts b/src/demo.ts index 0fb07df6..90e262a6 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -1,4 +1,4 @@ -import { FlexibleTransitPlanner } from "."; +import { FlexibleProfileTransitPlanner } from "."; import EventBus from "./events/EventBus"; import EventType from "./events/EventType"; import IPath from "./interfaces/IPath"; @@ -6,7 +6,7 @@ import Units from "./util/Units"; export default async (logResults) => { - const planner = new FlexibleTransitPlanner(); + const planner = new FlexibleProfileTransitPlanner(); planner.addConnectionSource("https://graph.irail.be/sncb/connections"); planner.addStopSource("https://irail.be/stations/NMBS"); @@ -63,7 +63,7 @@ export default async (logResults) => { console.log(`${new Date()} Start query`); } - const amount = 1; + const amount = 2; let i = 0; planner diff --git a/src/index.ts b/src/index.ts index f62037a8..65e556db 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,6 +10,7 @@ import EventType from "./events/EventType"; import BasicTrainPlanner from "./planner/configurations/BasicTrainPlanner"; import DelijnNmbsPlanner from "./planner/configurations/DelijnNmbsPlanner"; import DissectPlanner from "./planner/configurations/DissectPlanner"; +import FlexibleProfileTransitPlanner from "./planner/configurations/FlexibleProfileTransitPlanner"; import FlexibleTransitPlanner from "./planner/configurations/FlexibleTransitPlanner"; import GeospatialFragmentedPlanner from "./planner/configurations/GeospatialFragmentedPlanner"; import TransitCarPlanner from "./planner/configurations/TransitCarPlanner"; @@ -25,6 +26,7 @@ export { default as DelijnNmbsPlanner } from "./planner/configurations/DelijnNmb export { default as DissectPlanner } from "./planner/configurations/DissectPlanner"; export { default as TransitCarPlanner } from "./planner/configurations/TransitCarPlanner"; export { default as FlexibleTransitPlanner } from "./planner/configurations/FlexibleTransitPlanner"; +export { default as FlexibleProfileTransitPlanner } from "./planner/configurations/FlexibleProfileTransitPlanner"; export { default as GeospatialFragmentedPlanner } from "./planner/configurations/GeospatialFragmentedPlanner"; export { default as TriangleDemoPlanner } from "./planner/configurations/TriangleDemoPlanner"; export { default as TravelMode } from "./enums/TravelMode"; @@ -46,5 +48,6 @@ export default { TriangleDemoPlanner, RoutableTileRegistry, FlexibleTransitPlanner, + FlexibleProfileTransitPlanner, GeospatialFragmentedPlanner, }; diff --git a/src/planner/configurations/FlexibleProfileTransitPlanner.ts b/src/planner/configurations/FlexibleProfileTransitPlanner.ts new file mode 100644 index 00000000..d0e0e8d2 --- /dev/null +++ b/src/planner/configurations/FlexibleProfileTransitPlanner.ts @@ -0,0 +1,8 @@ +import config from "../../configs/flexible_profile_transit"; +import Planner from "./Planner"; + +export default class FlexibleProfileTransitPlanner extends Planner { + constructor() { + super(config); + } +} From e11174368b518256801b4f0ecd2341900ceb9243 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Thu, 9 Jan 2020 16:27:27 +0100 Subject: [PATCH 07/18] Experiment with stable connection orderings --- .../connections/ConnectionSelectors.ts | 4 + .../connections/ConnectionsFetcherRaw.ts | 8 +- .../CSAEarliestArrivalDynamic.ts | 744 +++++++++--------- 3 files changed, 385 insertions(+), 371 deletions(-) diff --git a/src/fetcher/connections/ConnectionSelectors.ts b/src/fetcher/connections/ConnectionSelectors.ts index 313d6ef3..0b3251ec 100644 --- a/src/fetcher/connections/ConnectionSelectors.ts +++ b/src/fetcher/connections/ConnectionSelectors.ts @@ -14,6 +14,10 @@ export function forwardsConnectionSelector(connections: IConnection[]): number { if (connection.departureTime < earliest.departureTime) { earliestIndex = i; earliest = connection; + } else if (connection.departureTime === earliest.departureTime + && connection.arrivalTime < earliest.arrivalTime) { + earliestIndex = i; + earliest = connection; } } diff --git a/src/fetcher/connections/ConnectionsFetcherRaw.ts b/src/fetcher/connections/ConnectionsFetcherRaw.ts index 8c058229..d1d67470 100644 --- a/src/fetcher/connections/ConnectionsFetcherRaw.ts +++ b/src/fetcher/connections/ConnectionsFetcherRaw.ts @@ -103,7 +103,13 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { EventBus.getInstance().emit(EventType.LDFetchGet, url, duration); connections.sort((a, b) => { - return a.departureTime.getTime() - b.departureTime.getTime(); + if (a.departureTime.getTime() !== b.departureTime.getTime()) { + return a.departureTime.getTime() - b.departureTime.getTime(); + } else if (a.arrivalTime.getTime() !== b.arrivalTime.getTime()) { + return a.arrivalTime.getTime() - b.arrivalTime.getTime(); + } + + return a.id.localeCompare(b.id); }); return new LinkedConnectionsPage(pageId, connections, previousPageUrl, nextPageUrl); diff --git a/src/planner/public-transport/CSAEarliestArrivalDynamic.ts b/src/planner/public-transport/CSAEarliestArrivalDynamic.ts index 00e7511a..c5e25489 100644 --- a/src/planner/public-transport/CSAEarliestArrivalDynamic.ts +++ b/src/planner/public-transport/CSAEarliestArrivalDynamic.ts @@ -33,427 +33,431 @@ import IPublicTransportPlanner from "./IPublicTransportPlanner"; import JourneyExtractorEarliestArrival from "./JourneyExtractorEarliestArrival"; interface IFinalReachableStops { - [stop: string]: IReachableStop; + [stop: string]: IReachableStop; } interface IQueryState { - finalReachableStops: IFinalReachableStops; - profilesByStop: IProfileByStop; // S - enterConnectionByTrip: IEnterConnectionByTrip; // T - footpathsQueue: FootpathQueue; - connectionsIterator: AsyncIterator; - mergedQueue: AsyncIterator; - clusterStops: object; - lowerBoundDate: Date; + finalReachableStops: IFinalReachableStops; + profilesByStop: IProfileByStop; // S + enterConnectionByTrip: IEnterConnectionByTrip; // T + footpathsQueue: FootpathQueue; + connectionsIterator: AsyncIterator; + mergedQueue: AsyncIterator; + clusterStops: object; + lowerBoundDate: Date; } // Implementation is as close as possible to the original paper: https://arxiv.org/pdf/1703.05997.pdf @injectable() export default class CSAEarliestArrivalDynamic implements IPublicTransportPlanner { - protected readonly connectionsProvider: IConnectionsProvider; - protected readonly locationResolver: ILocationResolver; - protected readonly treeProvider: IHypermediaTreeProvider; - protected readonly transferReachableStopsFinder: IReachableStopsFinder; - protected readonly initialReachableStopsFinder: IReachableStopsFinder; - protected readonly finalReachableStopsFinder: IReachableStopsFinder; - protected readonly eventBus: EventEmitter; - - protected journeyExtractor: IJourneyExtractor; - protected reachedClusters: Set; - protected stopsProvider: IStopsProvider; - - constructor( - @inject(TYPES.ConnectionsProvider) - connectionsProvider: IConnectionsProvider, - @inject(TYPES.LocationResolver) - locationResolver: ILocationResolver, - @inject(TYPES.ReachableStopsFinder) - @tagged("phase", ReachableStopsSearchPhase.Transfer) - transferReachableStopsFinder: IReachableStopsFinder, - @inject(TYPES.ReachableStopsFinder) - @tagged("phase", ReachableStopsSearchPhase.Initial) - initialReachableStopsFinder: IReachableStopsFinder, - @inject(TYPES.ReachableStopsFinder) - @tagged("phase", ReachableStopsSearchPhase.Final) - finalReachableStopsFinder: IReachableStopsFinder, - @inject(TYPES.HypermediaTreeProvider) - treeProvider: IHypermediaTreeProvider, - @inject(TYPES.StopsProvider) - stopsProvider: IStopsProvider, - ) { - this.reachedClusters = new Set(); - this.treeProvider = treeProvider; - this.connectionsProvider = connectionsProvider; - this.locationResolver = locationResolver; - this.transferReachableStopsFinder = transferReachableStopsFinder; - this.initialReachableStopsFinder = initialReachableStopsFinder; - this.finalReachableStopsFinder = finalReachableStopsFinder; - this.eventBus = EventBus.getInstance(); - this.journeyExtractor = new JourneyExtractorEarliestArrival(locationResolver); - this.stopsProvider = stopsProvider; - } - - public async plan(query: IResolvedQuery): Promise> { - const { - minimumDepartureTime: lowerBoundDate, - maximumArrivalTime: upperBoundDate, - } = query; - - const trees = await this.treeProvider.getAllTrees(); - const clusterStops = await this.clusterStops(trees); - const startLocation = clusterStops[Geo.getId(query.from[0])]; - this.reachedClusters.add(startLocation.id); - - const footpathsQueue = new FootpathQueue(); - const connectionsIterator = await this.connectionsProvider.createIterator({ - upperBoundDate, - lowerBoundDate, - excludedModes: query.excludedTravelModes, - region: startLocation, - }); - - const mergedQueue = new MergeIterator( - [connectionsIterator, footpathsQueue], - forwardsConnectionSelector, - true, - ); - - const queryState: IQueryState = { - finalReachableStops: {}, - profilesByStop: {}, - enterConnectionByTrip: {}, - footpathsQueue, - connectionsIterator, - clusterStops, - mergedQueue, - lowerBoundDate, - }; - - const [hasInitialReachableStops, hasFinalReachableStops] = await Promise.all([ - this.initInitialReachableStops(queryState, query), - this.initFinalReachableStops(queryState, query), - ]); - - if (!hasInitialReachableStops || !hasFinalReachableStops) { - return Promise.resolve(new ArrayIterator([])); + protected readonly connectionsProvider: IConnectionsProvider; + protected readonly locationResolver: ILocationResolver; + protected readonly treeProvider: IHypermediaTreeProvider; + protected readonly transferReachableStopsFinder: IReachableStopsFinder; + protected readonly initialReachableStopsFinder: IReachableStopsFinder; + protected readonly finalReachableStopsFinder: IReachableStopsFinder; + protected readonly eventBus: EventEmitter; + + protected journeyExtractor: IJourneyExtractor; + protected reachedClusters: Set; + protected stopsProvider: IStopsProvider; + + constructor( + @inject(TYPES.ConnectionsProvider) + connectionsProvider: IConnectionsProvider, + @inject(TYPES.LocationResolver) + locationResolver: ILocationResolver, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Transfer) + transferReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Initial) + initialReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.ReachableStopsFinder) + @tagged("phase", ReachableStopsSearchPhase.Final) + finalReachableStopsFinder: IReachableStopsFinder, + @inject(TYPES.HypermediaTreeProvider) + treeProvider: IHypermediaTreeProvider, + @inject(TYPES.StopsProvider) + stopsProvider: IStopsProvider, + ) { + this.reachedClusters = new Set(); + this.treeProvider = treeProvider; + this.connectionsProvider = connectionsProvider; + this.locationResolver = locationResolver; + this.transferReachableStopsFinder = transferReachableStopsFinder; + this.initialReachableStopsFinder = initialReachableStopsFinder; + this.finalReachableStopsFinder = finalReachableStopsFinder; + this.eventBus = EventBus.getInstance(); + this.journeyExtractor = new JourneyExtractorEarliestArrival(locationResolver); + this.stopsProvider = stopsProvider; } - const self = this; - return new Promise((resolve, reject) => { - let isDone: boolean = false; - - const done = () => { - if (!isDone) { - mergedQueue.close(); + public async plan(query: IResolvedQuery): Promise> { + const { + minimumDepartureTime: lowerBoundDate, + maximumArrivalTime: upperBoundDate, + } = query; + + const trees = await this.treeProvider.getAllTrees(); + const clusterStops = await this.clusterStops(trees); + const startLocation = clusterStops[Geo.getId(query.from[0])]; + this.reachedClusters.add(startLocation.id); + + const footpathsQueue = new FootpathQueue(); + const connectionsIterator = await this.connectionsProvider.createIterator({ + upperBoundDate, + lowerBoundDate, + excludedModes: query.excludedTravelModes, + region: startLocation, + }); + + const mergedQueue = new MergeIterator( + [connectionsIterator, footpathsQueue], + forwardsConnectionSelector, + true, + ); + + const queryState: IQueryState = { + finalReachableStops: {}, + profilesByStop: {}, + enterConnectionByTrip: {}, + footpathsQueue, + connectionsIterator, + clusterStops, + mergedQueue, + lowerBoundDate, + }; - self.extractJourneys(queryState, query) - .then((resultIterator) => { - resolve(resultIterator); - }); + const [hasInitialReachableStops, hasFinalReachableStops] = await Promise.all([ + this.initInitialReachableStops(queryState, query), + this.initFinalReachableStops(queryState, query), + ]); - isDone = true; + if (!hasInitialReachableStops || !hasFinalReachableStops) { + return Promise.resolve(new ArrayIterator([])); } - }; - connectionsIterator.on("readable", () => - self.processConnections(queryState, query, done), - ); + const self = this; + return new Promise((resolve, reject) => { + let isDone: boolean = false; + + const done = () => { + if (!isDone) { + mergedQueue.close(); - connectionsIterator.on("end", () => done()); + self.extractJourneys(queryState, query) + .then((resultIterator) => { + resolve(resultIterator); + }); + + isDone = true; + } + }; - // iterator may have become readable before the listener was attached - self.processConnections(queryState, query, done); + connectionsIterator.on("readable", () => + self.processConnections(queryState, query, done), + ); - }) as Promise>; - } + connectionsIterator.on("end", () => done()); - protected async clusterStops(trees: HypermediaTree[]): Promise { - const stops = await this.stopsProvider.getAllStops(); - const result = {}; - for (const stop of stops) { - const cluster = this.placeLocation(stop, trees); - result[Geo.getId(stop)] = cluster; + // iterator may have become readable before the listener was attached + self.processConnections(queryState, query, done); + + }) as Promise>; } - return result; - } - - protected placeLocation(location: ILocation, trees: HypermediaTree[]): GeometryValue { - for (const tree of trees) { - for (const relation of tree.relations) { - if (relation.geoValue.contains(location)) { - return relation.geoValue; + + protected async clusterStops(trees: HypermediaTree[]): Promise { + const stops = await this.stopsProvider.getAllStops(); + const result = {}; + for (const stop of stops) { + const cluster = this.placeLocation(stop, trees); + result[Geo.getId(stop)] = cluster; } - } + return result; } - } - - protected async updateProfile(state: IQueryState, query: IResolvedQuery, connection: IConnection) { - /* - Call this ONLY if the given connection is known to improve the arrival stop's profile - */ - - const tripId = connection.tripId; - const departureTime = connection.departureTime.getTime(); - const arrivalTime = connection.arrivalTime.getTime(); - - // update profile of arrival stop - const arrivalProfile: ITransferProfile = { - departureTime, - arrivalTime, - exitConnection: connection, - enterConnection: state.enterConnectionByTrip[tripId], - }; - state.profilesByStop[connection.arrivalStop] = arrivalProfile; - - const cluster = state.clusterStops[connection.arrivalStop]; - if (cluster && !this.reachedClusters.has(cluster.id)) { - const { - maximumArrivalTime: upperBoundDate, - } = query; - - // console.log("REACHED", cluster.id); - - this.reachedClusters.add(cluster.id); - - const newConnectionIterator = await this.connectionsProvider.appendIterator({ - upperBoundDate, - lowerBoundDate: connection.departureTime, - excludedModes: query.excludedTravelModes, - region: cluster, - }, state.connectionsIterator); - - state.connectionsIterator = newConnectionIterator; - state.mergedQueue = new MergeIterator( - [newConnectionIterator, state.footpathsQueue], - forwardsConnectionSelector, - true, - ); - } - } - - private async extractJourneys(state: IQueryState, query: IResolvedQuery): Promise> { - return this.journeyExtractor.extractJourneys(state.profilesByStop, query); - } - - private async processConnections(state: IQueryState, query: IResolvedQuery, resolve: () => void) { - const { from, to, minimumDepartureTime } = query; - const departureStopId: string = from[0].id; - const arrivalStopId: string = to[0].id; - - let connection: IConnection = state.mergedQueue.read(); - - while (connection && !state.connectionsIterator.closed) { - if (connection.departureTime < state.lowerBoundDate && !state.connectionsIterator.closed) { - // starting criterion - // skip connections before the minimum departure time - connection = state.mergedQueue.read(); - continue; - } - - state.lowerBoundDate = connection.departureTime; - // console.log(connection.id, connection.departureTime) - - if (this.getProfile(state, arrivalStopId).arrivalTime <= connection.departureTime.getTime()) { - // stopping criterion - // we cannot improve the tentative arrival time anymore - return resolve(); - } - - const tripId = connection.tripId; - const departureTime = connection.departureTime.getTime(); - - const canRemainSeated = state.enterConnectionByTrip[tripId]; - const canTakeTransfer = ( - ( - connection.departureStop === departureStopId || - this.getProfile(state, connection.departureStop).arrivalTime <= departureTime - ) && - connection.pickupType !== PickupType.NotAvailable - ); - - if (canRemainSeated || canTakeTransfer) { - // enterConnectionByTrip should point to the first reachable connection - if (!state.enterConnectionByTrip[tripId]) { - state.enterConnectionByTrip[tripId] = connection; + protected placeLocation(location: ILocation, trees: HypermediaTree[]): GeometryValue { + for (const tree of trees) { + for (const relation of tree.relations) { + if (relation.geoValue.contains(location)) { + return relation.geoValue; + } + } } - // limited walking optimization - const canImprove = connection.arrivalTime.getTime() < - this.getProfile(state, connection.arrivalStop).arrivalTime; - const canLeave = connection.dropOffType !== DropOffType.NotAvailable; + } - if (canLeave && canImprove) { - this.updateProfile(state, query, connection); - await this.scheduleExtraConnections(state, query, connection); + protected async updateProfile(state: IQueryState, query: IResolvedQuery, connection: IConnection) { + /* + Call this ONLY if the given connection is known to improve the arrival stop's profile + */ + if (connection.travelMode === TravelMode.Train) { + console.log(connection.departureTime, connection.id); } - } - if (!state.connectionsIterator.closed) { - connection = state.mergedQueue.read(); - continue; - } + const tripId = connection.tripId; + const departureTime = connection.departureTime.getTime(); + const arrivalTime = connection.arrivalTime.getTime(); - connection = undefined; + // update profile of arrival stop + const arrivalProfile: ITransferProfile = { + departureTime, + arrivalTime, + exitConnection: connection, + enterConnection: state.enterConnectionByTrip[tripId], + }; + state.profilesByStop[connection.arrivalStop] = arrivalProfile; + + const cluster = state.clusterStops[connection.arrivalStop]; + if (cluster && !this.reachedClusters.has(cluster.id)) { + const { + maximumArrivalTime: upperBoundDate, + } = query; + + // console.log("REACHED", cluster.id); + + this.reachedClusters.add(cluster.id); + + const newConnectionIterator = await this.connectionsProvider.appendIterator({ + upperBoundDate, + lowerBoundDate: connection.departureTime, + excludedModes: query.excludedTravelModes, + region: cluster, + }, state.connectionsIterator); + + state.connectionsIterator = newConnectionIterator; + state.mergedQueue = new MergeIterator( + [newConnectionIterator, state.footpathsQueue], + forwardsConnectionSelector, + true, + ); + } } - } - - private getProfile(state: IQueryState, stopId: string): ITransferProfile { - if (!state.profilesByStop[stopId]) { - state.profilesByStop[stopId] = { - departureTime: Infinity, - arrivalTime: Infinity, - }; + + private async extractJourneys(state: IQueryState, query: IResolvedQuery): Promise> { + return this.journeyExtractor.extractJourneys(state.profilesByStop, query); } - return state.profilesByStop[stopId]; - } - - private async scheduleExtraConnections(state: IQueryState, query: IResolvedQuery, sourceConnection: IConnection) { - try { - const arrivalStop: ILocation = await this.locationResolver.resolve(sourceConnection.arrivalStop); - const reachableStops: IReachableStop[] = await this.transferReachableStopsFinder.findReachableStops( - arrivalStop as IStop, - ReachableStopsFinderMode.Source, - query.maximumTransferDuration, - query.minimumWalkingSpeed, - query.profileID, - ); - - if (state.finalReachableStops[arrivalStop.id]) { - reachableStops.push(state.finalReachableStops[arrivalStop.id]); - } - - for (const reachableStop of reachableStops) { - const { stop: stop, duration: duration } = reachableStop; - - if (duration && stop.id) { - const transferTentativeArrival = this.getProfile(state, stop.id).arrivalTime; - const newArrivalTime = new Date(sourceConnection.arrivalTime.getTime() + duration); - - if (transferTentativeArrival > newArrivalTime.getTime() && newArrivalTime <= query.maximumArrivalTime) { - - const tripId = `TRANSFER_TO:${sourceConnection.arrivalStop}@${sourceConnection.arrivalTime.getTime()}`; - - // create a connection that resembles a footpath - // TODO, ditch the IReachbleStop and IConnection interfaces and make these proper objects - const transferConnection: IConnection = { - id: `${tripId}-${stop.id}`, - tripId, - travelMode: TravelMode.Walking, // TODO, this should be part of the reachable stop object - departureTime: sourceConnection.arrivalTime, - departureStop: sourceConnection.arrivalStop, - arrivalTime: new Date(sourceConnection.arrivalTime.getTime() + duration), - arrivalStop: stop.id, - dropOffType: DropOffType.Regular, - pickupType: PickupType.Regular, - headsign: stop.id, - }; - state.footpathsQueue.write(transferConnection); - } + private async processConnections(state: IQueryState, query: IResolvedQuery, resolve: () => void) { + const { from, to, minimumDepartureTime } = query; + const departureStopId: string = from[0].id; + const arrivalStopId: string = to[0].id; + + let connection: IConnection = state.mergedQueue.read(); + + while (connection && !state.connectionsIterator.closed) { + if (connection.departureTime < state.lowerBoundDate && !state.connectionsIterator.closed) { + // starting criterion + // skip connections before the minimum departure time + connection = state.mergedQueue.read(); + continue; + } + + state.lowerBoundDate = connection.departureTime; + // console.log(connection.id, connection.departureTime) + + if (this.getProfile(state, arrivalStopId).arrivalTime < connection.departureTime.getTime()) { + // stopping criterion + // we cannot improve the tentative arrival time anymore + return resolve(); + } + + const tripId = connection.tripId; + const departureTime = connection.departureTime.getTime(); + + const canRemainSeated = state.enterConnectionByTrip[tripId]; + const canTakeTransfer = ( + ( + connection.departureStop === departureStopId || + this.getProfile(state, connection.departureStop).arrivalTime <= departureTime + ) && + connection.pickupType !== PickupType.NotAvailable + ); + + if (canRemainSeated || canTakeTransfer) { + // enterConnectionByTrip should point to the first reachable connection + if (!state.enterConnectionByTrip[tripId]) { + state.enterConnectionByTrip[tripId] = connection; + } + + // limited walking optimization + const canImprove = connection.arrivalTime.getTime() < + this.getProfile(state, connection.arrivalStop).arrivalTime; + const canLeave = connection.dropOffType !== DropOffType.NotAvailable; + + if (canLeave && canImprove) { + this.updateProfile(state, query, connection); + await this.scheduleExtraConnections(state, query, connection); + } + } + + if (!state.connectionsIterator.closed) { + connection = state.mergedQueue.read(); + continue; + } + + connection = undefined; } - } - } catch (e) { - if (this.eventBus) { - this.eventBus.emit(EventType.Warning, (e)); - } } - } - private async initInitialReachableStops(state: IQueryState, query: IResolvedQuery): Promise { - const fromLocation: ILocation = query.from[0]; + private getProfile(state: IQueryState, stopId: string): ITransferProfile { + if (!state.profilesByStop[stopId]) { + state.profilesByStop[stopId] = { + departureTime: Infinity, + arrivalTime: Infinity, + }; + } + return state.profilesByStop[stopId]; + } - // Making sure the departure location has an id - const geoId = Geo.getId(fromLocation); - if (!fromLocation.id) { - query.from[0].id = geoId; - query.from[0].name = "Departure location"; + private async scheduleExtraConnections(state: IQueryState, query: IResolvedQuery, sourceConnection: IConnection) { + try { + const arrivalStop: ILocation = await this.locationResolver.resolve(sourceConnection.arrivalStop); + const reachableStops: IReachableStop[] = await this.transferReachableStopsFinder.findReachableStops( + arrivalStop as IStop, + ReachableStopsFinderMode.Source, + query.maximumTransferDuration, + query.minimumWalkingSpeed, + query.profileID, + ); + + if (state.finalReachableStops[arrivalStop.id]) { + reachableStops.push(state.finalReachableStops[arrivalStop.id]); + } + + for (const reachableStop of reachableStops) { + const { stop: stop, duration: duration } = reachableStop; + + if (duration && stop.id) { + const transferTentativeArrival = this.getProfile(state, stop.id).arrivalTime; + const newArrivalTime = new Date(sourceConnection.arrivalTime.getTime() + duration); + + if (transferTentativeArrival > newArrivalTime.getTime() + && newArrivalTime <= query.maximumArrivalTime) { + + const tripId = `TRANSFER_TO:${sourceConnection.arrivalStop}@${sourceConnection.arrivalTime.getTime()}`; + + // create a connection that resembles a footpath + // TODO, ditch the IReachbleStop and IConnection interfaces and make these proper objects + const transferConnection: IConnection = { + id: `${tripId}-${stop.id}`, + tripId, + travelMode: TravelMode.Walking, // TODO, this should be part of the reachable stop object + departureTime: sourceConnection.arrivalTime, + departureStop: sourceConnection.arrivalStop, + arrivalTime: new Date(sourceConnection.arrivalTime.getTime() + duration), + arrivalStop: stop.id, + dropOffType: DropOffType.Regular, + pickupType: PickupType.Regular, + headsign: stop.id, + }; + + state.footpathsQueue.write(transferConnection); + } + } + } + } catch (e) { + if (this.eventBus) { + this.eventBus.emit(EventType.Warning, (e)); + } + } } - const reachableStops = await this.initialReachableStopsFinder.findReachableStops( - fromLocation, - ReachableStopsFinderMode.Source, - query.maximumWalkingDuration, - query.minimumWalkingSpeed, - query.profileID, - ); + private async initInitialReachableStops(state: IQueryState, query: IResolvedQuery): Promise { + const fromLocation: ILocation = query.from[0]; - // Abort when we can't reach a single stop. - if (reachableStops.length === 0) { - this.eventBus.emit(EventType.AbortQuery, "No reachable stops at departure location"); + // Making sure the departure location has an id + const geoId = Geo.getId(fromLocation); + if (!fromLocation.id) { + query.from[0].id = geoId; + query.from[0].name = "Departure location"; + } - return false; - } + const reachableStops = await this.initialReachableStopsFinder.findReachableStops( + fromLocation, + ReachableStopsFinderMode.Source, + query.maximumWalkingDuration, + query.minimumWalkingSpeed, + query.profileID, + ); - if (this.eventBus) { - this.eventBus.emit(EventType.InitialReachableStops, reachableStops); - } + // Abort when we can't reach a single stop. + if (reachableStops.length === 0) { + this.eventBus.emit(EventType.AbortQuery, "No reachable stops at departure location"); - for (const reachableStop of reachableStops) { - const { stop: stop, duration: duration } = reachableStop; - - if (duration) { - // create a connection that resembles a footpath - // TODO, ditch the IReachbleStop and IConnection interfaces and make these proper objects - const transferConnection: IConnection = { - id: `MOVE_TO:${stop.id}`, - tripId: `MOVE_TO:${stop.id}`, - travelMode: TravelMode.Walking, // TODO, this should be part of the reachable stop object - departureTime: query.minimumDepartureTime, - departureStop: fromLocation.id, - arrivalTime: new Date(query.minimumDepartureTime.getTime() + duration), - arrivalStop: stop.id, - dropOffType: DropOffType.Regular, - pickupType: PickupType.Regular, - headsign: stop.id, - }; + return false; + } - state.footpathsQueue.write(transferConnection); - } + if (this.eventBus) { + this.eventBus.emit(EventType.InitialReachableStops, reachableStops); + } + + for (const reachableStop of reachableStops) { + const { stop: stop, duration: duration } = reachableStop; + + if (duration) { + // create a connection that resembles a footpath + // TODO, ditch the IReachbleStop and IConnection interfaces and make these proper objects + const transferConnection: IConnection = { + id: `MOVE_TO:${stop.id}`, + tripId: `MOVE_TO:${stop.id}`, + travelMode: TravelMode.Walking, // TODO, this should be part of the reachable stop object + departureTime: query.minimumDepartureTime, + departureStop: fromLocation.id, + arrivalTime: new Date(query.minimumDepartureTime.getTime() + duration), + arrivalStop: stop.id, + dropOffType: DropOffType.Regular, + pickupType: PickupType.Regular, + headsign: stop.id, + }; + + state.footpathsQueue.write(transferConnection); + } + } + + return true; } - return true; - } + private async initFinalReachableStops(state: IQueryState, query: IResolvedQuery): Promise { + const toLocation: ILocation = query.to[0]; - private async initFinalReachableStops(state: IQueryState, query: IResolvedQuery): Promise { - const toLocation: ILocation = query.to[0]; + // Making sure the departure location has an id + const geoId = Geo.getId(toLocation); + if (!toLocation.id) { + query.to[0].id = geoId; + query.to[0].name = "Arrival location"; + } - // Making sure the departure location has an id - const geoId = Geo.getId(toLocation); - if (!toLocation.id) { - query.to[0].id = geoId; - query.to[0].name = "Arrival location"; - } + const reachableStops = await this.finalReachableStopsFinder.findReachableStops( + toLocation, + ReachableStopsFinderMode.Target, + query.maximumWalkingDuration, + query.minimumWalkingSpeed, + query.profileID, + ); - const reachableStops = await this.finalReachableStopsFinder.findReachableStops( - toLocation, - ReachableStopsFinderMode.Target, - query.maximumWalkingDuration, - query.minimumWalkingSpeed, - query.profileID, - ); + // Abort when we can't reach a single stop. + if (reachableStops.length === 0) { + this.eventBus.emit(EventType.AbortQuery, "No reachable stops at arrival location"); - // Abort when we can't reach a single stop. - if (reachableStops.length === 0) { - this.eventBus.emit(EventType.AbortQuery, "No reachable stops at arrival location"); + return false; + } - return false; - } + if (this.eventBus) { + this.eventBus.emit(EventType.FinalReachableStops, reachableStops); + } - if (this.eventBus) { - this.eventBus.emit(EventType.FinalReachableStops, reachableStops); - } + for (const reachableStop of reachableStops) { + if (reachableStop.duration > 0) { + state.finalReachableStops[reachableStop.stop.id] = { + stop: toLocation as IStop, + duration: reachableStop.duration, + }; + } + } - for (const reachableStop of reachableStops) { - if (reachableStop.duration > 0) { - state.finalReachableStops[reachableStop.stop.id] = { - stop: toLocation as IStop, - duration: reachableStop.duration, - }; - } + return true; } - - return true; - } } From 2fd2b10bdcd749e54bb1e8aade2e9aa090a3f8ed Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Thu, 9 Jan 2020 17:47:17 +0100 Subject: [PATCH 08/18] Clean up event types --- src/analytics/isochrones/demo.html | 2 +- src/analytics/isochrones/main.ts | 4 ++-- src/analytics/traffic/main.ts | 4 ++-- src/demo.ts | 4 ++-- src/events/EventType.ts | 8 ++------ src/fetcher/LDFetch.ts | 2 +- src/fetcher/connections/ConnectionsFetcherRaw.ts | 15 +++++++++++---- src/fetcher/stops/StopsFetcherRaw.ts | 12 ++++++++++-- src/fetcher/tiles/RoutableTileFetcherRaw.ts | 12 ++++++++++-- .../public-transport/CSAEarliestArrivalDynamic.ts | 3 --- .../public-transport/CSAEarliestArrivalVerbose.ts | 2 +- src/planner/road/RoadPlannerPathfinding.ts | 2 +- .../road/RoadPlannerPathfindingExperimental.ts | 2 +- 13 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/analytics/isochrones/demo.html b/src/analytics/isochrones/demo.html index 8448453f..d409b5f6 100644 --- a/src/analytics/isochrones/demo.html +++ b/src/analytics/isochrones/demo.html @@ -150,7 +150,7 @@ }) */ - Planner.EventBus.on(Planner.EventType.PointReached, (point) => { + Planner.EventBus.on(Planner.EventType.ReachableLocation, (point) => { const wat = [point.latitude, point.longitude]; intermediate = L.circleMarker(wat, { color: 'red', diff --git a/src/analytics/isochrones/main.ts b/src/analytics/isochrones/main.ts index 778290c0..b1139480 100644 --- a/src/analytics/isochrones/main.ts +++ b/src/analytics/isochrones/main.ts @@ -121,7 +121,7 @@ export default class IsochroneGenerator { private async fetchTile(coordinate: RoutableTileCoordinate) { const tileId = this.tileProvider.getIdForTileCoords(coordinate); if (!this.reachedTiles.has(tileId)) { - this.eventBus.emit(EventType.FetchTile, coordinate); + this.eventBus.emit(EventType.ReachableTile, coordinate); const profile = await this.activeProfile; const pathfinder = this.pathfinderProvider.getShortestPathTreeAlgorithm(profile); @@ -140,7 +140,7 @@ export default class IsochroneGenerator { pathfinder.setBreakPoint(nodeId, async (on: string) => { const innerNode = self.registry.getNode(on); if (innerNode) { - self.eventBus.emit(EventType.PointReached, innerNode); + self.eventBus.emit(EventType.ReachableLocation, innerNode); } }); } diff --git a/src/analytics/traffic/main.ts b/src/analytics/traffic/main.ts index 22224780..83604283 100644 --- a/src/analytics/traffic/main.ts +++ b/src/analytics/traffic/main.ts @@ -163,7 +163,7 @@ export default class TrafficEstimator { tileId = this.transitTileProvider.getIdForTileCoords(coordinate); } if (!this.reachedTiles.has(tileId)) { - this.eventBus.emit(EventType.FetchTile, coordinate); + this.eventBus.emit(EventType.ReachableTile, coordinate); const profile = await this.activeProfile; const pathfinder = this.pathfinderProvider.getShortestPathTreeAlgorithm(profile); @@ -187,7 +187,7 @@ export default class TrafficEstimator { pathfinder.setBreakPoint(nodeId, async (on: string) => { const innerNode = self.registry.getNode(on); if (innerNode) { - self.eventBus.emit(EventType.PointReached, innerNode); + self.eventBus.emit(EventType.ReachableLocation, innerNode); } }); } diff --git a/src/demo.ts b/src/demo.ts index 90e262a6..89769985 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -41,9 +41,9 @@ export default async (logResults) => { console.log("Total scanned connections", scannedConnections); console.log("[Subquery]", minimumDepartureTime, maximumArrivalTime, maximumArrivalTime - minimumDepartureTime); }) - .on(EventType.LDFetchGet, (url, duration) => { + .on(EventType.ResourceFetch, (source, url, duration, size) => { scannedPages++; - console.log(`[GET] ${url} (${duration}ms)`); + console.log(`[GET] ${url} (${duration}ms ${size} bytes)`); // if (logFetch) { // console.log(`[GET] ${url} (${duration}ms)`); diff --git a/src/events/EventType.ts b/src/events/EventType.ts index 03662115..73c92af3 100644 --- a/src/events/EventType.ts +++ b/src/events/EventType.ts @@ -4,25 +4,21 @@ enum EventType { AbortQuery = "abort-query", InvalidQuery = "invalid-query", - LDFetchGet = "ldfetch-get", - Warning = "warning", ConnectionPrefetch = "connection-prefetch", ConnectionIteratorView = "connection-iterator-view", - FetchTile = "fetch-tile", - PointReached = "point-reached", - ConnectionScan = "connection-scan", FinalReachableStops = "final-reachable-stops", InitialReachableStops = "initial-reachable-stops", AddedNewTransferProfile = "added-new-transfer-profile", + ReachableLocation = "ReachableLocation", ReachableStop = "ReachableStop", ReachableTile = "ReachableTile", - Downloaded = "Downloaded", + ResourceFetch = "ResourceFetch", } export default EventType; diff --git a/src/fetcher/LDFetch.ts b/src/fetcher/LDFetch.ts index 4cdd6dbf..ee8f08bb 100644 --- a/src/fetcher/LDFetch.ts +++ b/src/fetcher/LDFetch.ts @@ -40,7 +40,7 @@ export default class LDFetch implements LDFetchBase { this.ldFetchBase.on("response", (url) => { const duration = (new Date()).getTime() - this.httpStartTimes[url].getTime(); - this.eventBus.emit(EventType.LDFetchGet, url, duration); + this.eventBus.emit(EventType.ResourceFetch, "?", url, duration, "?"); }); } } diff --git a/src/fetcher/connections/ConnectionsFetcherRaw.ts b/src/fetcher/connections/ConnectionsFetcherRaw.ts index d1d67470..95fc860b 100644 --- a/src/fetcher/connections/ConnectionsFetcherRaw.ts +++ b/src/fetcher/connections/ConnectionsFetcherRaw.ts @@ -7,6 +7,7 @@ import PickupType from "../../enums/PickupType"; import TravelMode from "../../enums/TravelMode"; import EventBus from "../../events/EventBus"; import EventType from "../../events/EventType"; +import TYPES from "../../types"; import JSONLDContext from "../../uri/JSONLDContext"; import IConnectionsFetcher from "./IConnectionsFetcher"; @@ -37,7 +38,8 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { const response = await fetch(url); const size = parseInt(response.headers.get("content-length"), 10); - EventBus.getInstance().emit(EventType.Downloaded, size); + const duration = (new Date()).getTime() - beginTime.getTime(); + const responseText = await response.text(); if (response.status !== 200) { EventBus.getInstance().emit(EventType.Warning, `${url} responded with status code ${response.status}`); @@ -99,9 +101,6 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { const nextPageUrl = blob["hydra:next"]; const previousPageUrl = blob["hydra:previous"]; - const duration = (new Date()).getTime() - beginTime.getTime(); - EventBus.getInstance().emit(EventType.LDFetchGet, url, duration); - connections.sort((a, b) => { if (a.departureTime.getTime() !== b.departureTime.getTime()) { return a.departureTime.getTime() - b.departureTime.getTime(); @@ -112,6 +111,14 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { return a.id.localeCompare(b.id); }); + EventBus.getInstance().emit( + EventType.ResourceFetch, + TYPES.ConnectionsFetcher, // origin + url, // resource uri + duration, // time it took to download and parse + size, // transferred data + ); + return new LinkedConnectionsPage(pageId, connections, previousPageUrl, nextPageUrl); } else { return new LinkedConnectionsPage(url, [], undefined, undefined); diff --git a/src/fetcher/stops/StopsFetcherRaw.ts b/src/fetcher/stops/StopsFetcherRaw.ts index 8822279c..5c87df6f 100644 --- a/src/fetcher/stops/StopsFetcherRaw.ts +++ b/src/fetcher/stops/StopsFetcherRaw.ts @@ -81,6 +81,9 @@ export default class StopsFetcherRaw implements IStopsFetcher { const response = await fetch(url); const responseText = await response.text(); + const size = parseInt(response.headers.get("content-length"), 10); + const duration = (new Date()).getTime() - beginTime.getTime(); + const stops: IStopMap = {}; if (response.status !== 200) { @@ -106,8 +109,13 @@ export default class StopsFetcherRaw implements IStopsFetcher { } } - const duration = (new Date()).getTime() - beginTime.getTime(); - EventBus.getInstance().emit(EventType.LDFetchGet, url, duration); + EventBus.getInstance().emit( + EventType.ResourceFetch, + TYPES.StopsFetcher, // origin + url, // resource uri + duration, // time it took to download and parse + size, // transferred data + ); return stops; } diff --git a/src/fetcher/tiles/RoutableTileFetcherRaw.ts b/src/fetcher/tiles/RoutableTileFetcherRaw.ts index b4c9fb01..e64a6b57 100644 --- a/src/fetcher/tiles/RoutableTileFetcherRaw.ts +++ b/src/fetcher/tiles/RoutableTileFetcherRaw.ts @@ -58,6 +58,9 @@ export default class RoutableTileFetcherRaw implements IRoutableTileFetcher { const nodes: IRoutableTileNodeIndex = {}; const ways: IRoutableTileWayIndex = {}; + const size = parseInt(response.headers.get("content-length"), 10); + const duration = (new Date()).getTime() - beginTime.getTime(); + for (const entity of blob["@graph"]) { if (entity["@type"] === "osm:Node") { const node = this.createNode(entity); @@ -68,8 +71,13 @@ export default class RoutableTileFetcherRaw implements IRoutableTileFetcher { } } - const duration = (new Date()).getTime() - beginTime.getTime(); - EventBus.getInstance().emit(EventType.LDFetchGet, url, duration); + EventBus.getInstance().emit( + EventType.ResourceFetch, + TYPES.StopsFetcher, // origin + url, // resource uri + duration, // time it took to download and parse + size, // transferred data + ); return this.processTileData(url, nodes, ways); } else { diff --git a/src/planner/public-transport/CSAEarliestArrivalDynamic.ts b/src/planner/public-transport/CSAEarliestArrivalDynamic.ts index c5e25489..de8eaa0d 100644 --- a/src/planner/public-transport/CSAEarliestArrivalDynamic.ts +++ b/src/planner/public-transport/CSAEarliestArrivalDynamic.ts @@ -193,9 +193,6 @@ export default class CSAEarliestArrivalDynamic implements IPublicTransportPlanne /* Call this ONLY if the given connection is known to improve the arrival stop's profile */ - if (connection.travelMode === TravelMode.Train) { - console.log(connection.departureTime, connection.id); - } const tripId = connection.tripId; const departureTime = connection.departureTime.getTime(); diff --git a/src/planner/public-transport/CSAEarliestArrivalVerbose.ts b/src/planner/public-transport/CSAEarliestArrivalVerbose.ts index f8ec4186..f5b0ccdc 100644 --- a/src/planner/public-transport/CSAEarliestArrivalVerbose.ts +++ b/src/planner/public-transport/CSAEarliestArrivalVerbose.ts @@ -33,6 +33,6 @@ export default class CSAEarliestArrivalVerbose extends CSAEarliestArrival { protected updateProfile(state, query: IResolvedQuery, connection: IConnection) { super.updateProfile(state, query, connection); - EventBus.getInstance().emit(EventType.PointReached, this.locationResolver.resolve(connection.arrivalStop)); + EventBus.getInstance().emit(EventType.ReachableLocation, this.locationResolver.resolve(connection.arrivalStop)); } } diff --git a/src/planner/road/RoadPlannerPathfinding.ts b/src/planner/road/RoadPlannerPathfinding.ts index f57e4f01..8910a400 100644 --- a/src/planner/road/RoadPlannerPathfinding.ts +++ b/src/planner/road/RoadPlannerPathfinding.ts @@ -125,7 +125,7 @@ export default class RoadPlannerPathfinding implements IRoadPlanner { private async fetchTile(coordinate: RoutableTileCoordinate) { const tileId = this.tileProvider.getIdForTileCoords(coordinate); if (!this.reachedTiles.has(tileId)) { - this.eventBus.emit(EventType.FetchTile, coordinate); + this.eventBus.emit(EventType.ReachableTile, coordinate); const tile = await this.tileProvider.getByTileCoords(coordinate); this.reachedTiles.add(tileId); const boundaryNodes: Set = new Set(); diff --git a/src/planner/road/RoadPlannerPathfindingExperimental.ts b/src/planner/road/RoadPlannerPathfindingExperimental.ts index 7146886d..22cfafe6 100644 --- a/src/planner/road/RoadPlannerPathfindingExperimental.ts +++ b/src/planner/road/RoadPlannerPathfindingExperimental.ts @@ -167,7 +167,7 @@ export default class RoadPlannerPathfindingExperimental implements IRoadPlanner const transitTileId = this.transitTileProvider.getIdForTileCoords(coordinate); if (!this.reachedTiles.has(transitTileId) && !this.reachedTiles.has(baseTileId)) { - this.eventBus.emit(EventType.FetchTile, coordinate); + this.eventBus.emit(EventType.ReachableTile, coordinate); let tile: RoutableTile; if (local) { tile = await this.baseTileProvider.getByTileCoords(coordinate); From 48fe2887df8daa8c8d4ccc8ec6bcee363b670737 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Mon, 13 Jan 2020 16:51:56 +0100 Subject: [PATCH 09/18] Second iteration of cleaner events --- src/configs/triangle_demo.ts | 4 +- src/events/EventType.ts | 7 ++-- .../connections/ConnectionsProviderDefault.ts | 10 +++-- .../connections/ConnectionsProviderSingle.ts | 10 +++-- .../connections/IConnectionsProvider.ts | 1 + .../tests/ConnectionsProviderNMBSTest.ts | 4 ++ src/fetcher/stops/IStopsProvider.ts | 4 +- src/fetcher/stops/StopsFetcherRaw.ts | 7 +++- src/fetcher/stops/StopsProviderDefault.ts | 17 ++++++--- .../stops/ld-fetch/StopsFetcherLDFetch.ts | 7 +++- src/planner/configurations/Planner.ts | 11 +++++- .../public-transport/CSAEarliestArrival.ts | 2 + .../CSAEarliestArrivalVerbose.ts | 38 ------------------- .../ReachableStopsFinderFootpathsVerbose.ts | 2 +- 14 files changed, 65 insertions(+), 59 deletions(-) delete mode 100644 src/planner/public-transport/CSAEarliestArrivalVerbose.ts diff --git a/src/configs/triangle_demo.ts b/src/configs/triangle_demo.ts index 35f13206..7a1f0458 100644 --- a/src/configs/triangle_demo.ts +++ b/src/configs/triangle_demo.ts @@ -34,7 +34,7 @@ import DijkstraTree from "../pathfinding/dijkstra-tree/DijkstraTree"; import MixedDijkstra from "../pathfinding/mixed-dijkstra/MixedDijkstra"; import { IShortestPathAlgorithm, IShortestPathTreeAlgorithm } from "../pathfinding/pathfinder"; import PathfinderProvider from "../pathfinding/PathfinderProvider"; -import CSAEarliestArrivalVerbose from "../planner/public-transport/CSAEarliestArrivalVerbose"; +import CSAEarliestArrival from "../planner/public-transport/CSAEarliestArrival"; import IJourneyExtractor from "../planner/public-transport/IJourneyExtractor"; import IPublicTransportPlanner from "../planner/public-transport/IPublicTransportPlanner"; import JourneyExtractorProfile from "../planner/public-transport/JourneyExtractorProfile"; @@ -61,7 +61,7 @@ container.bind(TYPES.JourneyExtractor) .to(JourneyExtractorProfile); container.bind(TYPES.PublicTransportPlanner) - .to(CSAEarliestArrivalVerbose); + .to(CSAEarliestArrival); container.bind>(TYPES.PublicTransportPlannerFactory) .toAutoFactory(TYPES.PublicTransportPlanner); diff --git a/src/events/EventType.ts b/src/events/EventType.ts index 73c92af3..3138c184 100644 --- a/src/events/EventType.ts +++ b/src/events/EventType.ts @@ -14,9 +14,10 @@ enum EventType { InitialReachableStops = "initial-reachable-stops", AddedNewTransferProfile = "added-new-transfer-profile", - ReachableLocation = "ReachableLocation", - ReachableStop = "ReachableStop", - ReachableTile = "ReachableTile", + ReachableLocation = "ReachableLocation", // planning reached a location + ReachableStop = "ReachableStop", // planning reached a stop (id) + ReachableTile = "ReachableTile", // planning reached a tile (coordinate) + ReachableTranfer = "ReachableTransfer", // planning reached a transfer ResourceFetch = "ResourceFetch", } diff --git a/src/fetcher/connections/ConnectionsProviderDefault.ts b/src/fetcher/connections/ConnectionsProviderDefault.ts index 2c9748c0..9babd9df 100644 --- a/src/fetcher/connections/ConnectionsProviderDefault.ts +++ b/src/fetcher/connections/ConnectionsProviderDefault.ts @@ -14,7 +14,7 @@ import IConnectionsProvider from "./IConnectionsProvider"; @injectable() export default class ConnectionsProviderDefault implements IConnectionsProvider { - private accessUrls: string[]; + private sources: IConnectionsSourceConfig[]; private singleProviders: ConnectionsProviderSingle[]; private connectionsFetcherFactory: ConnectionsFetcherFactory; private templateFetcher: IHydraTemplateFetcher; @@ -24,7 +24,7 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider @inject(TYPES.Catalog) catalog: Catalog, @inject(TYPES.HydraTemplateFetcher) templateFetcher: IHydraTemplateFetcher, ) { - this.accessUrls = []; + this.sources = []; this.singleProviders = []; this.connectionsFetcherFactory = connectionsFetcherFactory; this.templateFetcher = templateFetcher; @@ -35,12 +35,16 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider } public addConnectionSource(source: IConnectionsSourceConfig) { - this.accessUrls.push(source.accessUrl); + this.sources.push(source); this.singleProviders.push( new ConnectionsProviderSingle(this.connectionsFetcherFactory, source, this.templateFetcher), ); } + public getSources(): IConnectionsSourceConfig[] { + return this.sources; + } + public prefetchConnections(lowerBound: Date, upperBound: Date): void { for (const provider of this.singleProviders) { provider.prefetchConnections(lowerBound, upperBound); diff --git a/src/fetcher/connections/ConnectionsProviderSingle.ts b/src/fetcher/connections/ConnectionsProviderSingle.ts index caf701ab..cd68697c 100644 --- a/src/fetcher/connections/ConnectionsProviderSingle.ts +++ b/src/fetcher/connections/ConnectionsProviderSingle.ts @@ -21,7 +21,7 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { protected fetcher: IConnectionsFetcher; protected templateFetcher: IHydraTemplateFetcher; protected pages: ILinkedConnectionsPageIndex = {}; - protected accessUrl: string; + protected source: IConnectionsSourceConfig; protected template: Promise; constructor( @@ -30,7 +30,7 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { templateFetcher: IHydraTemplateFetcher, ) { const { accessUrl, travelMode } = catalog; - this.accessUrl = accessUrl; + this.source = catalog; this.fetcher = connectionsFetcherFactory(travelMode); this.templateFetcher = templateFetcher; } @@ -39,6 +39,10 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { throw new Error("Method not implemented."); } + public getSources(): IConnectionsSourceConfig[] { + return [this.source]; + } + public async getByUrl(url: string): Promise { if (!this.pages[url]) { this.pages[url] = this.fetcher.get(url); @@ -154,7 +158,7 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { protected async getTemplate(): Promise { if (!this.template) { - this.template = this.templateFetcher.get(this.accessUrl); + this.template = this.templateFetcher.get(this.source.accessUrl); } return this.template; } diff --git a/src/fetcher/connections/IConnectionsProvider.ts b/src/fetcher/connections/IConnectionsProvider.ts index 9ce0d9e0..43da2d7f 100644 --- a/src/fetcher/connections/IConnectionsProvider.ts +++ b/src/fetcher/connections/IConnectionsProvider.ts @@ -7,6 +7,7 @@ import IConnectionsIteratorOptions from "./IConnectionsIteratorOptions"; export default interface IConnectionsProvider { addConnectionSource(source: IConnectionsSourceConfig); + getSources(): IConnectionsSourceConfig[]; prefetchConnections(lowerBound: Date, upperBound: Date): void; appendIterator( diff --git a/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts b/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts index 364247f8..8b4fa7b7 100644 --- a/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts +++ b/src/fetcher/connections/tests/ConnectionsProviderNMBSTest.ts @@ -15,6 +15,10 @@ export default class ConnectionsProviderNMBSTest implements IConnectionsProvider this.connections = connections; } + public getSources(): IConnectionsSourceConfig[] { + throw new Error("Method not implemented."); + } + public appendIterator( options: IConnectionsIteratorOptions, existingIterator: AsyncIterator, diff --git a/src/fetcher/stops/IStopsProvider.ts b/src/fetcher/stops/IStopsProvider.ts index 6a0d908b..8a706d0b 100644 --- a/src/fetcher/stops/IStopsProvider.ts +++ b/src/fetcher/stops/IStopsProvider.ts @@ -1,3 +1,4 @@ +import { IStopsSourceConfig } from "../../Catalog"; import IStop from "./IStop"; /** @@ -8,7 +9,8 @@ import IStop from "./IStop"; */ export default interface IStopsProvider { prefetchStops(); - addStopSource(accessUrl: string); + addStopSource(source: IStopsSourceConfig); + getSources(): IStopsSourceConfig[]; getStopById(stopId: string): Promise; getAllStops(): Promise; } diff --git a/src/fetcher/stops/StopsFetcherRaw.ts b/src/fetcher/stops/StopsFetcherRaw.ts index 5c87df6f..406e6a64 100644 --- a/src/fetcher/stops/StopsFetcherRaw.ts +++ b/src/fetcher/stops/StopsFetcherRaw.ts @@ -1,6 +1,7 @@ import { inject, injectable } from "inversify"; import LDFetch from "ldfetch"; import { EventType } from "../.."; +import { IStopsSourceConfig } from "../../Catalog"; import EventBus from "../../events/EventBus"; import TYPES from "../../types"; import IStop from "./IStop"; @@ -30,10 +31,14 @@ export default class StopsFetcherRaw implements IStopsFetcher { this.ldFetch = ldFetch; } - public addStopSource(accessUrl: string) { + public addStopSource(source: IStopsSourceConfig) { throw new Error("Method not implemented."); } + public getSources(): IStopsSourceConfig[] { + return [{ accessUrl: this.accessUrl }]; + } + public setAccessUrl(accessUrl: string) { this.accessUrl = accessUrl; } diff --git a/src/fetcher/stops/StopsProviderDefault.ts b/src/fetcher/stops/StopsProviderDefault.ts index 0b0e83c8..29c9b605 100644 --- a/src/fetcher/stops/StopsProviderDefault.ts +++ b/src/fetcher/stops/StopsProviderDefault.ts @@ -1,5 +1,5 @@ import { inject, injectable } from "inversify"; -import Catalog from "../../Catalog"; +import Catalog, { IStopsSourceConfig } from "../../Catalog"; import TYPES, { StopsFetcherFactory } from "../../types"; import IStop from "./IStop"; import IStopsFetcher from "./IStopsFetcher"; @@ -12,24 +12,31 @@ export default class StopsProviderDefault implements IStopsProvider { private cachedStops: IStop[]; private allStops: Promise; private stopsFetcherFactory: StopsFetcherFactory; + private sources: IStopsSourceConfig[]; constructor( @inject(TYPES.StopsFetcherFactory) stopsFetcherFactory: StopsFetcherFactory, @inject(TYPES.Catalog) catalog: Catalog, ) { + this.sources = []; this.stopsFetchers = []; this.cachedStops = []; this.stopsFetcherFactory = stopsFetcherFactory; - for (const { accessUrl } of catalog.stopsSourceConfigs) { - this.addStopSource(accessUrl); + for (const source of catalog.stopsSourceConfigs) { + this.addStopSource(source); } } - public addStopSource(accessUrl: string) { + public addStopSource(source: IStopsSourceConfig) { + this.sources.push(source); this.cachedStops = []; this.allStops = null; - this.stopsFetchers.push(this.stopsFetcherFactory(accessUrl)); + this.stopsFetchers.push(this.stopsFetcherFactory(source.accessUrl)); + } + + public getSources(): IStopsSourceConfig[] { + return this.sources; } public prefetchStops(): void { diff --git a/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.ts b/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.ts index c12d8a51..d5aea3e2 100644 --- a/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.ts +++ b/src/fetcher/stops/ld-fetch/StopsFetcherLDFetch.ts @@ -1,6 +1,7 @@ import { inject, injectable } from "inversify"; import LDFetch from "ldfetch"; import { Triple } from "rdf-js"; +import { IStopsSourceConfig } from "../../../Catalog"; import TYPES from "../../../types"; import Rdf from "../../../util/Rdf"; import IStop from "../IStop"; @@ -30,10 +31,14 @@ export default class StopsFetcherLDFetch implements IStopsFetcher { this.loadStops(); } - public addStopSource(accessUrl: string) { + public addStopSource(source: IStopsSourceConfig) { throw new Error("Method not implemented."); } + public getSources(): IStopsSourceConfig[] { + return [{ accessUrl: this.accessUrl }]; + } + public setAccessUrl(accessUrl: string) { this.accessUrl = accessUrl; } diff --git a/src/planner/configurations/Planner.ts b/src/planner/configurations/Planner.ts index 425c0218..912974cd 100644 --- a/src/planner/configurations/Planner.ts +++ b/src/planner/configurations/Planner.ts @@ -1,6 +1,7 @@ import { AsyncIterator } from "asynciterator"; import { PromiseProxyIterator } from "asynciterator-promiseproxy"; import { EventEmitter } from "events"; +import { IConnectionsSourceConfig, IStopsSourceConfig } from "../../Catalog"; import defaultContainer from "../../configs/basic_train"; import Context from "../../Context"; import TravelMode from "../../enums/TravelMode"; @@ -58,7 +59,15 @@ export default abstract class Planner { } public addStopSource(accessUrl: string) { - this.stopsProvider.addStopSource(accessUrl); + this.stopsProvider.addStopSource({ accessUrl }); + } + + public getConnectionSources(): IConnectionsSourceConfig[] { + return this.connectionsProvider.getSources(); + } + + public getStopsSources(): IStopsSourceConfig[] { + return this.stopsProvider.getSources(); } public async completePath(path: IPath): Promise { diff --git a/src/planner/public-transport/CSAEarliestArrival.ts b/src/planner/public-transport/CSAEarliestArrival.ts index 0a3f42eb..c2275897 100644 --- a/src/planner/public-transport/CSAEarliestArrival.ts +++ b/src/planner/public-transport/CSAEarliestArrival.ts @@ -160,6 +160,8 @@ export default class CSAEarliestArrival implements IPublicTransportPlanner { enterConnection: state.enterConnectionByTrip[tripId], }; state.profilesByStop[connection.arrivalStop] = arrivalProfile; + + EventBus.getInstance().emit(EventType.ReachableLocation, this.locationResolver.resolve(connection.arrivalStop)); } private async extractJourneys(state: IQueryState, query: IResolvedQuery): Promise> { diff --git a/src/planner/public-transport/CSAEarliestArrivalVerbose.ts b/src/planner/public-transport/CSAEarliestArrivalVerbose.ts deleted file mode 100644 index f5b0ccdc..00000000 --- a/src/planner/public-transport/CSAEarliestArrivalVerbose.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { inject, injectable, tagged } from "inversify"; -import IConnection from "../../entities/connections/connections"; -import ReachableStopsSearchPhase from "../../enums/ReachableStopsSearchPhase"; -import EventBus from "../../events/EventBus"; -import EventType from "../../events/EventType"; -import IConnectionsProvider from "../../fetcher/connections/IConnectionsProvider"; -import ILocationResolver from "../../query-runner/ILocationResolver"; -import IResolvedQuery from "../../query-runner/IResolvedQuery"; -import TYPES from "../../types"; -import IReachableStopsFinder from "../stops/IReachableStopsFinder"; -import CSAEarliestArrival from "./CSAEarliestArrival"; - -@injectable() -export default class CSAEarliestArrivalVerbose extends CSAEarliestArrival { - constructor( - @inject(TYPES.ConnectionsProvider) - connectionsProvider: IConnectionsProvider, - @inject(TYPES.LocationResolver) - locationResolver: ILocationResolver, - @inject(TYPES.ReachableStopsFinder) - @tagged("phase", ReachableStopsSearchPhase.Transfer) - transferReachableStopsFinder: IReachableStopsFinder, - @inject(TYPES.ReachableStopsFinder) - @tagged("phase", ReachableStopsSearchPhase.Initial) - initialReachableStopsFinder: IReachableStopsFinder, - @inject(TYPES.ReachableStopsFinder) - @tagged("phase", ReachableStopsSearchPhase.Final) - finalReachableStopsFinder: IReachableStopsFinder, - ) { - super(connectionsProvider, locationResolver, transferReachableStopsFinder, - initialReachableStopsFinder, finalReachableStopsFinder); - } - - protected updateProfile(state, query: IResolvedQuery, connection: IConnection) { - super.updateProfile(state, query, connection); - EventBus.getInstance().emit(EventType.ReachableLocation, this.locationResolver.resolve(connection.arrivalStop)); - } -} diff --git a/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts b/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts index c8c23faf..759e8082 100644 --- a/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts +++ b/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts @@ -33,7 +33,7 @@ export default class ReachableStopsFinderFootpathsVerbose extends ReachableStops if (!this.done.has(sourceOrTargetStop.id)) { this.done.add(sourceOrTargetStop.id); for (const reachableStop of result) { - EventBus.getInstance().emit(EventType.ReachableStop, sourceOrTargetStop, reachableStop.stop); + EventBus.getInstance().emit(EventType.ReachableTranfer, sourceOrTargetStop, reachableStop.stop); } } From 74eebafe5ae6482e85523312c085f310d4b773e6 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 14:15:37 +0100 Subject: [PATCH 10/18] Clean up user-facing APIs --- src/QueryMode.ts | 7 + src/configs/bus_train.ts | 127 ------------------ .../{transit_car.ts => reduced_car.ts} | 0 .../{basic_train.ts => road_planner.ts} | 20 +-- .../{triangle_demo.ts => triangle_transit.ts} | 0 src/create.ts | 65 +++++++++ src/data/Datatypes.ts | 11 ++ src/data/IDataSource.ts | 4 + src/data/classify.ts | 44 ++++++ src/events/EventType.ts | 2 +- src/index.ts | 91 +++++++++---- src/isochrone.demo.ts | 7 - .../configurations/BasicTrainPlanner.ts | 8 -- .../configurations/DelijnNmbsPlanner.ts | 8 -- .../configurations/FlexibleRoadPlanner.ts | 16 +++ src/planner/configurations/Planner.ts | 9 +- ...nsitCarPlanner.ts => ReducedCarPlanner.ts} | 2 +- .../configurations/TriangleDemoPlanner.ts | 8 -- .../configurations/TriangleTransitPlanner.ts | 8 ++ .../public-transport/CSAEarliestArrival.ts | 2 +- src/uri/constants.ts | 1 + 21 files changed, 243 insertions(+), 197 deletions(-) create mode 100644 src/QueryMode.ts delete mode 100644 src/configs/bus_train.ts rename src/configs/{transit_car.ts => reduced_car.ts} (100%) rename src/configs/{basic_train.ts => road_planner.ts} (91%) rename src/configs/{triangle_demo.ts => triangle_transit.ts} (100%) create mode 100644 src/create.ts create mode 100644 src/data/Datatypes.ts create mode 100644 src/data/IDataSource.ts create mode 100644 src/data/classify.ts delete mode 100644 src/isochrone.demo.ts delete mode 100644 src/planner/configurations/BasicTrainPlanner.ts delete mode 100644 src/planner/configurations/DelijnNmbsPlanner.ts create mode 100644 src/planner/configurations/FlexibleRoadPlanner.ts rename src/planner/configurations/{TransitCarPlanner.ts => ReducedCarPlanner.ts} (89%) delete mode 100644 src/planner/configurations/TriangleDemoPlanner.ts create mode 100644 src/planner/configurations/TriangleTransitPlanner.ts diff --git a/src/QueryMode.ts b/src/QueryMode.ts new file mode 100644 index 00000000..f833ac73 --- /dev/null +++ b/src/QueryMode.ts @@ -0,0 +1,7 @@ +enum QueryMode { + "CSAEarliestArrival", + "CSAProfile", + "Dijkstra", +} + +export default QueryMode; diff --git a/src/configs/bus_train.ts b/src/configs/bus_train.ts deleted file mode 100644 index e5253556..00000000 --- a/src/configs/bus_train.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; -import catalogDeLijn from "../catalog.delijn"; -import catalogNmbs from "../catalog.nmbs"; -import Context from "../Context"; -import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; -import RoutingPhase from "../enums/RoutingPhase"; -import TravelMode from "../enums/TravelMode"; -import ConnectionsFetcherRaw from "../fetcher/connections/ConnectionsFetcherRaw"; -import ConnectionsProviderMerge from "../fetcher/connections/ConnectionsProviderDefault"; -import IConnectionsFetcher from "../fetcher/connections/IConnectionsFetcher"; -import IConnectionsProvider from "../fetcher/connections/IConnectionsProvider"; -import FootpathsProviderRaw from "../fetcher/footpaths/FootpathsProviderRaw"; -import IFootpathsFetcher from "../fetcher/footpaths/IFootpathsProvider"; -import HydraTemplateFetcherDefault from "../fetcher/hydra/HydraTemplateFetcherDefault"; -import IHydraTemplateFetcher from "../fetcher/hydra/IHydraTemplateFetcher"; -import LDFetch from "../fetcher/LDFetch"; -import IProfileFetcher from "../fetcher/profiles/IProfileFetcher"; -import IProfileProvider from "../fetcher/profiles/IProfileProvider"; -import ProfileFetcherDefault from "../fetcher/profiles/ProfileFetcherDefault"; -import ProfileProviderDefault from "../fetcher/profiles/ProfileProviderDefault"; -import IStopsFetcher from "../fetcher/stops/IStopsFetcher"; -import IStopsProvider from "../fetcher/stops/IStopsProvider"; -import StopsFetcherRaw from "../fetcher/stops/StopsFetcherRaw"; -import StopsProviderDefault from "../fetcher/stops/StopsProviderDefault"; -import IRoutableTileFetcher from "../fetcher/tiles/IRoutableTileFetcher"; -import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; -import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; -import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; -import RoutableTileProviderTransit from "../fetcher/tiles/RoutableTileProviderTransit"; - -import { LDLoader } from "../loader/ldloader"; -import DijkstraTree from "../pathfinding/dijkstra-tree/DijkstraTree"; -import MixedDijkstra from "../pathfinding/mixed-dijkstra/MixedDijkstra"; -import { IShortestPathAlgorithm, IShortestPathTreeAlgorithm } from "../pathfinding/pathfinder"; -import PathfinderProvider from "../pathfinding/PathfinderProvider"; -import CSAEarliestArrival from "../planner/public-transport/CSAEarliestArrival"; -import IJourneyExtractor from "../planner/public-transport/IJourneyExtractor"; -import IPublicTransportPlanner from "../planner/public-transport/IPublicTransportPlanner"; -import JourneyExtractorProfile from "../planner/public-transport/JourneyExtractorProfile"; -import IRoadPlanner from "../planner/road/IRoadPlanner"; -import RoadPlannerPathfinding from "../planner/road/RoadPlannerPathfinding"; -import IReachableStopsFinder from "../planner/stops/IReachableStopsFinder"; -import ReachableStopsFinderDelaunay from "../planner/stops/ReachableStopsFinderDelaunay"; -import ReachableStopsFinderFootpaths from "../planner/stops/ReachableStopsFinderFootpaths"; -import ILocationResolver from "../query-runner/ILocationResolver"; -import IQueryRunner from "../query-runner/IQueryRunner"; -import LocationResolverConvenience from "../query-runner/LocationResolverConvenience"; -import QueryRunnerDefault from "../query-runner/QueryRunnerDefault"; -import TYPES from "../types"; - -const container = new Container(); -container.bind(TYPES.Context).to(Context).inSingletonScope(); -container.bind(TYPES.QueryRunner).to(QueryRunnerDefault); -container.bind(TYPES.LocationResolver).to(LocationResolverConvenience); - -container.bind(TYPES.HydraTemplateFetcher).to(HydraTemplateFetcherDefault).inSingletonScope(); - -// TODO, make this a fixed property of the planner itself -container.bind(TYPES.JourneyExtractor) - .to(JourneyExtractorProfile); - -container.bind(TYPES.PublicTransportPlanner) - .to(CSAEarliestArrival); -container.bind>(TYPES.PublicTransportPlannerFactory) - .toAutoFactory(TYPES.PublicTransportPlanner); - -container.bind(TYPES.RoadPlanner) - .to(RoadPlannerPathfinding); - -container.bind(TYPES.ShortestPathTreeAlgorithm).to(DijkstraTree).inSingletonScope(); -container.bind(TYPES.ShortestPathAlgorithm).to(MixedDijkstra).inSingletonScope(); -container.bind(TYPES.PathfinderProvider).to(PathfinderProvider).inSingletonScope(); -container.bind(TYPES.ProfileFetcher).to(ProfileFetcherDefault).inSingletonScope(); -container.bind(TYPES.ProfileProvider).to(ProfileProviderDefault).inSingletonScope(); - -container.bind(TYPES.FootpathsProvider).to(FootpathsProviderRaw).inSingletonScope(); - -container.bind(TYPES.ReachableStopsFinder) - .to(ReachableStopsFinderDelaunay).whenTargetTagged("phase", ReachableStopsSearchPhase.Initial); -container.bind(TYPES.ReachableStopsFinder) - .to(ReachableStopsFinderFootpaths).whenTargetTagged("phase", ReachableStopsSearchPhase.Transfer); -container.bind(TYPES.ReachableStopsFinder) - .to(ReachableStopsFinderDelaunay).whenTargetTagged("phase", ReachableStopsSearchPhase.Final); - -container.bind(TYPES.ConnectionsProvider).to(ConnectionsProviderMerge).inSingletonScope(); -container.bind(TYPES.ConnectionsFetcher).to(ConnectionsFetcherRaw); -container.bind>(TYPES.ConnectionsFetcherFactory) - .toFactory( - (context: interfaces.Context) => - (travelMode: TravelMode) => { - const fetcher = context.container.get(TYPES.ConnectionsFetcher); - - fetcher.setTravelMode(travelMode); - - return fetcher; - }, - ); - -container.bind(TYPES.StopsProvider).to(StopsProviderDefault).inSingletonScope(); -container.bind(TYPES.StopsFetcher).to(StopsFetcherRaw); -container.bind>(TYPES.StopsFetcherFactory) - .toFactory( - (context: interfaces.Context) => - (accessUrl: string) => { - const fetcher = context.container.get(TYPES.StopsFetcher); - fetcher.setAccessUrl(accessUrl); - return fetcher; - }, - ); - -container.bind(TYPES.RoutableTileFetcher).to(RoutableTileFetcherRaw).inSingletonScope(); -container.bind(TYPES.RoutableTileProvider) - .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Base); -container.bind(TYPES.RoutableTileProvider) - .to(RoutableTileProviderTransit).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); - -// Bind catalog -const combined = Catalog.combine(catalogNmbs, catalogDeLijn); -container.bind(TYPES.Catalog).toConstantValue(combined); - -// Init LDFetch -container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); - -container.bind(TYPES.LDLoader).to(LDLoader); - -export default container; diff --git a/src/configs/transit_car.ts b/src/configs/reduced_car.ts similarity index 100% rename from src/configs/transit_car.ts rename to src/configs/reduced_car.ts diff --git a/src/configs/basic_train.ts b/src/configs/road_planner.ts similarity index 91% rename from src/configs/basic_train.ts rename to src/configs/road_planner.ts index 341cd9c8..9600bf7e 100644 --- a/src/configs/basic_train.ts +++ b/src/configs/road_planner.ts @@ -2,7 +2,6 @@ import { Container, interfaces } from "inversify"; import Catalog from "../Catalog"; import catalogNmbs from "../catalog.nmbs"; import Context from "../Context"; -import RoutableTileRegistry from "../entities/tiles/registry"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; import TravelMode from "../enums/TravelMode"; @@ -10,6 +9,8 @@ import ConnectionsFetcherRaw from "../fetcher/connections/ConnectionsFetcherRaw" import ConnectionsProviderDefault from "../fetcher/connections/ConnectionsProviderDefault"; import IConnectionsFetcher from "../fetcher/connections/IConnectionsFetcher"; import IConnectionsProvider from "../fetcher/connections/IConnectionsProvider"; +import FootpathsProviderDefault from "../fetcher/footpaths/FootpathsProviderDefault"; +import IFootpathsFetcher from "../fetcher/footpaths/IFootpathsProvider"; import HydraTemplateFetcherDefault from "../fetcher/hydra/HydraTemplateFetcherDefault"; import IHydraTemplateFetcher from "../fetcher/hydra/IHydraTemplateFetcher"; import LDFetch from "../fetcher/LDFetch"; @@ -25,13 +26,13 @@ import IRoutableTileFetcher from "../fetcher/tiles/IRoutableTileFetcher"; import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; -import RoutableTileProviderTransit from "../fetcher/tiles/RoutableTileProviderTransit"; + import { LDLoader } from "../loader/ldloader"; -import { BidirDijkstra } from "../pathfinding/bidirdijkstra/BidirDijkstra"; import DijkstraTree from "../pathfinding/dijkstra-tree/DijkstraTree"; +import MixedDijkstra from "../pathfinding/mixed-dijkstra/MixedDijkstra"; import { IShortestPathAlgorithm, IShortestPathTreeAlgorithm } from "../pathfinding/pathfinder"; import PathfinderProvider from "../pathfinding/PathfinderProvider"; -import CSAProfile from "../planner/public-transport/CSAProfile"; +import CSAEarliestArrival from "../planner/public-transport/CSAEarliestArrival"; import IJourneyExtractor from "../planner/public-transport/IJourneyExtractor"; import IPublicTransportPlanner from "../planner/public-transport/IPublicTransportPlanner"; import JourneyExtractorProfile from "../planner/public-transport/JourneyExtractorProfile"; @@ -58,19 +59,20 @@ container.bind(TYPES.JourneyExtractor) .to(JourneyExtractorProfile); container.bind(TYPES.PublicTransportPlanner) - .to(CSAProfile); + .to(CSAEarliestArrival); container.bind>(TYPES.PublicTransportPlannerFactory) .toAutoFactory(TYPES.PublicTransportPlanner); -container.bind(TYPES.RoadPlanner) - .to(RoadPlannerPathfinding); +container.bind(TYPES.RoadPlanner).to(RoadPlannerPathfinding); container.bind(TYPES.ShortestPathTreeAlgorithm).to(DijkstraTree).inSingletonScope(); -container.bind(TYPES.ShortestPathAlgorithm).to(BidirDijkstra).inSingletonScope(); +container.bind(TYPES.ShortestPathAlgorithm).to(MixedDijkstra).inSingletonScope(); container.bind(TYPES.PathfinderProvider).to(PathfinderProvider).inSingletonScope(); container.bind(TYPES.ProfileFetcher).to(ProfileFetcherDefault).inSingletonScope(); container.bind(TYPES.ProfileProvider).to(ProfileProviderDefault).inSingletonScope(); +container.bind(TYPES.FootpathsProvider).to(FootpathsProviderDefault).inSingletonScope(); + container.bind(TYPES.ReachableStopsFinder) .to(ReachableStopsFinderDelaunay).whenTargetTagged("phase", ReachableStopsSearchPhase.Initial); container.bind(TYPES.ReachableStopsFinder) @@ -108,7 +110,7 @@ container.bind(TYPES.RoutableTileFetcher).to(RoutableTileF container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Base); container.bind(TYPES.RoutableTileProvider) - .to(RoutableTileProviderTransit).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); + .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); // Bind catalog container.bind(TYPES.Catalog).toConstantValue(catalogNmbs); diff --git a/src/configs/triangle_demo.ts b/src/configs/triangle_transit.ts similarity index 100% rename from src/configs/triangle_demo.ts rename to src/configs/triangle_transit.ts diff --git a/src/create.ts b/src/create.ts new file mode 100644 index 00000000..c877cf85 --- /dev/null +++ b/src/create.ts @@ -0,0 +1,65 @@ +import { + DataType, + FlexibleProfileTransitPlanner, + FlexibleTransitPlanner, + QueryMode, + ReducedCarPlanner, + TriangleTransitPlanner, +} from "."; +import IDataSource from "./data/IDataSource"; +import FlexibleRoadPlanner from "./planner/configurations/FlexibleRoadPlanner"; +import Planner from "./planner/configurations/Planner"; + +/* + * Factory method for Planner configurations + * Picks the most appropriate configuration for the given data sources / query mode + * + * !! Due to hypermedia issues none of the tiled data sources are configurable right now + */ +export default function createPlanner(sources: IDataSource[], queryMode: QueryMode): Planner { + const connectionSources: IDataSource[] = []; + const stopSources: IDataSource[] = []; + const reducedTileSources: IDataSource[] = []; + const footpathSources: IDataSource[] = []; + + for (const source of sources) { + if (source.datatype === DataType.Connections) { + connectionSources.push(source); + } else if (source.datatype === DataType.Stops) { + stopSources.push(source); + } else if (source.datatype === DataType.ReducedRoutableTile) { + reducedTileSources.push(source); + } else if (source.datatype === DataType.Footpath) { + footpathSources.push(source); + } + } + + let planner: Planner; + if (queryMode === QueryMode.Dijkstra) { + if (reducedTileSources.length > 0) { + planner = new ReducedCarPlanner(); + } else { + planner = new FlexibleRoadPlanner(); + } + } else { + if (queryMode === QueryMode.CSAEarliestArrival) { + if (footpathSources.length > 0) { + planner = new TriangleTransitPlanner(); + } else { + planner = new FlexibleTransitPlanner(); + } + } else { + planner = new FlexibleProfileTransitPlanner(); + } + + for (const connectionSource of connectionSources) { + planner.addConnectionSource(connectionSource.accessUrl); + } + + for (const stopSource of stopSources) { + planner.addStopSource(stopSource.accessUrl); + } + } + + return planner; +} diff --git a/src/data/Datatypes.ts b/src/data/Datatypes.ts new file mode 100644 index 00000000..7c244ca4 --- /dev/null +++ b/src/data/Datatypes.ts @@ -0,0 +1,11 @@ +const DATATYPE = { + Connections: Symbol("Connection"), + Stops: Symbol("Stop"), + RoutableTile: Symbol("RoutableTile"), + ReducedRoutableTile: Symbol("ReducedRoutableTile"), + Profile: Symbol("Profile"), + Footpath: Symbol("Footpath"), + Unknown: Symbol("?"), +}; + +export default DATATYPE; diff --git a/src/data/IDataSource.ts b/src/data/IDataSource.ts new file mode 100644 index 00000000..86a89563 --- /dev/null +++ b/src/data/IDataSource.ts @@ -0,0 +1,4 @@ +export default interface IDataSource { + accessUrl: string; + datatype: symbol; +} diff --git a/src/data/classify.ts b/src/data/classify.ts new file mode 100644 index 00000000..5b48dbfc --- /dev/null +++ b/src/data/classify.ts @@ -0,0 +1,44 @@ +import LDFetch from "../fetcher/LDFetch"; +import { GEO, LC, PROFILE } from "../uri/constants"; +import URI from "../uri/uri"; +import DATATYPE from "./Datatypes"; +import IDataSource from "./IDataSource"; + +export default async function classifyDataSource(accessUrl: string): Promise { + let datatype: symbol; + if (accessUrl.indexOf("tiles") >= 0) { + if (accessUrl.indexOf("hdelva.be/") >= 0) { + datatype = DATATYPE.ReducedRoutableTile; + } else { + datatype = DATATYPE.RoutableTile; + } + } else if (accessUrl.indexOf("hdelva.be/stops/distances/") >= 0) { + datatype = DATATYPE.Footpath; + } else { + const fetcher = new LDFetch(); + const response = await fetcher.get(accessUrl); + const triples = response.triples; + + const usedPredicates = new Set(); + + for (const t of triples) { + const { predicate } = t; + usedPredicates.add(predicate.value); + } + + if (usedPredicates.has(URI.inNS(LC, "departureStop"))) { + datatype = DATATYPE.Connections; + } else if (usedPredicates.has(URI.inNS(GEO, "lat"))) { + datatype = DATATYPE.Stops; + } else if (usedPredicates.has(URI.inNS(PROFILE, "hasAccessRules"))) { + datatype = DATATYPE.Profile; + } else { + datatype = DATATYPE.Unknown; + } + } + + return { + accessUrl, + datatype, + }; +} diff --git a/src/events/EventType.ts b/src/events/EventType.ts index 3138c184..c74911f9 100644 --- a/src/events/EventType.ts +++ b/src/events/EventType.ts @@ -15,7 +15,7 @@ enum EventType { AddedNewTransferProfile = "added-new-transfer-profile", ReachableLocation = "ReachableLocation", // planning reached a location - ReachableStop = "ReachableStop", // planning reached a stop (id) + ReachableID = "ReachableID", // planning reached a location, but the value is just a ID ReachableTile = "ReachableTile", // planning reached a tile (coordinate) ReachableTranfer = "ReachableTransfer", // planning reached a transfer diff --git a/src/index.ts b/src/index.ts index 65e556db..29ae92cf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,53 +1,92 @@ import "isomorphic-fetch"; import "reflect-metadata"; +// classes import IsochroneGenerator from "./analytics/isochrones/main"; import TrafficEstimator from "./analytics/traffic/main"; + +// functions +import createPlanner from "./create"; +import classifyDataSource from "./data/classify"; + +// instances import RoutableTileRegistry_ from "./entities/tiles/registry"; -import TravelMode from "./enums/TravelMode"; import EventBus_ from "./events/EventBus"; + +// enums +import DataType from "./data/Datatypes"; +import TravelMode from "./enums/TravelMode"; import EventType from "./events/EventType"; -import BasicTrainPlanner from "./planner/configurations/BasicTrainPlanner"; -import DelijnNmbsPlanner from "./planner/configurations/DelijnNmbsPlanner"; +import QueryMode from "./QueryMode"; +import Units from "./util/Units"; + +// +// EXPORTS +// + +// planners import DissectPlanner from "./planner/configurations/DissectPlanner"; import FlexibleProfileTransitPlanner from "./planner/configurations/FlexibleProfileTransitPlanner"; +import FlexibleRoadPlanner from "./planner/configurations/FlexibleRoadPlanner"; import FlexibleTransitPlanner from "./planner/configurations/FlexibleTransitPlanner"; import GeospatialFragmentedPlanner from "./planner/configurations/GeospatialFragmentedPlanner"; -import TransitCarPlanner from "./planner/configurations/TransitCarPlanner"; -import TriangleDemoPlanner from "./planner/configurations/TriangleDemoPlanner"; -import Units from "./util/Units"; +import ReducedCarPlanner from "./planner/configurations/ReducedCarPlanner"; +import TriangleTransitPlanner from "./planner/configurations/TriangleTransitPlanner"; -export { default as EventType } from "./events/EventType"; +// classes export { default as IsochroneGenerator } from "./analytics/isochrones/main"; export { default as TrafficEstimator } from "./analytics/traffic/main"; + +// functions +export { default as createPlanner } from "./create"; +export { default as classifyDataSource } from "./data/classify"; + +// instances +export const EventBus = EventBus_.getInstance(); +export const RoutableTileRegistry = RoutableTileRegistry_.getInstance(); + +// enums +export { default as DataType } from "./data/Datatypes"; +export { default as TravelMode } from "./enums/TravelMode"; +export { default as EventType } from "./events/EventType"; +export { default as QueryMode } from "./QueryMode"; export { default as Units } from "./util/Units"; -export { default as BasicTrainPlanner } from "./planner/configurations/BasicTrainPlanner"; -export { default as DelijnNmbsPlanner } from "./planner/configurations/DelijnNmbsPlanner"; + +// planners export { default as DissectPlanner } from "./planner/configurations/DissectPlanner"; -export { default as TransitCarPlanner } from "./planner/configurations/TransitCarPlanner"; -export { default as FlexibleTransitPlanner } from "./planner/configurations/FlexibleTransitPlanner"; export { default as FlexibleProfileTransitPlanner } from "./planner/configurations/FlexibleProfileTransitPlanner"; +export { default as FlexibleRoadPlanner } from "./planner/configurations/FlexibleRoadPlanner"; +export { default as FlexibleTransitPlanner } from "./planner/configurations/FlexibleTransitPlanner"; export { default as GeospatialFragmentedPlanner } from "./planner/configurations/GeospatialFragmentedPlanner"; -export { default as TriangleDemoPlanner } from "./planner/configurations/TriangleDemoPlanner"; -export { default as TravelMode } from "./enums/TravelMode"; - -export const EventBus = EventBus_.getInstance(); -export const RoutableTileRegistry = RoutableTileRegistry_.getInstance(); +export { default as ReducedCarPlanner } from "./planner/configurations/ReducedCarPlanner"; +export { default as TriangleTransitPlanner } from "./planner/configurations/TriangleTransitPlanner"; export default { - TravelMode, - EventType, + // classes IsochroneGenerator, TrafficEstimator, - Units, + + // functions + classifyDataSource, + createPlanner, + + // instances + RoutableTileRegistry, EventBus, - BasicTrainPlanner, - DelijnNmbsPlanner, + + // enums + TravelMode, + EventType, + Units, + QueryMode, + DataType, + + // planners DissectPlanner, - TransitCarPlanner, - TriangleDemoPlanner, - RoutableTileRegistry, - FlexibleTransitPlanner, FlexibleProfileTransitPlanner, - GeospatialFragmentedPlanner, + FlexibleRoadPlanner, + FlexibleTransitPlanner, + GeospatialFragmentedPlanner, // experimental + ReducedCarPlanner, + TriangleTransitPlanner, }; diff --git a/src/isochrone.demo.ts b/src/isochrone.demo.ts deleted file mode 100644 index 6e02b53b..00000000 --- a/src/isochrone.demo.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { IsochroneGenerator } from "."; - -const x = new IsochroneGenerator({ latitude: 51.0262973, longitude: 3.7110885 }); -x.enableDebugLogs(); -x.getIsochrone(2500, true).then((y) => { - console.log(y); -}); diff --git a/src/planner/configurations/BasicTrainPlanner.ts b/src/planner/configurations/BasicTrainPlanner.ts deleted file mode 100644 index 74f2c115..00000000 --- a/src/planner/configurations/BasicTrainPlanner.ts +++ /dev/null @@ -1,8 +0,0 @@ -import basicTrainProfile from "../../configs/basic_train"; -import Planner from "./Planner"; - -export default class BasicTrainPlanner extends Planner { - constructor() { - super(basicTrainProfile); - } -} diff --git a/src/planner/configurations/DelijnNmbsPlanner.ts b/src/planner/configurations/DelijnNmbsPlanner.ts deleted file mode 100644 index dced5d0e..00000000 --- a/src/planner/configurations/DelijnNmbsPlanner.ts +++ /dev/null @@ -1,8 +0,0 @@ -import delijnNmbsProfile from "../../configs/bus_train"; -import Planner from "./Planner"; - -export default class DelijnNmbsPlanner extends Planner { - constructor() { - super(delijnNmbsProfile); - } -} diff --git a/src/planner/configurations/FlexibleRoadPlanner.ts b/src/planner/configurations/FlexibleRoadPlanner.ts new file mode 100644 index 00000000..69170c52 --- /dev/null +++ b/src/planner/configurations/FlexibleRoadPlanner.ts @@ -0,0 +1,16 @@ +import { AsyncIterator } from "asynciterator"; +import roadProfile from "../../configs/road_planner"; +import IPath from "../../interfaces/IPath"; +import IQuery from "../../interfaces/IQuery"; +import Planner from "./Planner"; + +export default class FlexibleRoadPlanner extends Planner { + constructor() { + super(roadProfile); + } + + public query(query: IQuery): AsyncIterator { + query.roadNetworkOnly = true; + return super.query(query); + } +} diff --git a/src/planner/configurations/Planner.ts b/src/planner/configurations/Planner.ts index 912974cd..63d54b20 100644 --- a/src/planner/configurations/Planner.ts +++ b/src/planner/configurations/Planner.ts @@ -2,7 +2,7 @@ import { AsyncIterator } from "asynciterator"; import { PromiseProxyIterator } from "asynciterator-promiseproxy"; import { EventEmitter } from "events"; import { IConnectionsSourceConfig, IStopsSourceConfig } from "../../Catalog"; -import defaultContainer from "../../configs/basic_train"; +import defaultContainer from "../../configs/default"; import Context from "../../Context"; import TravelMode from "../../enums/TravelMode"; import EventBus from "../../events/EventBus"; @@ -11,8 +11,10 @@ import IConnectionsProvider from "../../fetcher/connections/IConnectionsProvider import ProfileProvider from "../../fetcher/profiles/ProfileProviderDefault"; import IStop from "../../fetcher/stops/IStop"; import IStopsProvider from "../../fetcher/stops/IStopsProvider"; +import ILocation from "../../interfaces/ILocation"; import IPath from "../../interfaces/IPath"; import IQuery from "../../interfaces/IQuery"; +import ILocationResolver from "../../query-runner/ILocationResolver"; import IQueryRunner from "../../query-runner/IQueryRunner"; import TYPES from "../../types"; import Iterators from "../../util/Iterators"; @@ -34,6 +36,7 @@ export default abstract class Planner { private roadPlanner: IRoadPlanner; private connectionsProvider: IConnectionsProvider; private stopsProvider: IStopsProvider; + private locationResolver: ILocationResolver; /** * Initializes a new Planner @@ -50,6 +53,7 @@ export default abstract class Planner { this.roadPlanner = container.get(TYPES.RoadPlanner); this.connectionsProvider = container.get(TYPES.ConnectionsProvider); this.stopsProvider = container.get(TYPES.StopsProvider); + this.locationResolver = container.get(TYPES.LocationResolver); this.activeProfileID = "https://hdelva.be/profile/pedestrian"; } @@ -180,4 +184,7 @@ export default abstract class Planner { return Promise.reject(); } + public resolveLocation(id: string): Promise { + return this.locationResolver.resolve(id); + } } diff --git a/src/planner/configurations/TransitCarPlanner.ts b/src/planner/configurations/ReducedCarPlanner.ts similarity index 89% rename from src/planner/configurations/TransitCarPlanner.ts rename to src/planner/configurations/ReducedCarPlanner.ts index 94f87376..d0134577 100644 --- a/src/planner/configurations/TransitCarPlanner.ts +++ b/src/planner/configurations/ReducedCarPlanner.ts @@ -1,5 +1,5 @@ import { AsyncIterator } from "asynciterator"; -import transitCarProfile from "../../configs/transit_car"; +import transitCarProfile from "../../configs/reduced_car"; import IPath from "../../interfaces/IPath"; import IQuery from "../../interfaces/IQuery"; import Planner from "./Planner"; diff --git a/src/planner/configurations/TriangleDemoPlanner.ts b/src/planner/configurations/TriangleDemoPlanner.ts deleted file mode 100644 index e0fb9dda..00000000 --- a/src/planner/configurations/TriangleDemoPlanner.ts +++ /dev/null @@ -1,8 +0,0 @@ -import triangleDemoProfile from "../../configs/triangle_demo"; -import Planner from "./Planner"; - -export default class TriangleDemoPlanner extends Planner { - constructor() { - super(triangleDemoProfile); - } -} diff --git a/src/planner/configurations/TriangleTransitPlanner.ts b/src/planner/configurations/TriangleTransitPlanner.ts new file mode 100644 index 00000000..9452e686 --- /dev/null +++ b/src/planner/configurations/TriangleTransitPlanner.ts @@ -0,0 +1,8 @@ +import triangleDemoProfile from "../../configs/triangle_transit"; +import Planner from "./Planner"; + +export default class TriangleTransitPlanner extends Planner { + constructor() { + super(triangleDemoProfile); + } +} diff --git a/src/planner/public-transport/CSAEarliestArrival.ts b/src/planner/public-transport/CSAEarliestArrival.ts index c2275897..ad34f58c 100644 --- a/src/planner/public-transport/CSAEarliestArrival.ts +++ b/src/planner/public-transport/CSAEarliestArrival.ts @@ -161,7 +161,7 @@ export default class CSAEarliestArrival implements IPublicTransportPlanner { }; state.profilesByStop[connection.arrivalStop] = arrivalProfile; - EventBus.getInstance().emit(EventType.ReachableLocation, this.locationResolver.resolve(connection.arrivalStop)); + EventBus.getInstance().emit(EventType.ReachableID, connection.arrivalStop); } private async extractJourneys(state: IQueryState, query: IResolvedQuery): Promise> { diff --git a/src/uri/constants.ts b/src/uri/constants.ts index 1494cdc5..a645d9a9 100644 --- a/src/uri/constants.ts +++ b/src/uri/constants.ts @@ -9,3 +9,4 @@ export const ROUTE = "https://w3id.org/routabletiles/terms#"; export const PLANNER = "https://planner.js.org/terms#"; export const PROFILE = "https://w3id.org/openplannerteam/profile#"; export const TREE = "https://w3id.org/tree#"; +export const LC = "http://semweb.mmlab.be/ns/linkedconnections#"; From 4e4688c6beb9170c5b127e8e068d1dac1700136f Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 14:41:01 +0100 Subject: [PATCH 11/18] Nuke all hard coded catalogs --- src/Catalog.ts | 31 +------------------ src/catalog.delijn.oostvlaanderen.ts | 16 ---------- src/catalog.delijn.ts | 20 ------------ src/catalog.delijn.vlaenderen.ts | 17 ---------- src/catalog.mivb.ts | 9 ------ src/catalog.nmbs.ts | 9 ------ src/catalog.tec.ts | 8 ----- src/configs/default.ts | 5 --- src/configs/dissect.ts | 9 +----- src/configs/flexible_profile_transit.ts | 6 +--- src/configs/flexible_transit.ts | 6 +--- src/configs/geospatial_fragment.ts | 6 +--- src/configs/reduced_car.ts | 5 --- src/configs/road_planner.ts | 5 --- src/configs/triangle_transit.ts | 7 ----- .../connections/ConnectionsProviderDefault.ts | 7 +---- src/fetcher/stops/StopsProviderDefault.ts | 7 +---- ...lt.ts => HypermediaTreeProviderDefault.ts} | 6 ---- src/planner/configurations/DissectPlanner.ts | 18 +++++++++++ .../CSAEarliestArrival.test.ts | 9 +++--- .../public-transport/CSAProfile.test.ts | 18 ++++++----- .../QueryRunnerExponential.test.ts | 11 ++++--- src/types.ts | 1 - 23 files changed, 46 insertions(+), 190 deletions(-) delete mode 100644 src/catalog.delijn.oostvlaanderen.ts delete mode 100644 src/catalog.delijn.ts delete mode 100644 src/catalog.delijn.vlaenderen.ts delete mode 100644 src/catalog.mivb.ts delete mode 100644 src/catalog.nmbs.ts delete mode 100644 src/catalog.tec.ts rename src/fetcher/tree/{HypermediaTreeProviderDeault.ts => HypermediaTreeProviderDefault.ts} (83%) diff --git a/src/Catalog.ts b/src/Catalog.ts index 0d2aeb2c..82608566 100644 --- a/src/Catalog.ts +++ b/src/Catalog.ts @@ -1,35 +1,6 @@ import TravelMode from "./enums/TravelMode"; -/** - * A Catalog instance holds the stops source and connections source configs. - * These configs get passed to the [[StopsFetcherFactory]] and [[ConnectionsFetcherFactory]] to construct - * respectively [[IStopsFetcher]] and [[IConnectionsFetcher]] instances - */ -export default class Catalog { - - public static combine(...catalogs: Catalog[]): Catalog { - const combinedCatalog = new Catalog(); - - for (const sourceCatalog of catalogs) { - combinedCatalog.stopsSourceConfigs.push(...sourceCatalog.stopsSourceConfigs); - combinedCatalog.connectionsSourceConfigs.push(...sourceCatalog.connectionsSourceConfigs); - } - - return combinedCatalog; - } - - public stopsSourceConfigs: IStopsSourceConfig[] = []; - public connectionsSourceConfigs: IConnectionsSourceConfig[] = []; - - public addStopsSource(accessUrl: string) { - this.stopsSourceConfigs.push({accessUrl}); - } - - public addConnectionsSource(accessUrl: string, travelMode: TravelMode) { - this.connectionsSourceConfigs.push({accessUrl, travelMode}); - } -} - +// bit of legacy stuff, should be ok export interface IStopsSourceConfig { accessUrl: string; } diff --git a/src/catalog.delijn.oostvlaanderen.ts b/src/catalog.delijn.oostvlaanderen.ts deleted file mode 100644 index 391af230..00000000 --- a/src/catalog.delijn.oostvlaanderen.ts +++ /dev/null @@ -1,16 +0,0 @@ -import Catalog from "./Catalog"; -import TravelMode from "./enums/TravelMode"; - -/* tslint:disable:max-line-length */ - -const catalogDeLijn = new Catalog(); - -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Antwerpen/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Limburg/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Vlaams-Brabant/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/stops"); - -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/connections", TravelMode.Bus); - -export default catalogDeLijn; diff --git a/src/catalog.delijn.ts b/src/catalog.delijn.ts deleted file mode 100644 index 386a6ab1..00000000 --- a/src/catalog.delijn.ts +++ /dev/null @@ -1,20 +0,0 @@ -import Catalog from "./Catalog"; -import TravelMode from "./enums/TravelMode"; - -/* tslint:disable:max-line-length */ - -const catalogDeLijn = new Catalog(); - -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Antwerpen/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Limburg/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Vlaams-Brabant/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/stops"); - -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/Antwerpen/connections", TravelMode.Bus); -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/Limburg/connections", TravelMode.Bus); -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/connections", TravelMode.Bus); -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/Vlaams-Brabant/connections", TravelMode.Bus); -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/connections", TravelMode.Bus); - -export default catalogDeLijn; diff --git a/src/catalog.delijn.vlaenderen.ts b/src/catalog.delijn.vlaenderen.ts deleted file mode 100644 index 0139a6d0..00000000 --- a/src/catalog.delijn.vlaenderen.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Catalog from "./Catalog"; -import TravelMode from "./enums/TravelMode"; - -/* tslint:disable:max-line-length */ - -const catalogDeLijn = new Catalog(); - -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Antwerpen/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Limburg/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/Vlaams-Brabant/stops"); -catalogDeLijn.addStopsSource("https://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/stops"); - -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/connections", TravelMode.Bus); -catalogDeLijn.addConnectionsSource("https://openplanner.ilabt.imec.be/delijn/West-Vlaanderen/connections", TravelMode.Bus); - -export default catalogDeLijn; diff --git a/src/catalog.mivb.ts b/src/catalog.mivb.ts deleted file mode 100644 index 9cfcdf50..00000000 --- a/src/catalog.mivb.ts +++ /dev/null @@ -1,9 +0,0 @@ -import Catalog from "./Catalog"; -import TravelMode from "./enums/TravelMode"; - -const catalogMivb = new Catalog(); - -catalogMivb.addStopsSource("https://openplanner.ilabt.imec.be/mivb/stops"); -catalogMivb.addConnectionsSource("https://openplanner.ilabt.imec.be/mivb/connections", TravelMode.Bus); - -export default catalogMivb; diff --git a/src/catalog.nmbs.ts b/src/catalog.nmbs.ts deleted file mode 100644 index 7d4b1846..00000000 --- a/src/catalog.nmbs.ts +++ /dev/null @@ -1,9 +0,0 @@ -import Catalog from "./Catalog"; -import TravelMode from "./enums/TravelMode"; - -const catalogNmbs = new Catalog(); - -catalogNmbs.addStopsSource("https://irail.be/stations/NMBS"); -catalogNmbs.addConnectionsSource("https://graph.irail.be/sncb/connections", TravelMode.Train); - -export default catalogNmbs; diff --git a/src/catalog.tec.ts b/src/catalog.tec.ts deleted file mode 100644 index 3e30627a..00000000 --- a/src/catalog.tec.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Catalog from "./Catalog"; -import TravelMode from "./enums/TravelMode"; - -const catalogTec = new Catalog(); - -catalogTec.addStopsSource("https://openplanner.ilabt.imec.be/tec/stops"); - -export default catalogTec; diff --git a/src/configs/default.ts b/src/configs/default.ts index 4bf5af34..70df166c 100644 --- a/src/configs/default.ts +++ b/src/configs/default.ts @@ -1,7 +1,5 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; -import catalogNmbs from "../catalog.nmbs"; import Context from "../Context"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; @@ -112,9 +110,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.FootpathsProvider).to(FootpathsProviderDefault).inSingletonScope(); -// Bind catalog -container.bind(TYPES.Catalog).toConstantValue(catalogNmbs); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/configs/dissect.ts b/src/configs/dissect.ts index 9e070067..18d8b44e 100644 --- a/src/configs/dissect.ts +++ b/src/configs/dissect.ts @@ -1,8 +1,5 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; -import catalogOVl from "../catalog.delijn.oostvlaanderen"; -import catalogMivb from "../catalog.mivb"; -import catalogNmbs from "../catalog.nmbs"; + import Context from "../Context"; import RoutableTileRegistry from "../entities/tiles/registry"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; @@ -117,10 +114,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderTransit).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); -// Bind catalog -const combined = Catalog.combine(catalogMivb, catalogNmbs, catalogOVl); -container.bind(TYPES.Catalog).toConstantValue(combined); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/configs/flexible_profile_transit.ts b/src/configs/flexible_profile_transit.ts index f56d6f1f..ea91c871 100644 --- a/src/configs/flexible_profile_transit.ts +++ b/src/configs/flexible_profile_transit.ts @@ -1,5 +1,4 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; import Context from "../Context"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; @@ -25,7 +24,7 @@ import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; import HypermediaTreeFetcherDefault from "../fetcher/tree/HypermediaTreeFetcherDefault"; -import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDeault"; +import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDefault"; import IHypermediaTreeProvider from "../fetcher/tree/IHeadermediaTreeProvider"; import IHypermediaTreeFetcher from "../fetcher/tree/IHypermediaTreeFetcher"; import { LDLoader } from "../loader/ldloader"; @@ -115,9 +114,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); -// Bind empty catalog -container.bind(TYPES.Catalog).toConstantValue(new Catalog()); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/configs/flexible_transit.ts b/src/configs/flexible_transit.ts index e9dc932f..9bda734d 100644 --- a/src/configs/flexible_transit.ts +++ b/src/configs/flexible_transit.ts @@ -1,5 +1,4 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; import Context from "../Context"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; @@ -25,7 +24,7 @@ import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; import HypermediaTreeFetcherDefault from "../fetcher/tree/HypermediaTreeFetcherDefault"; -import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDeault"; +import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDefault"; import IHypermediaTreeProvider from "../fetcher/tree/IHeadermediaTreeProvider"; import IHypermediaTreeFetcher from "../fetcher/tree/IHypermediaTreeFetcher"; import { LDLoader } from "../loader/ldloader"; @@ -115,9 +114,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); -// Bind empty catalog -container.bind(TYPES.Catalog).toConstantValue(new Catalog()); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/configs/geospatial_fragment.ts b/src/configs/geospatial_fragment.ts index 5a43c345..e3364c96 100644 --- a/src/configs/geospatial_fragment.ts +++ b/src/configs/geospatial_fragment.ts @@ -1,5 +1,4 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; import Context from "../Context"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; @@ -24,7 +23,7 @@ import IRoutableTileProvider from "../fetcher/tiles/IRoutableTileProvider"; import RoutableTileFetcherRaw from "../fetcher/tiles/RoutableTileFetcherRaw"; import RoutableTileProviderDefault from "../fetcher/tiles/RoutableTileProviderDefault"; import HypermediaTreeFetcherDefault from "../fetcher/tree/HypermediaTreeFetcherDefault"; -import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDeault"; +import HypermediaTreeProviderDefault from "../fetcher/tree/HypermediaTreeProviderDefault"; import IHypermediaTreeProvider from "../fetcher/tree/IHeadermediaTreeProvider"; import IHypermediaTreeFetcher from "../fetcher/tree/IHypermediaTreeFetcher"; import { LDLoader } from "../loader/ldloader"; @@ -119,9 +118,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); -// Bind empty catalog -container.bind(TYPES.Catalog).toConstantValue(new Catalog()); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/configs/reduced_car.ts b/src/configs/reduced_car.ts index 8db59907..43b63032 100644 --- a/src/configs/reduced_car.ts +++ b/src/configs/reduced_car.ts @@ -1,6 +1,4 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; -import catalogNmbs from "../catalog.nmbs"; import Context from "../Context"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; @@ -114,9 +112,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderTransit).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); -// Bind catalog -container.bind(TYPES.Catalog).toConstantValue(catalogNmbs); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/configs/road_planner.ts b/src/configs/road_planner.ts index 9600bf7e..9ad2fb60 100644 --- a/src/configs/road_planner.ts +++ b/src/configs/road_planner.ts @@ -1,6 +1,4 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; -import catalogNmbs from "../catalog.nmbs"; import Context from "../Context"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; @@ -112,9 +110,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderDefault).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); -// Bind catalog -container.bind(TYPES.Catalog).toConstantValue(catalogNmbs); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/configs/triangle_transit.ts b/src/configs/triangle_transit.ts index 7a1f0458..0ec90715 100644 --- a/src/configs/triangle_transit.ts +++ b/src/configs/triangle_transit.ts @@ -1,7 +1,4 @@ import { Container, interfaces } from "inversify"; -import Catalog from "../Catalog"; -import catalogDeLijn from "../catalog.delijn.vlaenderen"; -import catalogNmbs from "../catalog.nmbs"; import Context from "../Context"; import ReachableStopsSearchPhase from "../enums/ReachableStopsSearchPhase"; import RoutingPhase from "../enums/RoutingPhase"; @@ -115,10 +112,6 @@ container.bind(TYPES.RoutableTileProvider) container.bind(TYPES.RoutableTileProvider) .to(RoutableTileProviderTransit).inSingletonScope().whenTargetTagged("phase", RoutingPhase.Transit); -// Bind catalog -const combined = Catalog.combine(catalogNmbs, catalogDeLijn); -container.bind(TYPES.Catalog).toConstantValue(combined); - // Init LDFetch container.bind(TYPES.LDFetch).to(LDFetch).inSingletonScope(); diff --git a/src/fetcher/connections/ConnectionsProviderDefault.ts b/src/fetcher/connections/ConnectionsProviderDefault.ts index 9babd9df..a39f3e28 100644 --- a/src/fetcher/connections/ConnectionsProviderDefault.ts +++ b/src/fetcher/connections/ConnectionsProviderDefault.ts @@ -1,6 +1,6 @@ import { AsyncIterator } from "asynciterator"; import { inject, injectable } from "inversify"; -import Catalog, { IConnectionsSourceConfig } from "../../Catalog"; +import { IConnectionsSourceConfig } from "../../Catalog"; import IConnection from "../../entities/connections/connections"; import { LinkedConnectionsPage } from "../../entities/connections/page"; import TYPES, { ConnectionsFetcherFactory } from "../../types"; @@ -21,17 +21,12 @@ export default class ConnectionsProviderDefault implements IConnectionsProvider constructor( @inject(TYPES.ConnectionsFetcherFactory) connectionsFetcherFactory: ConnectionsFetcherFactory, - @inject(TYPES.Catalog) catalog: Catalog, @inject(TYPES.HydraTemplateFetcher) templateFetcher: IHydraTemplateFetcher, ) { this.sources = []; this.singleProviders = []; this.connectionsFetcherFactory = connectionsFetcherFactory; this.templateFetcher = templateFetcher; - - for (const connectionSource of catalog.connectionsSourceConfigs) { - this.addConnectionSource(connectionSource); - } } public addConnectionSource(source: IConnectionsSourceConfig) { diff --git a/src/fetcher/stops/StopsProviderDefault.ts b/src/fetcher/stops/StopsProviderDefault.ts index 29c9b605..11073b8c 100644 --- a/src/fetcher/stops/StopsProviderDefault.ts +++ b/src/fetcher/stops/StopsProviderDefault.ts @@ -1,5 +1,5 @@ import { inject, injectable } from "inversify"; -import Catalog, { IStopsSourceConfig } from "../../Catalog"; +import { IStopsSourceConfig } from "../../Catalog"; import TYPES, { StopsFetcherFactory } from "../../types"; import IStop from "./IStop"; import IStopsFetcher from "./IStopsFetcher"; @@ -16,16 +16,11 @@ export default class StopsProviderDefault implements IStopsProvider { constructor( @inject(TYPES.StopsFetcherFactory) stopsFetcherFactory: StopsFetcherFactory, - @inject(TYPES.Catalog) catalog: Catalog, ) { this.sources = []; this.stopsFetchers = []; this.cachedStops = []; this.stopsFetcherFactory = stopsFetcherFactory; - - for (const source of catalog.stopsSourceConfigs) { - this.addStopSource(source); - } } public addStopSource(source: IStopsSourceConfig) { diff --git a/src/fetcher/tree/HypermediaTreeProviderDeault.ts b/src/fetcher/tree/HypermediaTreeProviderDefault.ts similarity index 83% rename from src/fetcher/tree/HypermediaTreeProviderDeault.ts rename to src/fetcher/tree/HypermediaTreeProviderDefault.ts index 60524dc0..0c4444f3 100644 --- a/src/fetcher/tree/HypermediaTreeProviderDeault.ts +++ b/src/fetcher/tree/HypermediaTreeProviderDefault.ts @@ -1,5 +1,4 @@ import { inject, injectable } from "inversify"; -import Catalog from "../../Catalog"; import HypermediaTree from "../../entities/tree/tree"; import TYPES from "../../types"; import IHypermediaTreeProvider from "./IHeadermediaTreeProvider"; @@ -13,14 +12,9 @@ export default class HypermediaTreeProviderDefault implements IHypermediaTreePro constructor( @inject(TYPES.HypermediaTreeFetcher) treeFetcher: IHypermediaTreeFetcher, - @inject(TYPES.Catalog) catalog: Catalog, ) { this.accessUrls = []; this.treeFetcher = treeFetcher; - - for (const { accessUrl } of catalog.connectionsSourceConfigs) { - this.addTreeSource(accessUrl); - } } public addTreeSource(accessUrl: string) { diff --git a/src/planner/configurations/DissectPlanner.ts b/src/planner/configurations/DissectPlanner.ts index 654e7b01..030678a8 100644 --- a/src/planner/configurations/DissectPlanner.ts +++ b/src/planner/configurations/DissectPlanner.ts @@ -1,8 +1,26 @@ import dissectProfile from "../../configs/dissect"; +import TravelMode from "../../enums/TravelMode"; import Planner from "./Planner"; export default class DissectPlanner extends Planner { constructor() { super(dissectProfile); + + this.addConnectionSource( + "https://graph.irail.be/sncb/connections", + TravelMode.Train, + ); + this.addConnectionSource( + "https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/connections", + TravelMode.Bus, + ); + this.addConnectionSource( + "https://openplanner.ilabt.imec.be/mivb/connections", + TravelMode.Bus, + ); + + this.addStopSource("https://irail.be/stations/NMBS"); + this.addStopSource("https://openplanner.ilabt.imec.be/delijn/Oost-Vlaanderen/stops"); + this.addStopSource("https://openplanner.ilabt.imec.be/mivb/stops"); } } diff --git a/src/planner/public-transport/CSAEarliestArrival.test.ts b/src/planner/public-transport/CSAEarliestArrival.test.ts index 9befecf2..e89c38b8 100644 --- a/src/planner/public-transport/CSAEarliestArrival.test.ts +++ b/src/planner/public-transport/CSAEarliestArrival.test.ts @@ -1,6 +1,5 @@ import "jest"; import LDFetch from "ldfetch"; -import Catalog from "../../Catalog"; import Defaults from "../../Defaults"; import RoutableTileRegistry from "../../entities/tiles/registry"; import TravelMode from "../../enums/TravelMode"; @@ -173,16 +172,18 @@ describe("[PublicTransportPlannerCSAEarliestArrival]", () => { const createQueryRunner = () => { const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); - const catalog = new Catalog(); - catalog.addConnectionsSource("https://graph.irail.be/sncb/connections", TravelMode.Train); const connectionProvider = new ConnectionsProviderDefault( (travelMode: TravelMode) => { const fetcher = new ConnectionsFetcherRaw(); fetcher.setTravelMode(travelMode); return fetcher; - }, catalog, + }, new HydraTemplateFetcherDefault(ldFetch), ); + connectionProvider.addConnectionSource({ + accessUrl: "https://graph.irail.be/sncb/connections", + travelMode: TravelMode.Train, + }); const stopsFetcher = new StopsFetcherLDFetch(ldFetch); stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); diff --git a/src/planner/public-transport/CSAProfile.test.ts b/src/planner/public-transport/CSAProfile.test.ts index 9d728d7e..7272a806 100644 --- a/src/planner/public-transport/CSAProfile.test.ts +++ b/src/planner/public-transport/CSAProfile.test.ts @@ -1,6 +1,5 @@ import "jest"; import LDFetch from "ldfetch"; -import Catalog from "../../Catalog"; import Defaults from "../../Defaults"; import RoutableTileRegistry from "../../entities/tiles/registry"; import TravelMode from "../../enums/TravelMode"; @@ -54,7 +53,7 @@ describe("[PublicTransportPlannerCSAProfile]", () => { let result: IPath[]; const query: IResolvedQuery = { - from: [{latitude: 50.914326, longitude: 3.255415 }], + from: [{ latitude: 50.914326, longitude: 3.255415 }], to: [{ latitude: 51.035896, longitude: 3.710875 }], profileID: "https://hdelva.be/profile/pedestrian", minimumDepartureTime: new Date("2018-11-06T09:00:00.000Z"), @@ -88,17 +87,20 @@ describe("[PublicTransportPlannerCSAProfile]", () => { const createQueryRunner = () => { const ldFetch = new LDFetch({ headers: { Accept: "application/ld+json" } }); - const catalog = new Catalog(); - catalog.addConnectionsSource("https://graph.irail.be/sncb/connections", TravelMode.Train); const connectionProvider = new ConnectionsProviderDefault( (travelMode: TravelMode) => { const fetcher = new ConnectionsFetcherRaw(); fetcher.setTravelMode(travelMode); return fetcher; - }, catalog, + }, new HydraTemplateFetcherDefault(ldFetch), ); + connectionProvider.addConnectionSource({ + accessUrl: "https://graph.irail.be/sncb/connections", + travelMode: TravelMode.Train, + }); + const stopsFetcher = new StopsFetcherLDFetch(ldFetch); stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); @@ -184,7 +186,7 @@ describe("[PublicTransportPlannerCSAProfile]", () => { let result: IPath[]; beforeAll(async () => { - const queryRunner = createQueryRunner(); + const queryRunner = createQueryRunner(); const iterator = await queryRunner.run(query); result = await Iterators.toArray(iterator); @@ -216,7 +218,7 @@ describe("[PublicTransportPlannerCSAProfile]", () => { let result: IPath[]; beforeAll(async () => { - const queryRunner = createQueryRunner(); + const queryRunner = createQueryRunner(); const iterator = await queryRunner.run(query); result = await Iterators.toArray(iterator); @@ -248,7 +250,7 @@ describe("[PublicTransportPlannerCSAProfile]", () => { let result: IPath[]; beforeAll(async () => { - const queryRunner = createQueryRunner(); + const queryRunner = createQueryRunner(); const iterator = await queryRunner.run(query); result = await Iterators.toArray(iterator); diff --git a/src/query-runner/exponential/QueryRunnerExponential.test.ts b/src/query-runner/exponential/QueryRunnerExponential.test.ts index b3ed2a6b..9c5c491b 100644 --- a/src/query-runner/exponential/QueryRunnerExponential.test.ts +++ b/src/query-runner/exponential/QueryRunnerExponential.test.ts @@ -1,6 +1,5 @@ import "jest"; import LDFetch from "ldfetch"; -import Catalog from "../../Catalog"; import TravelMode from "../../enums/TravelMode"; import ConnectionsFetcherRaw from "../../fetcher/connections/ConnectionsFetcherRaw"; import ConnectionsProviderDefault from "../../fetcher/connections/ConnectionsProviderDefault"; @@ -34,13 +33,15 @@ describe("[QueryRunnerExponential]", () => { const stopsFetcher = new StopsFetcherLDFetch(ldFetch); stopsFetcher.setAccessUrl("https://irail.be/stations/NMBS"); - const catalog = new Catalog(); - catalog.addConnectionsSource("https://graph.irail.be/sncb/connections", TravelMode.Train); - const connectionProvider = new ConnectionsProviderDefault((travelMode: TravelMode) => { connectionsFetcher.setTravelMode(travelMode); return connectionsFetcher; - }, catalog, new HydraTemplateFetcherDefault(ldFetch)); + }, new HydraTemplateFetcherDefault(ldFetch)); + + connectionProvider.addConnectionSource({ + accessUrl: "https://graph.irail.be/sncb/connections", + travelMode: TravelMode.Train, + }); const locationResolver = new LocationResolverDefault(stopsFetcher); const reachableStopsFinder = new ReachableStopsFinderBirdsEyeCached(stopsFetcher); diff --git a/src/types.ts b/src/types.ts index ad4c502f..d7fe4eaa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -42,7 +42,6 @@ const TYPES = { JourneyExtractor: Symbol("JourneyExtractor"), LDFetch: Symbol("LDFetch"), LDLoader: Symbol("LDLoader"), - Catalog: Symbol("Catalog"), }; export default TYPES; From 012a2d9751804fdc85d3b215bd6529859b7d525b Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 14:57:49 +0100 Subject: [PATCH 12/18] Third iteration of cleaner events --- src/fetcher/LDFetch.ts | 6 +++++- .../connections/ConnectionsFetcherRaw.ts | 12 ++++++----- .../connections/ConnectionsProviderSingle.ts | 20 ++++++++++++------- src/fetcher/footpaths/FootpathsProviderRaw.ts | 15 ++++++++++++++ src/fetcher/stops/StopsFetcherRaw.ts | 12 ++++++----- src/fetcher/tiles/RoutableTileFetcherRaw.ts | 11 ++++++---- .../ReachableStopsFinderFootpathsVerbose.ts | 6 +++++- 7 files changed, 59 insertions(+), 23 deletions(-) diff --git a/src/fetcher/LDFetch.ts b/src/fetcher/LDFetch.ts index ee8f08bb..82a18cd5 100644 --- a/src/fetcher/LDFetch.ts +++ b/src/fetcher/LDFetch.ts @@ -40,7 +40,11 @@ export default class LDFetch implements LDFetchBase { this.ldFetchBase.on("response", (url) => { const duration = (new Date()).getTime() - this.httpStartTimes[url].getTime(); - this.eventBus.emit(EventType.ResourceFetch, "?", url, duration, "?"); + this.eventBus.emit(EventType.ResourceFetch, + { + url, + duration, + }); }); } } diff --git a/src/fetcher/connections/ConnectionsFetcherRaw.ts b/src/fetcher/connections/ConnectionsFetcherRaw.ts index 95fc860b..23140f26 100644 --- a/src/fetcher/connections/ConnectionsFetcherRaw.ts +++ b/src/fetcher/connections/ConnectionsFetcherRaw.ts @@ -1,5 +1,6 @@ import fetch from "cross-fetch"; import { injectable } from "inversify"; +import { DataType } from "../.."; import IConnection from "../../entities/connections/connections"; import { LinkedConnectionsPage } from "../../entities/connections/page"; import DropOffType from "../../enums/DropOffType"; @@ -7,7 +8,6 @@ import PickupType from "../../enums/PickupType"; import TravelMode from "../../enums/TravelMode"; import EventBus from "../../events/EventBus"; import EventType from "../../events/EventType"; -import TYPES from "../../types"; import JSONLDContext from "../../uri/JSONLDContext"; import IConnectionsFetcher from "./IConnectionsFetcher"; @@ -113,10 +113,12 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { EventBus.getInstance().emit( EventType.ResourceFetch, - TYPES.ConnectionsFetcher, // origin - url, // resource uri - duration, // time it took to download and parse - size, // transferred data + { + datatype: DataType.Connections, + url, + duration, + size, + }, ); return new LinkedConnectionsPage(pageId, connections, previousPageUrl, nextPageUrl); diff --git a/src/fetcher/connections/ConnectionsProviderSingle.ts b/src/fetcher/connections/ConnectionsProviderSingle.ts index cd68697c..325683e6 100644 --- a/src/fetcher/connections/ConnectionsProviderSingle.ts +++ b/src/fetcher/connections/ConnectionsProviderSingle.ts @@ -91,8 +91,10 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { ): Promise> { EventBus.getInstance().emit( EventType.ConnectionIteratorView, - options.lowerBoundDate, - options.upperBoundDate, + { + lowerBound: options.lowerBoundDate, + upperBound: options.upperBoundDate, + }, ); const selector = options.backward ? backwardsConnectionsSelector : forwardsConnectionSelector; @@ -131,8 +133,10 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { public async createIterator(options: IConnectionsIteratorOptions): Promise> { EventBus.getInstance().emit( EventType.ConnectionIteratorView, - options.lowerBoundDate, - options.upperBoundDate, + { + lowerBound: options.lowerBoundDate, + upperBound: options.upperBoundDate, + }, ); let iterator: AsyncIterator; @@ -149,9 +153,11 @@ export default class ConnectionsProviderSingle implements IConnectionsProvider { return iterator.on("end", () => { EventBus.getInstance().emit( EventType.ConnectionIteratorView, - options.lowerBoundDate, - options.upperBoundDate, - true, + { + lowerBound: options.lowerBoundDate, + upperBound: options.upperBoundDate, + finished: true, + }, ); }); } diff --git a/src/fetcher/footpaths/FootpathsProviderRaw.ts b/src/fetcher/footpaths/FootpathsProviderRaw.ts index c6c2e1ae..92e40161 100644 --- a/src/fetcher/footpaths/FootpathsProviderRaw.ts +++ b/src/fetcher/footpaths/FootpathsProviderRaw.ts @@ -1,4 +1,5 @@ import { inject, injectable } from "inversify"; +import { DataType } from "../.."; import { Footpath, IFootpathIndex } from "../../entities/footpaths/footpath"; import { RoutableTileCoordinate } from "../../entities/tiles/coordinate"; import EventBus from "../../events/EventBus"; @@ -55,7 +56,11 @@ export default class FootpathsProviderRaw implements IFootpathsProvider { } protected async getByUrl(url: string): Promise { + const beginTime = new Date(); const response = await fetch(url); + const size = parseInt(response.headers.get("content-length"), 10); + const duration = (new Date()).getTime() - beginTime.getTime(); + const responseText = await response.text(); const footpaths: IFootpathIndex = {}; @@ -77,6 +82,16 @@ export default class FootpathsProviderRaw implements IFootpathsProvider { } } + EventBus.getInstance().emit( + EventType.ResourceFetch, + { + datatype: DataType.Footpath, + url, + duration, + size, + }, + ); + return footpaths; } } diff --git a/src/fetcher/stops/StopsFetcherRaw.ts b/src/fetcher/stops/StopsFetcherRaw.ts index 406e6a64..777c1d6a 100644 --- a/src/fetcher/stops/StopsFetcherRaw.ts +++ b/src/fetcher/stops/StopsFetcherRaw.ts @@ -1,6 +1,6 @@ import { inject, injectable } from "inversify"; import LDFetch from "ldfetch"; -import { EventType } from "../.."; +import { DataType, EventType } from "../.."; import { IStopsSourceConfig } from "../../Catalog"; import EventBus from "../../events/EventBus"; import TYPES from "../../types"; @@ -116,10 +116,12 @@ export default class StopsFetcherRaw implements IStopsFetcher { EventBus.getInstance().emit( EventType.ResourceFetch, - TYPES.StopsFetcher, // origin - url, // resource uri - duration, // time it took to download and parse - size, // transferred data + { + DataType: DataType.Stops, + url, + duration, + size, + }, ); return stops; diff --git a/src/fetcher/tiles/RoutableTileFetcherRaw.ts b/src/fetcher/tiles/RoutableTileFetcherRaw.ts index e64a6b57..6a175930 100644 --- a/src/fetcher/tiles/RoutableTileFetcherRaw.ts +++ b/src/fetcher/tiles/RoutableTileFetcherRaw.ts @@ -1,5 +1,6 @@ import fetch from "cross-fetch"; import { inject, injectable } from "inversify"; +import { DataType } from "../.."; import { IRoutableTileNodeIndex, RoutableTileNode } from "../../entities/tiles/node"; import RoutableTileRegistry from "../../entities/tiles/registry"; import { RoutableTile } from "../../entities/tiles/tile"; @@ -73,10 +74,12 @@ export default class RoutableTileFetcherRaw implements IRoutableTileFetcher { EventBus.getInstance().emit( EventType.ResourceFetch, - TYPES.StopsFetcher, // origin - url, // resource uri - duration, // time it took to download and parse - size, // transferred data + { + DataType: DataType.RoutableTile, + url, + duration, + size, + }, ); return this.processTileData(url, nodes, ways); diff --git a/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts b/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts index 759e8082..fb513292 100644 --- a/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts +++ b/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts @@ -33,7 +33,11 @@ export default class ReachableStopsFinderFootpathsVerbose extends ReachableStops if (!this.done.has(sourceOrTargetStop.id)) { this.done.add(sourceOrTargetStop.id); for (const reachableStop of result) { - EventBus.getInstance().emit(EventType.ReachableTranfer, sourceOrTargetStop, reachableStop.stop); + EventBus.getInstance().emit(EventType.ReachableTranfer, + { + from: sourceOrTargetStop, + to: reachableStop.stop, + }); } } From cead11c247372b47ab56737e7534de1efb9ff5b2 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 15:47:08 +0100 Subject: [PATCH 13/18] Make response length slightly more robust --- src/demo.ts | 7 ++----- src/fetcher/connections/ConnectionsFetcherRaw.ts | 14 +++++++++++++- src/fetcher/footpaths/FootpathsProviderRaw.ts | 14 +++++++++++++- src/fetcher/stops/StopsFetcherRaw.ts | 14 +++++++++++++- src/fetcher/tiles/RoutableTileFetcherRaw.ts | 14 +++++++++++++- src/planner/configurations/Planner.ts | 2 +- 6 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/demo.ts b/src/demo.ts index 89769985..608f3b09 100644 --- a/src/demo.ts +++ b/src/demo.ts @@ -11,7 +11,6 @@ export default async (logResults) => { planner.addStopSource("https://irail.be/stations/NMBS"); if (logResults) { - let scannedPages = 0; let scannedConnections = 0; const eventBus = EventBus.getInstance(); @@ -37,13 +36,11 @@ export default async (logResults) => { // logFetch = true; - console.log("Total scanned pages", scannedPages); console.log("Total scanned connections", scannedConnections); console.log("[Subquery]", minimumDepartureTime, maximumArrivalTime, maximumArrivalTime - minimumDepartureTime); }) - .on(EventType.ResourceFetch, (source, url, duration, size) => { - scannedPages++; - console.log(`[GET] ${url} (${duration}ms ${size} bytes)`); + .on(EventType.ResourceFetch, (data) => { + console.log(`[GET] ${JSON.stringify(data)}`); // if (logFetch) { // console.log(`[GET] ${url} (${duration}ms)`); diff --git a/src/fetcher/connections/ConnectionsFetcherRaw.ts b/src/fetcher/connections/ConnectionsFetcherRaw.ts index 23140f26..724e31ea 100644 --- a/src/fetcher/connections/ConnectionsFetcherRaw.ts +++ b/src/fetcher/connections/ConnectionsFetcherRaw.ts @@ -37,7 +37,7 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { const beginTime = new Date(); const response = await fetch(url); - const size = parseInt(response.headers.get("content-length"), 10); + const size = this.parseResponseLength(response); const duration = (new Date()).getTime() - beginTime.getTime(); const responseText = await response.text(); @@ -126,4 +126,16 @@ export default class ConnectionsFetcherRaw implements IConnectionsFetcher { return new LinkedConnectionsPage(url, [], undefined, undefined); } } + + private parseResponseLength(response): number { + if (response.headers.get("content-length")) { + return parseInt(response.headers.get("content-length"), 10); + } else { + try { + return response.body._chunkSize; + } catch (e) { + // + } + } + } } diff --git a/src/fetcher/footpaths/FootpathsProviderRaw.ts b/src/fetcher/footpaths/FootpathsProviderRaw.ts index 92e40161..40f85602 100644 --- a/src/fetcher/footpaths/FootpathsProviderRaw.ts +++ b/src/fetcher/footpaths/FootpathsProviderRaw.ts @@ -58,7 +58,7 @@ export default class FootpathsProviderRaw implements IFootpathsProvider { protected async getByUrl(url: string): Promise { const beginTime = new Date(); const response = await fetch(url); - const size = parseInt(response.headers.get("content-length"), 10); + const size = this.parseResponseLength(response); const duration = (new Date()).getTime() - beginTime.getTime(); const responseText = await response.text(); @@ -94,4 +94,16 @@ export default class FootpathsProviderRaw implements IFootpathsProvider { return footpaths; } + + protected parseResponseLength(response): number { + if (response.headers.get("content-length")) { + return parseInt(response.headers.get("content-length"), 10); + } else { + try { + return response.body._chunkSize; + } catch (e) { + // + } + } + } } diff --git a/src/fetcher/stops/StopsFetcherRaw.ts b/src/fetcher/stops/StopsFetcherRaw.ts index 777c1d6a..6c7f9f0b 100644 --- a/src/fetcher/stops/StopsFetcherRaw.ts +++ b/src/fetcher/stops/StopsFetcherRaw.ts @@ -86,7 +86,7 @@ export default class StopsFetcherRaw implements IStopsFetcher { const response = await fetch(url); const responseText = await response.text(); - const size = parseInt(response.headers.get("content-length"), 10); + const size = this.parseResponseLength(response); const duration = (new Date()).getTime() - beginTime.getTime(); const stops: IStopMap = {}; @@ -126,4 +126,16 @@ export default class StopsFetcherRaw implements IStopsFetcher { return stops; } + + private parseResponseLength(response): number { + if (response.headers.get("content-length")) { + return parseInt(response.headers.get("content-length"), 10); + } else { + try { + return response.body._chunkSize; + } catch (e) { + // + } + } + } } diff --git a/src/fetcher/tiles/RoutableTileFetcherRaw.ts b/src/fetcher/tiles/RoutableTileFetcherRaw.ts index 6a175930..1a67c63f 100644 --- a/src/fetcher/tiles/RoutableTileFetcherRaw.ts +++ b/src/fetcher/tiles/RoutableTileFetcherRaw.ts @@ -59,7 +59,7 @@ export default class RoutableTileFetcherRaw implements IRoutableTileFetcher { const nodes: IRoutableTileNodeIndex = {}; const ways: IRoutableTileWayIndex = {}; - const size = parseInt(response.headers.get("content-length"), 10); + const size = this.parseResponseLength(response); const duration = (new Date()).getTime() - beginTime.getTime(); for (const entity of blob["@graph"]) { @@ -88,6 +88,18 @@ export default class RoutableTileFetcherRaw implements IRoutableTileFetcher { } } + protected parseResponseLength(response): number { + if (response.headers.get("content-length")) { + return parseInt(response.headers.get("content-length"), 10); + } else { + try { + return response.body._chunkSize; + } catch (e) { + // + } + } + } + protected processTileData(url: string, nodes: IRoutableTileNodeIndex, ways: IRoutableTileWayIndex) { this.pathfinderProvider.registerEdges(ways, nodes); diff --git a/src/planner/configurations/Planner.ts b/src/planner/configurations/Planner.ts index 63d54b20..418381d6 100644 --- a/src/planner/configurations/Planner.ts +++ b/src/planner/configurations/Planner.ts @@ -141,7 +141,7 @@ export default abstract class Planner { iterator.on("error", (e) => { if (e && e.eventType) { - this.eventBus.emit(e.eventType, e.message); + this.eventBus.emit(e.eventType, e); } }); From 9bc577b74740cde32cecaec2318da468a1e5df3f Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 16:48:49 +0100 Subject: [PATCH 14/18] Restore triangle bois --- src/events/EventType.ts | 2 +- src/pathfinding/PathfinderProvider.ts | 81 +++++++++++++------ src/planner/configurations/Planner.ts | 2 +- .../stops/ReachableStopsFinderDelaunay.ts | 2 + .../ReachableStopsFinderFootpathsVerbose.ts | 2 +- 5 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/events/EventType.ts b/src/events/EventType.ts index c74911f9..5840260f 100644 --- a/src/events/EventType.ts +++ b/src/events/EventType.ts @@ -17,7 +17,7 @@ enum EventType { ReachableLocation = "ReachableLocation", // planning reached a location ReachableID = "ReachableID", // planning reached a location, but the value is just a ID ReachableTile = "ReachableTile", // planning reached a tile (coordinate) - ReachableTranfer = "ReachableTransfer", // planning reached a transfer + ReachableTransfer = "ReachableTransfer", // planning reached a transfer ResourceFetch = "ResourceFetch", } diff --git a/src/pathfinding/PathfinderProvider.ts b/src/pathfinding/PathfinderProvider.ts index 2b9b68db..8cb5c1a2 100644 --- a/src/pathfinding/PathfinderProvider.ts +++ b/src/pathfinding/PathfinderProvider.ts @@ -23,8 +23,8 @@ interface IPointEmbedding { way: RoutableTileWay; // the road where the point gets embedded in point: ILocation; // point that's embedded into the road network intersection: ILocation; // closest point on the road segment closest to the point - segA: RoutableTileNode; // one side of the road segment closest to the point - segB: RoutableTileNode; // other side of the road segment closest to the point + segA: ILocation; // one side of the road segment closest to the point + segB: ILocation; // other side of the road segment closest to the point } interface IGraphMap { @@ -106,7 +106,7 @@ export default class PathfinderProvider { for (const profile of await this.profileProvider.getProfiles()) { let bestDistance = Infinity; - let bestEmbedding: IPointEmbedding; + let bestSegment: [RoutableTileWay, ILocation, ILocation]; for (const wayId of tileset.getWays()) { const way = this.routableTileRegistry.getWay(wayId); @@ -129,37 +129,33 @@ export default class PathfinderProvider { const embedding = this.segmentDistToPoint(from, to, p); if (embedding) { - const [distance, intersection] = this.segmentDistToPoint(from, to, p); + const distance = this.segmentDistToPoint(from, to, p); if (distance < bestDistance) { bestDistance = distance; - bestEmbedding = { - way, - point: p, - segA: from, - segB: to, - intersection, - }; + bestSegment = [way, from, to]; } } } } } - if (bestEmbedding) { - const way = bestEmbedding.way; + if (bestSegment) { + const [way, segA, segB] = bestSegment; + const intersection = this.projectOntoSegment(segA, segB, p); + const newEmbedding: IPointEmbedding = { + way, segA, segB, intersection, point: p, + }; for (const otherEmbedding of this.embeddings) { - if (otherEmbedding.segA === bestEmbedding.segA && otherEmbedding.segB === bestEmbedding.segB) { - this.addEdge(profile, bestEmbedding.intersection, otherEmbedding.intersection, way); - this.addEdge(profile, otherEmbedding.intersection, bestEmbedding.intersection, way); + if (Geo.getId(otherEmbedding.segA) === Geo.getId(segA) + && Geo.getId(otherEmbedding.segB) === Geo.getId(segB)) { + this.addEdge(profile, intersection, otherEmbedding.intersection, way); + this.addEdge(profile, otherEmbedding.intersection, intersection, way); } } - this.embeddings.push(bestEmbedding); + this.embeddings.push(newEmbedding); - const intersection = bestEmbedding.intersection; - const segA = bestEmbedding.segA; - const segB = bestEmbedding.segB; const isOneWay = profile.isOneWay(way); if (!invert) { @@ -235,7 +231,47 @@ export default class PathfinderProvider { graph.addEdge(Geo.getId(from), Geo.getId(to), distance, duration, cost); } - private segmentDistToPoint(segA: ILocation, segB: ILocation, p: ILocation): [number, ILocation] { + private segmentDistToPoint(segA: ILocation, segB: ILocation, p: ILocation): number { + // potential 'catastrophic cancellation' + const sx1 = segA.longitude; + const sx2 = segB.longitude; + const px = p.longitude; + + const sy1 = segA.latitude; + const sy2 = segB.latitude; + const py = p.latitude; + + const px2 = sx2 - sx1; // <- + const py2 = sy2 - sy1; // <- + + const norm = px2 * px2 + py2 * py2; + + let u; + if (norm) { + u = ((px - sx1) * px2 + (py - sy1) * py2) / norm; + } else { + u = Infinity; + } + + if (u > 1) { + u = 1; + } else if (u < 0) { + u = 0; + } + + const x = sx1 + u * px2; + const y = sy1 + u * py2; + + const result = { + longitude: x, + latitude: y, + }; + + const dist = Geo.getDistanceBetweenLocations(p, result); + return dist; + } + + private projectOntoSegment(segA: ILocation, segB: ILocation, p: ILocation): ILocation { // potential 'catastrophic cancellation' const mSegA = proj4("EPSG:4326", "EPSG:3857", [segA.longitude, segA.latitude]); const mSegB = proj4("EPSG:4326", "EPSG:3857", [segB.longitude, segB.latitude]); @@ -276,7 +312,6 @@ export default class PathfinderProvider { latitude: intersection[1], }; - const dist = Geo.getDistanceBetweenLocations(p, result); - return [dist, result]; + return result; } } diff --git a/src/planner/configurations/Planner.ts b/src/planner/configurations/Planner.ts index 418381d6..63d54b20 100644 --- a/src/planner/configurations/Planner.ts +++ b/src/planner/configurations/Planner.ts @@ -141,7 +141,7 @@ export default abstract class Planner { iterator.on("error", (e) => { if (e && e.eventType) { - this.eventBus.emit(e.eventType, e); + this.eventBus.emit(e.eventType, e.message); } }); diff --git a/src/planner/stops/ReachableStopsFinderDelaunay.ts b/src/planner/stops/ReachableStopsFinderDelaunay.ts index e3eea7fd..c04c3160 100644 --- a/src/planner/stops/ReachableStopsFinderDelaunay.ts +++ b/src/planner/stops/ReachableStopsFinderDelaunay.ts @@ -88,6 +88,7 @@ export default class ReachableStopsFinderDelaunay implements IReachableStopsFind // not including these for now // may result in large route network queries if the stops network is sparse + /* const neighbors = this.triangles.neighbors(cell); for (const neighbor of neighbors) { const neighborLocation = this.trianglePoints[neighbor]; @@ -95,6 +96,7 @@ export default class ReachableStopsFinderDelaunay implements IReachableStopsFind result.push(neighborLocation); } } + */ return result; } diff --git a/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts b/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts index fb513292..09420d48 100644 --- a/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts +++ b/src/planner/stops/ReachableStopsFinderFootpathsVerbose.ts @@ -33,7 +33,7 @@ export default class ReachableStopsFinderFootpathsVerbose extends ReachableStops if (!this.done.has(sourceOrTargetStop.id)) { this.done.add(sourceOrTargetStop.id); for (const reachableStop of result) { - EventBus.getInstance().emit(EventType.ReachableTranfer, + EventBus.getInstance().emit(EventType.ReachableTransfer, { from: sourceOrTargetStop, to: reachableStop.stop, From 384973d415905937a65d89c257b39441c862571a Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 16:53:27 +0100 Subject: [PATCH 15/18] Update dependencies --- package-lock.json | 1358 +++++++++++++++++---------------------------- package.json | 20 +- 2 files changed, 529 insertions(+), 849 deletions(-) diff --git a/package-lock.json b/package-lock.json index d525a209..d2880e24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1827,9 +1827,9 @@ "dev": true }, "@types/node": { - "version": "12.7.8", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.8.tgz", - "integrity": "sha512-FMdVn84tJJdV+xe+53sYiZS4R5yn1mAIxfj+DVoNiQjTYz1+OYmjwEZr1ev9nU0axXwda0QDbYl06QHanRVH3A==" + "version": "12.12.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.25.tgz", + "integrity": "sha512-nf1LMGZvgFX186geVZR1xMZKKblJiRfiASTHw85zED2kI1yDKHDwTKMdkaCbTlXoRKlGKaDfYywt+V0As30q3w==" }, "@types/rdf-js": { "version": "1.0.1", @@ -2065,18 +2065,18 @@ }, "dependencies": { "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", "dev": true }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "dev": true, "requires": { - "mime-db": "1.40.0" + "mime-db": "1.43.0" } } } @@ -2560,7 +2560,7 @@ }, "util": { "version": "0.10.3", - "resolved": "http://registry.npmjs.org/util/-/util-0.10.3.tgz", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", "dev": true, "requires": { @@ -2587,10 +2587,13 @@ "dev": true }, "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } }, "async-each": { "version": "1.0.3", @@ -2609,9 +2612,9 @@ "integrity": "sha512-aVLheZsDNU5qpOv6jZEHnFv79GfEi+N0w/OLmMmXZfGD8XFFmPsRhkSqleNl9jS6mqy/DNoV7tXGcI0S3cUvHQ==" }, "asynciterator-promiseproxy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/asynciterator-promiseproxy/-/asynciterator-promiseproxy-2.0.0.tgz", - "integrity": "sha512-C0ub2jkCId4a66R9OuPa3Cvu+PF73yXEBErZc3NUlfLVXbYMmPF9vBUPzmCo3UuMdFmJLcfOjGxJpQ5a7z/G9A==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/asynciterator-promiseproxy/-/asynciterator-promiseproxy-2.1.0.tgz", + "integrity": "sha512-SIUlNe40pmPWDJ7N5yHK3ej694r90j0cblWAsh+8OBJLwlzGVdaehmAao2rgzjnzf1U3BhmEP9Fs4ddvDNoBTg==", "requires": { "asynciterator": "^2.0.0" } @@ -2954,7 +2957,7 @@ }, "browserify-aes": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", "dev": true, "requires": { @@ -2991,7 +2994,7 @@ }, "browserify-rsa": { "version": "4.0.1", - "resolved": "http://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.0.1.tgz", "integrity": "sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ=", "dev": true, "requires": { @@ -3042,9 +3045,9 @@ } }, "buffer": { - "version": "4.9.1", - "resolved": "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", "dev": true, "requires": { "base64-js": "^1.0.2", @@ -3319,31 +3322,14 @@ } }, "cliui": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", - "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" } }, "clone": { @@ -3413,18 +3399,18 @@ "dev": true }, "compressible": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.17.tgz", - "integrity": "sha512-BGHeLCK1GV7j1bSmQQAi26X+GgWcTjLr/0tzSvMCl3LH1w1IJ4PFSPoV5316b30cneTziC+B1a+3OjoSUcQYmw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "dev": true, "requires": { - "mime-db": ">= 1.40.0 < 2" + "mime-db": ">= 1.43.0 < 2" }, "dependencies": { "mime-db": { - "version": "1.41.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.41.0.tgz", - "integrity": "sha512-B5gxBI+2K431XW8C2rcc/lhppbuji67nf9v39eH8pkWoZDxnAL0PxdpH32KYRScniF8qDHBDlI+ipgg5WrCUYw==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", "dev": true } } @@ -3488,13 +3474,10 @@ "dev": true }, "console-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz", - "integrity": "sha1-8CQcRXMKn8YyOyBtvzjtx0HQuxA=", - "dev": true, - "requires": { - "date-now": "^0.1.4" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true }, "constants-browserify": { "version": "1.0.0", @@ -3575,7 +3558,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "dev": true, "requires": { @@ -3588,7 +3571,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "dev": true, "requires": { @@ -3714,12 +3697,6 @@ } } }, - "date-now": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/date-now/-/date-now-0.1.4.tgz", - "integrity": "sha1-6vQ5/U1ISK105cx9vvIAZyueNFs=", - "dev": true - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -3850,15 +3827,6 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true - }, - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } } } }, @@ -3884,9 +3852,9 @@ "dev": true }, "des.js": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.0.tgz", - "integrity": "sha1-wHTS4qpqipoH29YfmhXCzYPsjsw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -3918,9 +3886,9 @@ "dev": true }, "diff": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.1.tgz", - "integrity": "sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, "diff-sequences": { @@ -3931,7 +3899,7 @@ }, "diffie-hellman": { "version": "5.0.3", - "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", "dev": true, "requires": { @@ -4012,9 +3980,9 @@ "dev": true }, "elliptic": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.1.tgz", - "integrity": "sha512-xvJINNLbTeWQjrl6X+7eQCrIy/YPv5XCpKW6kB5mKvtnGILoLDcySuwomfdzt0BMdLNVnuRNTuzKNHj0bva1Cg==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.2.tgz", + "integrity": "sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw==", "dev": true, "requires": { "bn.js": "^4.4.0", @@ -4198,9 +4166,9 @@ "dev": true }, "events": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.0.0.tgz", - "integrity": "sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.1.0.tgz", + "integrity": "sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg==", "dev": true }, "eventsource": { @@ -4682,9 +4650,9 @@ }, "dependencies": { "graceful-fs": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.2.tgz", - "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", "dev": true } } @@ -5279,9 +5247,9 @@ } }, "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, "get-closest": { @@ -5368,9 +5336,9 @@ } }, "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true } } @@ -5565,9 +5533,9 @@ "integrity": "sha512-KW4MS8+krLIeiw8bF5z532CptG0ZyGGFj0UbKMxx25lKnnJ1hMUbuzQl+PXQjNiDLnl1bOyz23U6hSK10r4guw==" }, "highlight.js": { - "version": "9.15.10", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.15.10.tgz", - "integrity": "sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw==", + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-9.18.0.tgz", + "integrity": "sha512-A97kI1KAUzKoAiEoaGcf2O9YPS8nbDTCRFokaaeBhnqjQTvbAuAJrQMm21zw8s8xzaMtCQBtgbyGXLGxdxQyqQ==", "dev": true }, "hmac-drbg": { @@ -5814,9 +5782,9 @@ "dev": true }, "is-absolute-url": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.2.tgz", - "integrity": "sha512-+5g/wLlcm1AcxSP7014m6GvbPHswDx980vD/3bZaap8aGV9Yfs7Q6y6tfaupgZ5O74Byzc8dGrSCJ+bFXx0KdA==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", "dev": true }, "is-accessor-descriptor": { @@ -7056,9 +7024,9 @@ "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=" }, "loglevel": { - "version": "1.6.4", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.4.tgz", - "integrity": "sha512-p0b6mOGKcGa+7nnmKbpzR6qloPbrgLcnio++E+14Vo/XffOGwZtRpUhr8dTH/x2oCMmEoIU0Zwm3ZauhvYD17g==", + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.6.6.tgz", + "integrity": "sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ==", "dev": true }, "loose-envify": { @@ -7081,9 +7049,9 @@ } }, "lunr": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.6.tgz", - "integrity": "sha512-swStvEyDqQ85MGpABCMBclZcLI/pBIlu8FFDtmX197+oEgKloJ67QnB+Tidh0340HmLMs39c4GrkPY3cmkXp6Q==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.8.tgz", + "integrity": "sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==", "dev": true }, "make-dir": { @@ -7150,9 +7118,9 @@ } }, "marked": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.7.0.tgz", - "integrity": "sha512-c+yYdCZJQrsRjTPhUx7VKkApw9bwDkNbHUKo1ovgcfDjb2kc8rLuRbIFyXL5WOEUwzSSKo3IXpph2K6DqB/KZg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.8.0.tgz", + "integrity": "sha512-MyUe+T/Pw4TZufHkzAfDj6HarCBWia2y27/bhuYkTaiUnfDYFnCP3KUN+9oM7Wi6JA2rymtVYbQu3spE0GCmxQ==", "dev": true }, "md5.js": { @@ -8069,14 +8037,31 @@ "integrity": "sha1-1Ztk6P7kHElFiqyCtWcYxZV7Kvc=" }, "portfinder": { - "version": "1.0.24", - "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.24.tgz", - "integrity": "sha512-ekRl7zD2qxYndYflwiryJwMioBI7LI7rVXg3EnLK3sjkouT5eOuhS3gS255XxBksa30VG8UPZYZCdgfGOfkSUg==", + "version": "1.0.25", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.25.tgz", + "integrity": "sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg==", "dev": true, "requires": { - "async": "^1.5.2", - "debug": "^2.2.0", - "mkdirp": "0.5.x" + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, "posix-character-classes": { @@ -8149,9 +8134,9 @@ "dev": true }, "proj4": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.5.0.tgz", - "integrity": "sha512-XZTRT7OPdLzgvtTqL8DG2cEj8lYdovztOwiwpwRSYayOty5Ipf3H68dh/fiL+HKDEyetmQSMhkkMGiJoyziz3w==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/proj4/-/proj4-2.6.0.tgz", + "integrity": "sha512-ll2WyehUFOyzEZtN8hAiOTmZpuDCN5V+4A/HjhPbhlwVwlsFKnIHSZ3l3uhzgDndHjoL2MyERFGe9VmXN4rYUg==", "requires": { "mgrs": "1.0.0", "wkt-parser": "^1.2.0" @@ -8414,447 +8399,162 @@ "graceful-fs": "^4.1.11", "micromatch": "^3.1.10", "readable-stream": "^2.0.2" + } + }, + "realpath-native": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", + "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", + "dev": true, + "requires": { + "util.promisify": "^1.0.0" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "^1.1.6" + } + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + } + }, + "regexp.prototype.flags": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", + "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", + "requires": { + "define-properties": "^1.1.2" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", + "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + } + }, + "request-promise-core": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", + "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", + "requires": { + "lodash": "^4.13.1" + } + }, + "request-promise-native": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", + "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", + "requires": { + "request-promise-core": "1.1.1", + "stealthy-require": "^1.1.0", + "tough-cookie": ">=2.3.3" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" }, "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "realpath-native": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/realpath-native/-/realpath-native-1.1.0.tgz", - "integrity": "sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA==", - "dev": true, - "requires": { - "util.promisify": "^1.0.0" - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexp.prototype.flags": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz", - "integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==", - "requires": { - "define-properties": "^1.1.2" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "request": { - "version": "2.88.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", - "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", - "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.0", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.4.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - } - }, - "request-promise-core": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.1.tgz", - "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", - "requires": { - "lodash": "^4.13.1" - } - }, - "request-promise-native": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.5.tgz", - "integrity": "sha1-UoF3D2jgyXGeUWP9P6tIIhX0/aU=", - "requires": { - "request-promise-core": "1.1.1", - "stealthy-require": "^1.1.0", - "tough-cookie": ">=2.3.3" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", - "dev": true - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-cwd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", - "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", - "dev": true, - "requires": { - "resolve-from": "^3.0.0" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - }, - "dependencies": { - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, "requires": { "global-prefix": "^1.0.1", @@ -9013,21 +8713,21 @@ }, "dependencies": { "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", "dev": true }, "json-schema-traverse": { @@ -9045,18 +8745,18 @@ "dev": true }, "selfsigned": { - "version": "1.10.6", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.6.tgz", - "integrity": "sha512-i3+CeqxL7DpAazgVpAGdKMwHuL63B5nhJMh9NQ7xmChGkA3jNFflq6Jyo1LLJYcr3idWiNOPWHCrm4zMayLG4w==", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", + "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", "dev": true, "requires": { - "node-forge": "0.8.2" + "node-forge": "0.9.0" }, "dependencies": { "node-forge": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.8.2.tgz", - "integrity": "sha512-mXQ9GBq1N3uDCyV1pdSzgIguwgtVpM7f5/5J4ipz12PKWElmPpVWLDuWl8iXmhysr21+WmX/OJ5UKx82wjomgg==", + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", + "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", "dev": true } } @@ -9191,7 +8891,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { @@ -9452,9 +9152,9 @@ } }, "source-map-support": { - "version": "0.5.13", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", - "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz", + "integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -9569,9 +9269,9 @@ "dev": true }, "readable-stream": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.4.0.tgz", - "integrity": "sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.5.0.tgz", + "integrity": "sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA==", "dev": true, "requires": { "inherits": "^2.0.3", @@ -9693,9 +9393,9 @@ } }, "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", "dev": true }, "string-length": { @@ -9726,30 +9426,14 @@ } }, "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", "dev": true, "requires": { + "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } + "strip-ansi": "^5.1.0" } }, "string.prototype.trimleft": { @@ -9823,9 +9507,9 @@ "dev": true }, "terser": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.4.2.tgz", - "integrity": "sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.6.3.tgz", + "integrity": "sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ==", "dev": true, "requires": { "commander": "^2.20.0", @@ -9879,9 +9563,9 @@ } }, "thunky": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz", - "integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, "tiles-in-bbox": { @@ -10357,9 +10041,9 @@ "dev": true }, "tslint": { - "version": "5.20.0", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.0.tgz", - "integrity": "sha512-2vqIvkMHbnx8acMogAERQ/IuINOq6DFqgF8/VDvhEkBqQh/x6SP0Y+OHnKth9/ZcHQSroOZwUQSN18v8KKF0/g==", + "version": "5.20.1", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.20.1.tgz", + "integrity": "sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -10439,18 +10123,18 @@ }, "dependencies": { "mime-db": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", - "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==", + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", "dev": true }, "mime-types": { - "version": "2.1.24", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", - "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "dev": true, "requires": { - "mime-db": "1.40.0" + "mime-db": "1.43.0" } } } @@ -10461,48 +10145,54 @@ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, "typedoc": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.15.0.tgz", - "integrity": "sha512-NOtfq5Tis4EFt+J2ozhVq9RCeUnfEYMFKoU6nCXCXUULJz1UQynOM+yH3TkfZCPLzigbqB0tQYGVlktUWweKlw==", + "version": "0.15.8", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.15.8.tgz", + "integrity": "sha512-a0zypcvfIFsS7Gqpf2MkC1+jNND3K1Om38pbDdy/gYWX01NuJZhC5+O0HkIp0oRIZOo7PWrA5+fC24zkANY28Q==", "dev": true, "requires": { "@types/minimatch": "3.0.3", "fs-extra": "^8.1.0", - "handlebars": "^4.1.2", - "highlight.js": "^9.15.8", + "handlebars": "^4.7.0", + "highlight.js": "^9.17.1", "lodash": "^4.17.15", - "marked": "^0.7.0", + "marked": "^0.8.0", "minimatch": "^3.0.0", "progress": "^2.0.3", "shelljs": "^0.8.3", - "typedoc-default-themes": "^0.6.0", - "typescript": "3.5.x" + "typedoc-default-themes": "^0.6.3", + "typescript": "3.7.x" }, "dependencies": { - "typescript": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz", - "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g==", - "dev": true + "handlebars": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.2.tgz", + "integrity": "sha512-4PwqDL2laXtTWZghzzCtunQUTLbo31pcCJrd/B/9JP8XbhVzpS5ZXuKqlOzsd1rtcaLo4KqAn8nl8mkknS4MHw==", + "dev": true, + "requires": { + "neo-async": "^2.6.0", + "optimist": "^0.6.1", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4" + } } } }, "typedoc-default-themes": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.6.0.tgz", - "integrity": "sha512-MdTROOojxod78CEv22rIA69o7crMPLnVZPefuDLt/WepXqJwgiSu8Xxq+H36x0Jj3YGc7lOglI2vPJ2GhoOybw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.6.3.tgz", + "integrity": "sha512-rouf0TcIA4M2nOQFfC7Zp4NEwoYiEX4vX/ZtudJWU9IHA29MPC+PPgSXYLPESkUo7FuB//GxigO3mk9Qe1xp3Q==", "dev": true, "requires": { "backbone": "^1.4.0", "jquery": "^3.4.1", - "lunr": "^2.3.6", + "lunr": "^2.3.8", "underscore": "^1.9.1" } }, "typescript": { - "version": "3.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.6.3.tgz", - "integrity": "sha512-N7bceJL1CtRQ2RiG0AQME13ksR7DiuQh/QehubYcghzv20tnh+MQnQIuJddTmsbqYj+dztchykemz0zFzlvdQw==", + "version": "3.7.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.5.tgz", + "integrity": "sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw==", "dev": true }, "uglify-js": { @@ -10526,9 +10216,9 @@ } }, "underscore": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", - "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz", + "integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ==", "dev": true }, "union-value": { @@ -10620,9 +10310,9 @@ } }, "upath": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.2.tgz", - "integrity": "sha512-kXpym8nmDmlCBr7nKdIx8P2jNBa+pBpIUFRnKJ4dr8htyYGJFokkr2ZvERRtUN+9SY+JqXouNgUPtv6JQva/2Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", "dev": true }, "uri-js": { @@ -10752,9 +10442,9 @@ } }, "vm-browserify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.0.tgz", - "integrity": "sha512-iq+S7vZJE60yejDYM0ek6zg308+UZsdtPExWP9VZoCFCz1zkJoXFnAX7aZfd/ZwrkidzdUZL0C/ryW+JwAiIGw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", "dev": true }, "w3c-hr-time": { @@ -10800,9 +10490,9 @@ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==" }, "webpack": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.0.tgz", - "integrity": "sha512-yNV98U4r7wX1VJAj5kyMsu36T8RPPQntcb5fJLOsMz/pt/WrKC0Vp1bAlqPLkA1LegSwQwf6P+kAbyhRKVQ72g==", + "version": "4.41.5", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.41.5.tgz", + "integrity": "sha512-wp0Co4vpyumnp3KlkmpM5LWuzvZYayDwM2n17EHFr4qxBBbRokC7DJawPJC7TfSFZ9HZ6GsdH40EBj4UV0nmpw==", "dev": true, "requires": { "@webassemblyjs/ast": "1.8.5", @@ -10825,33 +10515,33 @@ "node-libs-browser": "^2.2.1", "schema-utils": "^1.0.0", "tapable": "^1.1.3", - "terser-webpack-plugin": "^1.4.1", + "terser-webpack-plugin": "^1.4.3", "watchpack": "^1.6.0", "webpack-sources": "^1.4.1" }, "dependencies": { "acorn": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.3.0.tgz", - "integrity": "sha512-/czfa8BwS88b9gWQVhc8eknunSA2DoJpJyTQkhheIf5E48u1N0R4q/YxxsAeqRrmK9TQ/uYfgLDfZo91UlANIA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.0.tgz", + "integrity": "sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw==", "dev": true }, "ajv": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", - "integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.11.0.tgz", + "integrity": "sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", + "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", "dev": true }, "json-schema-traverse": { @@ -10869,9 +10559,9 @@ } }, "webpack-cli": { - "version": "3.3.9", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.9.tgz", - "integrity": "sha512-xwnSxWl8nZtBl/AFJCOn9pG7s5CYUYdZxmmukv+fAHLcBIHM36dImfpQg3WfShZXeArkWlf6QRw24Klcsv8a5A==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-3.3.10.tgz", + "integrity": "sha512-u1dgND9+MXaEt74sJR4PR7qkPxXUSQ0RXYq8x1L6Jg1MYVEmGPrH6Ah6C4arD4r0J1P5HKjRqpab36k0eIzPqg==", "dev": true, "requires": { "chalk": "2.4.2", @@ -10887,12 +10577,6 @@ "yargs": "13.2.4" }, "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -10915,17 +10599,6 @@ } } }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, "cross-spawn": { "version": "6.0.5", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", @@ -10938,70 +10611,13 @@ "shebang-command": "^1.2.0", "which": "^1.2.9" } - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - } - }, - "yargs": { - "version": "13.2.4", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", - "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "os-locale": "^3.1.0", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.0" - } - }, - "yargs-parser": { - "version": "13.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", - "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } } } }, "webpack-dev-middleware": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.1.tgz", - "integrity": "sha512-5MWu9SH1z3hY7oHOV6Kbkz5x7hXbxK56mGHNqHTe6d+ewxOwKUxoUJBs7QIaJb33lPjl9bJZ3X0vCoooUzC36A==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz", + "integrity": "sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw==", "dev": true, "requires": { "memory-fs": "^0.4.1", @@ -11020,9 +10636,9 @@ } }, "webpack-dev-server": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.8.1.tgz", - "integrity": "sha512-9F5DnfFA9bsrhpUCAfQic/AXBVHvq+3gQS+x6Zj0yc1fVVE0erKh2MV4IV12TBewuTrYeeTIRwCH9qLMvdNvTw==", + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.10.1.tgz", + "integrity": "sha512-AGG4+XrrXn4rbZUueyNrQgO4KGnol+0wm3MPdqGLmmA+NofZl3blZQKxZ9BND6RDNuvAK9OMYClhjOSnxpWRoA==", "dev": true, "requires": { "ansi-html": "0.0.7", @@ -11034,18 +10650,18 @@ "del": "^4.1.1", "express": "^4.17.1", "html-entities": "^1.2.1", - "http-proxy-middleware": "^0.19.1", + "http-proxy-middleware": "0.19.1", "import-local": "^2.0.0", "internal-ip": "^4.3.0", "ip": "^1.1.5", - "is-absolute-url": "^3.0.2", + "is-absolute-url": "^3.0.3", "killable": "^1.0.1", - "loglevel": "^1.6.4", + "loglevel": "^1.6.6", "opn": "^5.5.0", "p-retry": "^3.0.1", - "portfinder": "^1.0.24", + "portfinder": "^1.0.25", "schema-utils": "^1.0.0", - "selfsigned": "^1.10.6", + "selfsigned": "^1.10.7", "semver": "^6.3.0", "serve-index": "^1.9.1", "sockjs": "0.3.19", @@ -11054,7 +10670,7 @@ "strip-ansi": "^3.0.1", "supports-color": "^6.1.0", "url": "^0.11.0", - "webpack-dev-middleware": "^3.7.1", + "webpack-dev-middleware": "^3.7.2", "webpack-log": "^2.0.0", "ws": "^6.2.1", "yargs": "12.0.5" @@ -11066,24 +10682,38 @@ "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "cliui": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz", + "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "debug": { @@ -11095,16 +10725,22 @@ "ms": "^2.1.1" } }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", "dev": true }, "semver": { @@ -11113,6 +10749,33 @@ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -11122,6 +10785,38 @@ "ansi-regex": "^2.0.0" } }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", @@ -11130,6 +10825,36 @@ "requires": { "async-limiter": "~1.0.0" } + }, + "yargs": { + "version": "12.0.5", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", + "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "dev": true, + "requires": { + "cliui": "^4.0.0", + "decamelize": "^1.2.0", + "find-up": "^3.0.0", + "get-caller-file": "^1.0.1", + "os-locale": "^3.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1 || ^4.0.0", + "yargs-parser": "^11.1.1" + } + }, + "yargs-parser": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", + "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } } } }, @@ -11282,50 +11007,14 @@ } }, "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" } }, "wrappy": { @@ -11391,37 +11080,28 @@ "dev": true }, "yargs": { - "version": "12.0.5", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz", - "integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==", + "version": "13.2.4", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.2.4.tgz", + "integrity": "sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.2.0", + "cliui": "^5.0.0", "find-up": "^3.0.0", - "get-caller-file": "^1.0.1", - "os-locale": "^3.0.0", + "get-caller-file": "^2.0.1", + "os-locale": "^3.1.0", "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", + "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", - "string-width": "^2.0.0", + "string-width": "^3.0.0", "which-module": "^2.0.0", - "y18n": "^3.2.1 || ^4.0.0", - "yargs-parser": "^11.1.1" - }, - "dependencies": { - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - } + "y18n": "^4.0.0", + "yargs-parser": "^13.1.0" } }, "yargs-parser": { - "version": "11.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz", - "integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==", + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.1.tgz", + "integrity": "sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==", "dev": true, "requires": { "camelcase": "^5.0.0", diff --git a/package.json b/package.json index 29e007ac..f11141c5 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,9 @@ "dependencies": { "@turf/turf": "^5.1.6", "@types/concaveman": "^1.1.3", - "@types/node": "^12.7.8", + "@types/node": "^12.12.25", "asynciterator": "^2.0.1", - "asynciterator-promiseproxy": "^2.0.0", + "asynciterator-promiseproxy": "^2.1.0", "concaveman": "^1.1.1", "cross-fetch": "^3.0.4", "d3-delaunay": "^4.1.5", @@ -41,7 +41,7 @@ "isomorphic-fetch": "^2.2.1", "ldfetch": "^1.1.2", "node-dijkstra": "^2.5.0", - "proj4": "^2.5.0", + "proj4": "^2.6.0", "reflect-metadata": "^0.1.13", "tiles-in-bbox": "^1.0.2", "tinyqueue": "^2.0.2", @@ -59,15 +59,15 @@ "jest": "^24.9.0", "pre-commit": "^1.2.2", "prettier": "1.14.3", - "source-map-support": "^0.5.13", + "source-map-support": "^0.5.16", "ts-jest": "^23.10.5", "ts-loader": "^5.4.5", - "tslint": "^5.20.0", - "typedoc": "^0.15.0", - "typescript": "^3.6.3", - "webpack": "^4.41.0", - "webpack-cli": "^3.3.9", - "webpack-dev-server": "^3.8.1" + "tslint": "^5.20.1", + "typedoc": "^0.15.8", + "typescript": "^3.7.5", + "webpack": "^4.41.5", + "webpack-cli": "^3.3.10", + "webpack-dev-server": "^3.10.1" }, "sideEffects": false } From d67a15ca1fa776144440fb8d8eccb95714cafec4 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 17:46:39 +0100 Subject: [PATCH 16/18] Bump version to 0.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f11141c5..30a548f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plannerjs", - "version": "0.2.2", + "version": "0.3.0", "description": "The JavaScript framework for journey planning.", "main": "lib/index.js", "license": "MIT", From 118ec4a4b7fbe62a82236a00abbdcac5b28f7f37 Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 17:48:33 +0100 Subject: [PATCH 17/18] update readme --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 968ba601..a9867b08 100644 --- a/README.md +++ b/README.md @@ -13,22 +13,24 @@ Include it in the browser: ... ``` Include it in your JavaScript project: ```javascript -const { BasicTrainPlanner, Units } = require('plannerjs'); +const { FlexibleTransitPlanner, Units } = require('plannerjs'); // or -import { BasicTrainPlanner, Units } from 'plannerjs'; +import { FlexibleTransitPlanner, Units } from 'plannerjs'; ``` Use it in both environments: ```javascript -const planner = new BasicTrainPlanner(); +const planner = new FlexibleTransitPlanner(); +planner.addConnectionSource("https://graph.irail.be/sncb/connections"); +planner.addStopSource("https://irail.be/stations/NMBS"); planner.query({ from: "http://irail.be/stations/NMBS/008812005", // Brussels North From de663c082ff33574346aab9db30907c80619b65b Mon Sep 17 00:00:00 2001 From: Harm Delva Date: Wed, 22 Jan 2020 17:53:30 +0100 Subject: [PATCH 18/18] Update demo --- docs/js/example.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/js/example.js b/docs/js/example.js index 820ac4d7..ec9f7e6e 100644 --- a/docs/js/example.js +++ b/docs/js/example.js @@ -12,7 +12,9 @@ L.tileLayer( } ).addTo(map); -const planner = new PlannerJS.DelijnNmbsPlanner(); +const planner = new PlannerJS.FlexibleTransitPlanner(); +planner.addConnectionSource("https://graph.irail.be/sncb/connections"); +planner.addStopSource("https://irail.be/stations/NMBS"); planner.prefetchStops(); planner.prefetchConnections(new Date(), new Date(new Date().getTime() + 2 * 60 * 60 * 1000));