diff --git a/src/repositoryDataLoader.ts b/src/repositoryDataLoader.ts index 31e3329..0709227 100644 --- a/src/repositoryDataLoader.ts +++ b/src/repositoryDataLoader.ts @@ -1,9 +1,13 @@ -import { IRoute, IShuttle, ISystem, Repository } from "./repository"; +import { IOrderedStop, IRoute, IShuttle, IStop, ISystem, Repository } from "./repository"; const timeout = 10000; -const systemIdsToSupport = ["263", "3215"]; +const systemIdsToSupport = ["263"]; const baseUrl = "https://passiogo.com/mapGetData.php"; +// Ideas to break this into smaller pieces in the future: +// Have one repository data loader running for each supported system +// Each data loader independently updates data based on frequency of usage + export class RepositoryDataLoader { private shouldBeRunning: boolean = false; @@ -31,8 +35,8 @@ export class RepositoryDataLoader { try { await this.fetchAndUpdateSystemData(); await this.fetchAndUpdateRouteDataForExistingSystems(); - await this.fetchAndUpdateStopAndPolylineDataForRoutes(); - await this.fetchAndUpdateShuttleDataForSystems(); + await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems(); + await this.fetchAndUpdateShuttleDataForExistingSystems(); await this.fetchAndUpdateEtaData(); } catch (e) { console.error(e); @@ -103,11 +107,36 @@ export class RepositoryDataLoader { })); } - private async fetchAndUpdateStopAndPolylineDataForRoutes() { + private async fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems() { + // Fetch from the API + // Pass JSON output into two different methods to update repository + const systems = await this.repository.getSystems(); + await Promise.all(systems.map(async (system: any) => { + const params = { + getStops: "2", + }; + const formDataJsonObject = { + "s0": "263", + "sA": 1 + }; + const formData = new FormData(); + formData.set("json", JSON.stringify(formDataJsonObject)); + + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${baseUrl}?${query}`, { + method: "POST", + body: formData, + }); + const json = await response.json(); + + await this.updateStopDataForSystemAndApiResponse(system, json); + await this.updateOrderedStopDataForExistingStops(json); + await this.updatePolylineDataForExistingRoutesAndApiResponse(json); + })); } - private async fetchAndUpdateShuttleDataForSystems() { + private async fetchAndUpdateShuttleDataForExistingSystems() { const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system: ISystem) => { const params = { @@ -155,4 +184,70 @@ export class RepositoryDataLoader { private async fetchAndUpdateEtaData() { } + + private async updateStopDataForSystemAndApiResponse(system: ISystem, json: any) { + if (json.stops) { + const jsonStops = Object.values(json.stops); + + await Promise.all(jsonStops.map(async (stop: any) => { + const constructedStop: IStop = { + name: stop.name, + id: stop.id, + systemId: system.id, + coordinates: { + latitude: parseFloat(stop.latitude), + longitude: parseFloat(stop.longitude), + }, + }; + + await this.repository.addOrUpdateStop(constructedStop); + })); + } + } + + private async updateOrderedStopDataForExistingStops(json: any) { + if (json.routes) { + await Promise.all(Object.keys(json.routes).map(async (routeId) => { + const jsonOrderedStopData: any[][] = json.routes[routeId].slice(2); + + // The API may return the same stop twice to indicate that + // the route runs in a loop + // If the API does not do this, assume the route is one-way + // To account for this, check if ordered stop already exists in repo + // If it does, write to that stop instead + + for (let index = 0; index < jsonOrderedStopData.length; index++) { + const orderedStopDataArray = jsonOrderedStopData[index]; + + const stopId = orderedStopDataArray[1]; + let constructedOrderedStop = await this.repository.getOrderedStopByRouteAndStopId(routeId, stopId) + if (constructedOrderedStop === null) { + constructedOrderedStop = { + routeId, + stopId, + }; + } + + if (index >= 1) { + constructedOrderedStop.previousStop = { + routeId, + stopId: jsonOrderedStopData[index - 1][1], + }; + } + if (index < jsonOrderedStopData.length - 1) { + constructedOrderedStop.nextStop = { + routeId, + stopId: jsonOrderedStopData[index + 1][1], + }; + } + + await this.repository.addOrUpdateOrderedStop(constructedOrderedStop); + } + })); + } + } + + private async updatePolylineDataForExistingRoutesAndApiResponse(json: any) { + + } } \ No newline at end of file