From 86777a16811fb4f246f7c7e44b7ffb5248a97ccb Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 13:25:16 -0800 Subject: [PATCH 01/31] make all loader methods public for improved testing --- src/loaders/ApiBasedRepositoryLoader.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index 964dac0..b9b9cd2 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -6,11 +6,11 @@ const baseUrl = "https://passiogo.com/mapGetData.php"; export class ApiBasedRepositoryLoader { constructor( - protected repository: GetterSetterRepository, + public repository: GetterSetterRepository, ) { } - protected async fetchAndUpdateSystemData() { + public async fetchAndUpdateSystemData() { const params = { getSystems: "2", }; @@ -32,7 +32,7 @@ export class ApiBasedRepositoryLoader { } } - protected async fetchAndUpdateRouteDataForExistingSystems() { + public async fetchAndUpdateRouteDataForExistingSystems() { const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system) => { const params = { @@ -69,7 +69,7 @@ export class ApiBasedRepositoryLoader { })); } - protected async fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems() { + public async fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems() { // Fetch from the API // Pass JSON output into two different methods to update repository const systems = await this.repository.getSystems(); @@ -98,7 +98,7 @@ export class ApiBasedRepositoryLoader { })); } - protected async fetchAndUpdateShuttleDataForExistingSystems() { + public async fetchAndUpdateShuttleDataForExistingSystems() { const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system: ISystem) => { const params = { @@ -143,7 +143,7 @@ export class ApiBasedRepositoryLoader { })); } - protected async fetchAndUpdateEtaDataForExistingOrderedStops() { + public async fetchAndUpdateEtaDataForExistingOrderedStops() { // TODO implement once I figure out how to associate ETA data with shuttles const systems = await this.repository.getSystems() @@ -181,7 +181,7 @@ export class ApiBasedRepositoryLoader { })) } - protected async updateStopDataForSystemAndApiResponse(system: ISystem, json: any) { + public async updateStopDataForSystemAndApiResponse(system: ISystem, json: any) { if (json.stops) { const jsonStops = Object.values(json.stops); @@ -201,7 +201,7 @@ export class ApiBasedRepositoryLoader { } } - protected async updateOrderedStopDataForExistingStops(json: any) { + public 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); @@ -246,7 +246,7 @@ export class ApiBasedRepositoryLoader { } } - protected async updatePolylineDataForExistingRoutesAndApiResponse(json: any) { + public async updatePolylineDataForExistingRoutesAndApiResponse(json: any) { if (json.routePoints) { await Promise.all(Object.keys(json.routePoints).map(async (routeId) => { const routePoints = json.routePoints[routeId][0]; From 0f41ff1868994e185bdf99cb9bab74c4416dc830 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 13:35:39 -0800 Subject: [PATCH 02/31] add test cases --- .../ApiBasedRepositoryLoaderTests.test.ts | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 test/loaders/ApiBasedRepositoryLoaderTests.test.ts diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts new file mode 100644 index 0000000..f14a794 --- /dev/null +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -0,0 +1,80 @@ +import { beforeEach, describe, it, jest, test } from "@jest/globals"; +import { ApiBasedRepositoryLoader } from "../../src/loaders/ApiBasedRepositoryLoader"; +import { UnoptimizedInMemoryRepository } from "../../src/repositories/UnoptimizedInMemoryRepository"; + +function updateGlobalFetchMockJson(obj: any) { + // @ts-ignore + global.fetch = jest.fn(() => { + return Promise.resolve({ + json: () => Promise.resolve(obj) + }) + }) as jest.Mock; +} + +/** + * Reset the global fetch function mock's JSON to return an empty object. + * @param obj + */ +function resetGlobalFetchMockJson() { + updateGlobalFetchMockJson({}) +} + +describe("ApiBasedRepositoryLoader", () => { + let loader: ApiBasedRepositoryLoader; + + beforeEach(() => { + loader = new ApiBasedRepositoryLoader(new UnoptimizedInMemoryRepository()); + resetGlobalFetchMockJson(); + }); + + describe("fetchAndUpdateSystemData", () => { + it("updates system data in repository if response received", async () => { + + }); + + it("throws the correct error if the API response contains no data", async () => { + + }); + }); + + describe("fetchAndUpdateRouteDataForExistingSystems", () => { + it("updates route data in repository if there are systems and response received", async () => { + + }); + + it("throws the correct error if the API response contains no data", async () => { + + }); + }); + + describe("fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems", () => { + it("updates stop and polyline data if there are systems and response received", async () => { + + }); + + it("throws the correct error if the API response contains no data", async () => { + + }) + }); + + describe("fetchAndUpdateShuttleDataForExistingSystems", () => { + it("updates shuttle data in repository if there are systems and response received", async () => { + + }); + + it("throws the correct error if the API response contains no data", async () => { + + }); + }); + + describe("fetchAndUpdateEtaDataForExistingSystems", () => { + it("updates shuttle data in repository if there are systems and response received", async () => { + + }); + + it("throws the correct error if the API response contains no data", async () => { + + }); + }); +}); + From e4b4683b60e185942d36d5552bb5daa44df1e98a Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 13:41:17 -0800 Subject: [PATCH 03/31] change update helper methods back to protected --- src/loaders/ApiBasedRepositoryLoader.ts | 8 +++----- test/jsonSnapshots/getAllSystemsResponse.ts | 0 2 files changed, 3 insertions(+), 5 deletions(-) create mode 100644 test/jsonSnapshots/getAllSystemsResponse.ts diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index b9b9cd2..145639a 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -144,8 +144,6 @@ export class ApiBasedRepositoryLoader { } public async fetchAndUpdateEtaDataForExistingOrderedStops() { - // TODO implement once I figure out how to associate ETA data with shuttles - const systems = await this.repository.getSystems() await Promise.all(systems.map(async (system: ISystem) => { const stops = await this.repository.getStopsBySystemId(system.id); @@ -181,7 +179,7 @@ export class ApiBasedRepositoryLoader { })) } - public async updateStopDataForSystemAndApiResponse(system: ISystem, json: any) { + protected async updateStopDataForSystemAndApiResponse(system: ISystem, json: any) { if (json.stops) { const jsonStops = Object.values(json.stops); @@ -201,7 +199,7 @@ export class ApiBasedRepositoryLoader { } } - public async updateOrderedStopDataForExistingStops(json: any) { + protected 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); @@ -246,7 +244,7 @@ export class ApiBasedRepositoryLoader { } } - public async updatePolylineDataForExistingRoutesAndApiResponse(json: any) { + protected async updatePolylineDataForExistingRoutesAndApiResponse(json: any) { if (json.routePoints) { await Promise.all(Object.keys(json.routePoints).map(async (routeId) => { const routePoints = json.routePoints[routeId][0]; diff --git a/test/jsonSnapshots/getAllSystemsResponse.ts b/test/jsonSnapshots/getAllSystemsResponse.ts new file mode 100644 index 0000000..e69de29 From 4dd8b450a0700d4581d4a3be1d90c6f6e2d42bb4 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 13:43:37 -0800 Subject: [PATCH 04/31] move baseUrl and supported system ids to class level --- src/loaders/ApiBasedRepositoryLoader.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index 145639a..01e9cec 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -1,10 +1,10 @@ import { GetterSetterRepository } from "../repositories/GetterSetterRepository"; import { IEta, IRoute, IShuttle, IStop, ISystem } from "../entities/entities"; -const systemIdsToSupport = ["263"]; -const baseUrl = "https://passiogo.com/mapGetData.php"; - export class ApiBasedRepositoryLoader { + readonly supportedSystemIds = ["263"]; + readonly baseUrl = "https://passiogo.com/mapGetData.php"; + constructor( public repository: GetterSetterRepository, ) { @@ -15,12 +15,12 @@ export class ApiBasedRepositoryLoader { getSystems: "2", }; const query = new URLSearchParams(params).toString(); - const response = await fetch(`${baseUrl}?${query}`); + const response = await fetch(`${this.baseUrl}?${query}`); const json = await response.json() if (typeof json.all === "object") { // filter down to supported systems - const filteredSystems = json.all.filter((jsonSystem: any) => systemIdsToSupport.includes(jsonSystem.id)); + const filteredSystems = json.all.filter((jsonSystem: any) => this.supportedSystemIds.includes(jsonSystem.id)); await Promise.all(filteredSystems.map(async (system: any) => { const constructedSystem: ISystem = { id: system.id, @@ -47,7 +47,7 @@ export class ApiBasedRepositoryLoader { formData.set("json", JSON.stringify(formDataJsonObject)); const query = new URLSearchParams(params).toString(); - const response = await fetch(`${baseUrl}?${query}`, { + const response = await fetch(`${this.baseUrl}?${query}`, { method: "POST", body: formData, }); @@ -86,7 +86,7 @@ export class ApiBasedRepositoryLoader { formData.set("json", JSON.stringify(formDataJsonObject)); const query = new URLSearchParams(params).toString(); - const response = await fetch(`${baseUrl}?${query}`, { + const response = await fetch(`${this.baseUrl}?${query}`, { method: "POST", body: formData, }); @@ -114,7 +114,7 @@ export class ApiBasedRepositoryLoader { formData.set("json", JSON.stringify(formDataJsonObject)); const query = new URLSearchParams(params).toString(); - const response = await fetch(`${baseUrl}?${query}`, { + const response = await fetch(`${this.baseUrl}?${query}`, { method: "POST", body: formData, }); @@ -154,7 +154,7 @@ export class ApiBasedRepositoryLoader { }; const query = new URLSearchParams(params).toString(); - const response = await fetch(`${baseUrl}?${query}`, { + const response = await fetch(`${this.baseUrl}?${query}`, { method: "GET", }); const json = await response.json(); From 045fa3a30ac5324ad5856013a24492447fa3264a Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 13:43:53 -0800 Subject: [PATCH 05/31] add json snapshot of successful system response --- test/jsonSnapshots/getAllSystemsResponse.ts | 3350 +++++++++++++++++++ 1 file changed, 3350 insertions(+) diff --git a/test/jsonSnapshots/getAllSystemsResponse.ts b/test/jsonSnapshots/getAllSystemsResponse.ts index e69de29..f1e134c 100644 --- a/test/jsonSnapshots/getAllSystemsResponse.ts +++ b/test/jsonSnapshots/getAllSystemsResponse.ts @@ -0,0 +1,3350 @@ +export const getAllSystemsResponse = { + "all": [ + { + "fullname": "Chapman University", + "username": "chapman", + "goAgencyName": "Chapman University", + "name2": "0", + "id": "263", + "goAuthenticationType": "0", + "goParentUserId": null, + "mapApp": "1", + "goTestMode": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "distance": "0", + "latitude": "33.796601000", + "longitude": "-117.889280500", + "nearest": 1, + "mine": 1 + }, + { + "fullname": "3630 Peachtree", + "username": "peachtree", + "goAgencyName": null, + "id": "951", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "5025 Apartments", + "username": "cardinal5025", + "goAgencyName": null, + "id": "1634", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "725 Ponce", + "username": "725ponce", + "goAgencyName": null, + "id": "1832", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Agnes Scott College", + "username": "ascott", + "goAgencyName": null, + "id": "1471", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Alabama A&M University", + "username": "aamu", + "goAgencyName": "Alabama A&M University", + "id": "2456", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Albany State University ", + "username": "asurams", + "goAgencyName": "Albany State University ", + "id": "5213", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#393b79", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Anne Arundel County Office of Transportation", + "username": "AnneC", + "goAgencyName": null, + "id": "3469", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Atlantic Station", + "username": "atlcarpark", + "goAgencyName": "Atlantic Station", + "id": "4349", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "AUC", + "username": "rwwl", + "goAgencyName": "AUC", + "id": "67", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "shuttle@auctr.edu", + "goAuthenticationType": "0", + "email": "shuttle@auctr.edu" + }, + { + "fullname": "Audible", + "username": "Audible", + "goAgencyName": null, + "id": "876", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Augusta University", + "username": "gru", + "goAgencyName": null, + "id": "553", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "parkingoffice@augusta.edu", + "goAuthenticationType": "0", + "email": "parkingoffice@augusta.edu" + }, + { + "fullname": "Bayonne Bay", + "username": "bayonne", + "goAgencyName": null, + "id": "1808", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Beacon College", + "username": "BeaconCollege11", + "goAgencyName": null, + "id": "3389", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Beacon Shuttle", + "username": "beaconprop", + "goAgencyName": "Beacon Shuttle", + "id": "3561", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Beloit Transit", + "username": "beloit", + "goAgencyName": null, + "id": "3655", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Bis-Man Transit", + "username": "bisman", + "goAgencyName": "Bis-Man Transit", + "id": "4121", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#2ca02c", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "BLT (Propark)", + "username": "buildingland", + "goAgencyName": null, + "id": "4940", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Boise Airport (The Car Park)", + "username": "boiseairport", + "goAgencyName": "Boise Airport (The Car Park)", + "id": "5366", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Bowie State University", + "username": "bowie", + "goAgencyName": null, + "id": "3001", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiotech.com", + "goAuthenticationType": "0", + "email": "support@passiotech.com" + }, + { + "fullname": "Brockton Area Transit Authority (BAT)", + "username": "brockton", + "goAgencyName": null, + "id": "2046", + "goTestMode": "1", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Brown University ", + "username": "brown", + "goAgencyName": "Brown University ", + "id": "1067", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Bull Runner at USF", + "username": "usf", + "goAgencyName": "Bull Runner at USF", + "id": "2343", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#006747", + "goSupportEmail": "bullrunner@usf.edu", + "goAuthenticationType": "0", + "email": "bullrunner@usf.edu" + }, + { + "fullname": "Cal State San Bernardino", + "username": "sundiego", + "goAgencyName": null, + "id": "1187", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Calabasas Transit", + "username": "calabasas", + "goAgencyName": null, + "id": "5211", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Canby Area Transit", + "username": "canbyTransit", + "goAgencyName": null, + "id": "3274", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "cat@canbyoregon.gov", + "goAuthenticationType": "0", + "email": "cat@canbyoregon.gov" + }, + { + "fullname": "Cascades East Transit", + "username": "cet", + "goAgencyName": "Cascades East Transit", + "id": "2460", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "abreault@coic.org", + "goAuthenticationType": "0", + "email": "abreault@coic.org" + }, + { + "fullname": "Casper Area Transit", + "username": "casper", + "goAgencyName": "Casper Area Transit", + "id": "4055", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Century Village (FT)", + "username": "century", + "goAgencyName": null, + "id": "444", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Chapman University", + "username": "chapman", + "goAgencyName": "Chapman University", + "id": "263", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Charles River TMA", + "username": "charlesriver", + "goAgencyName": "Charles River TMA", + "id": "5019", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Charleston Airport REEF", + "username": "charlestonairport", + "goAgencyName": "Charleston Airport REEF", + "id": "4749", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Charm City Circulator", + "username": "charmcity", + "goAgencyName": "Charm City Circulator", + "id": "3554", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Chemung County (C-Tran)", + "username": "chemung", + "goAgencyName": "Chemung County (C-Tran)", + "id": "4009", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#000080", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "CHOA", + "username": "choa", + "goAgencyName": "CHOA", + "id": "3489", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Citrus Connection", + "username": "citrusconn", + "goAgencyName": null, + "id": "1752", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Arcadia", + "username": "ArcadiaCity", + "goAgencyName": null, + "id": "3304", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#2ca02c", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Bangor", + "username": "bangor", + "goAgencyName": "City of Bangor", + "id": "4631", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Billings MET Transit", + "username": "billings", + "goAgencyName": "City of Billings MET Transit", + "id": "3901", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#2ca02c", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Cerritos", + "username": "cerritos", + "goAgencyName": null, + "id": "2282", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Clovis", + "username": "clovis", + "goAgencyName": "City of Clovis", + "id": "3743", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#8c564b", + "goSupportEmail": "clovistransit@cityofclovis.com", + "goAuthenticationType": "0", + "email": "clovistransit@cityofclovis.com" + }, + { + "fullname": "City of Detroit - Employee Shuttle", + "username": "detroitemp", + "goAgencyName": "City of Detroit - Employee Shuttle", + "id": "1275", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Harrisonburg Department of Public Transportation (HDPT)", + "username": "harrisonburg", + "goAgencyName": null, + "id": "2868", + "goTestMode": "1", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Hoboken", + "username": "hoboken", + "goAgencyName": "City of Hoboken", + "id": "466", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Irvine", + "username": "irvine", + "goAgencyName": "City of Irvine", + "id": "4502", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#17becf", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Jackson (JTRAN)", + "username": "jtran", + "goAgencyName": null, + "id": "3363", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Jacksonville", + "username": "jacksonville", + "goAgencyName": null, + "id": "3521", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Monterey Park", + "username": "montereyp", + "goAgencyName": null, + "id": "3215", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Newport Beach (Balboa Peninsula Trolley)", + "username": "newportbeach", + "goAgencyName": "City of Newport Beach (Balboa Peninsula Trolley)", + "id": "4883", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#bdbdbd", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Olean", + "username": "oats", + "goAgencyName": null, + "id": "2084", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Passaic UEZ Shuttle (Propark)", + "username": "passaic", + "goAgencyName": "City of Passaic UEZ Shuttle (Propark)", + "id": "5730", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Rosemead", + "username": "rosemead", + "goAgencyName": null, + "id": "3670", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Sandy", + "username": "sandyor", + "goAgencyName": null, + "id": "3183", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "City of Tracy (MTM / Tracer Transit)", + "username": "CityofTracy", + "goAgencyName": null, + "id": "2996", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "City of Tyler", + "username": "tylertx", + "goAgencyName": "City of Tyler", + "id": "3777", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "tylertransit@tylertexas.com", + "goAuthenticationType": "0", + "email": "tylertransit@tylertexas.com" + }, + { + "fullname": "City of Watertown (CitiBus)", + "username": "watertown", + "goAgencyName": "City of Watertown (CitiBus)", + "id": "2775", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Citylink Edmond", + "username": "edmond", + "goAgencyName": "Citylink Edmond", + "id": "4662", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#6baed6", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "2", + "email": "support@passiogo.com" + }, + { + "fullname": "Citylink North (Kootenai County)", + "username": "kootenai", + "goAgencyName": "Citylink North (Kootenai County)", + "id": "2016", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Citylink South", + "username": "citylinkrural", + "goAgencyName": "Citylink South", + "id": "2059", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Clackamas County", + "username": "clackamas", + "goAgencyName": null, + "id": "3205", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Clemson Tiger Transit", + "username": "Clemson2", + "goAgencyName": "Clemson Tiger Transit", + "id": "1654", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Clemson University", + "username": "ClemsonU", + "goAgencyName": null, + "id": "793", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Cleveland Urban Area Transit System (CUATS)", + "username": "cuats", + "goAgencyName": "Cleveland Urban Area Transit System (CUATS)", + "id": "4836", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#17becf", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Coca Cola", + "username": "coke", + "goAgencyName": null, + "id": "416", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#fe001a", + "goSupportEmail": "gboothe@lanierparking.com", + "goAuthenticationType": "0", + "email": "gboothe@lanierparking.com" + }, + { + "fullname": "Colby College", + "username": "security@colby.edu", + "goAgencyName": null, + "id": "3377", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#002169", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Columbia University", + "username": "columbia", + "goAgencyName": null, + "id": "74", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "transportation@columbia.edu", + "goAuthenticationType": "0", + "email": "transportation@columbia.edu" + }, + { + "fullname": "Concho Valley Transit", + "username": "conchoVT", + "goAgencyName": null, + "id": "3281", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Concord Kannapolis Area Transit", + "username": "concordKat", + "goAgencyName": "Concord Kannapolis Area Transit", + "id": "4124", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "support@ckrider.com", + "goAuthenticationType": "0", + "email": "support@ckrider.com" + }, + { + "fullname": "Concourse", + "username": "Concourse", + "goAgencyName": null, + "id": "1841", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Connect Douglas", + "username": "douglas", + "goAgencyName": null, + "id": "1661", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "connectdouglas@co.douglas.ga.us", + "goAuthenticationType": "0", + "email": "connectdouglas@co.douglas.ga.us" + }, + { + "fullname": "Connecticut Children's Medical Center (Propark)", + "username": "ccmc", + "goAgencyName": "Connecticut Children's Medical Center (Propark)", + "id": "5387", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#d62728", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Cooperative Alliance for Seacoast Transportation (COAST)", + "username": "coast", + "goAgencyName": null, + "id": "2962", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Coos County Area Transit", + "username": "cooscounty", + "goAgencyName": "Coos County Area Transit", + "id": "4835", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#3182bd", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "2", + "email": "support@passiogo.com" + }, + { + "fullname": "Coral Gables", + "username": "cgables", + "goAgencyName": null, + "id": "2787", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "County Connector", + "username": "countyconn", + "goAgencyName": "County Connector", + "id": "2933", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "countyconnector", + "goAuthenticationType": "0", + "email": "countyconnector" + }, + { + "fullname": "CSULB", + "username": "longbeachcal", + "goAgencyName": "CSULB", + "id": "4163", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#eba91b", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Disney Programs", + "username": "disneyw", + "goAgencyName": "Disney Programs", + "id": "2208", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "District of Chamblee", + "username": "reefdoc", + "goAgencyName": null, + "id": "1897", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Drury Plaza Hotel - Disney Springs", + "username": "druryhoteldisney", + "goAgencyName": "Drury Plaza Hotel - Disney Springs", + "id": "4748", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#800000", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Eastern Kentucky University", + "username": "easternken", + "goAgencyName": null, + "id": "3828", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "parking@eku.edu", + "goAuthenticationType": "0", + "email": "parking@eku.edu" + }, + { + "fullname": "Eastern Panhandle Transit Authority (EPTA)", + "username": "epta", + "goAgencyName": null, + "id": "1298", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Eastern Virginia Medical School", + "username": "EVMS", + "goAgencyName": null, + "id": "591", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f7f9b", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Elon University", + "username": "elonedu", + "goAgencyName": null, + "id": "3045", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "bswift3@elon.edu", + "goAuthenticationType": "0", + "email": "bswift3@elon.edu" + }, + { + "fullname": "Emory University", + "username": "Emoryuni", + "goAgencyName": "Emory University", + "id": "4432", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#012169", + "goSupportEmail": "commute@emory.edu", + "goAuthenticationType": "0", + "email": "commute@emory.edu" + }, + { + "fullname": "Endicott College", + "username": "endicott", + "goAgencyName": "Endicott College", + "id": "2873", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#111680", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "ES Atlanta", + "username": "epsteins", + "goAgencyName": "ES Atlanta", + "id": "2280", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Escambia County Area Transit (ECAT)", + "username": "ecat", + "goAgencyName": "Escambia County Area Transit (ECAT)", + "id": "2283", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#31a354", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "ETHRA", + "username": "ethra", + "goAgencyName": "ETHRA", + "id": "4583", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "EWR Employee Shuttle", + "username": "uniteda", + "goAgencyName": "EWR Employee Shuttle", + "id": "2989", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiotech.com", + "goAuthenticationType": "0", + "email": "support@passiotech.com" + }, + { + "fullname": "EWR Port Authority NYNJ", + "username": "ewrpanynj", + "goAgencyName": null, + "id": "2496", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "FIT NY", + "username": "fitnewyork", + "goAgencyName": null, + "id": "973", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Florham Park (Sun Valley/River Bend)", + "username": "fpark", + "goAgencyName": "Florham Park (Sun Valley/River Bend)", + "id": "2311", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Florida Gulf Coast University (FGCU)", + "username": "fgcu", + "goAgencyName": "Florida Gulf Coast University (FGCU)", + "id": "2281", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#004785", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Florida International University", + "username": "floridaint", + "goAgencyName": "Florida International University", + "id": "4119", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#000080", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Fort Saskatchewan Transit (PWTransit Canada Ltd.)", + "username": "fortsask", + "goAgencyName": null, + "id": "912", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Four Points Sheraton (Propark)", + "username": "4PointsFlushing", + "goAgencyName": "Four Points Sheraton (Propark)", + "id": "5208", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Franklin Regional Transit Authority", + "username": "frta", + "goAgencyName": "Franklin Regional Transit Authority", + "id": "2771", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Franklin Transit", + "username": "franklint", + "goAgencyName": null, + "id": "1652", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#0033A0", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Fresh Direct (Pro Park)", + "username": "freshdirect", + "goAgencyName": "Fresh Direct (Pro Park)", + "id": "4691", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Fresno State University", + "username": "fresno", + "goAgencyName": null, + "id": "805", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "GatewayJFK Connection", + "username": "gatewayjfk", + "goAgencyName": "GatewayJFK Connection", + "id": "2125", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#0694E2", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "George Washington University (GW)", + "username": "georgewashu", + "goAgencyName": "George Washington University (GW)", + "id": "4120", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#1f77b4", + "goSupportEmail": "tve@gwu.edu", + "goAuthenticationType": "0", + "email": "tve@gwu.edu" + }, + { + "fullname": "Georgia College & State University (GCSU)", + "username": "gcsu", + "goAgencyName": "Georgia College & State University (GCSU)", + "id": "895", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#245745", + "goSupportEmail": "support@passiotech.com", + "goAuthenticationType": "0", + "email": "support@passiotech.com" + }, + { + "fullname": "Georgia Southern University", + "username": "GASO", + "goAgencyName": null, + "id": "137", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Georgia State University", + "username": "georgiast", + "goAgencyName": "Georgia State University", + "id": "480", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1a5dad", + "goSupportEmail": "auxiliary@gsu.edu", + "goAuthenticationType": "0", + "email": "auxiliary@gsu.edu" + }, + { + "fullname": "Georgia Tech", + "username": "gatech", + "goAgencyName": "Georgia Tech", + "id": "76", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#003057", + "goSupportEmail": "aaron.fowler@gatech.edu", + "goAuthenticationType": "0", + "email": "aaron.fowler@gatech.edu" + }, + { + "fullname": "GoBus", + "username": "miller", + "goAgencyName": "GoBus", + "id": "1839", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Harbortown (Atlantic Realty)", + "username": "harbortown", + "goAgencyName": "Harbortown (Atlantic Realty)", + "id": "4686", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Harford County", + "username": "harford", + "goAgencyName": "Harford County", + "id": "4620", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#3182bd", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Harris County Transit", + "username": "harrisco", + "goAgencyName": "Harris County Transit", + "id": "3497", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#393b79", + "goSupportEmail": "transit@csd.hctx.net", + "goAuthenticationType": "0", + "email": "transit@csd.hctx.net" + }, + { + "fullname": "HARTransit", + "username": "hart", + "goAgencyName": null, + "id": "2250", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "www.hartransit.com", + "goAuthenticationType": "0", + "email": "www.hartransit.com" + }, + { + "fullname": "Harvard University", + "username": "harvard", + "goAgencyName": null, + "id": "831", + "goTestMode": "1", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#A51C30", + "goSupportEmail": "", + "goAuthenticationType": "0" + }, + { + "fullname": "Hendry County Transit System", + "username": "hendrycounty", + "goAgencyName": null, + "id": "2217", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Highland Hospital Metropolis", + "username": "highlandhos", + "goAgencyName": null, + "id": "3829", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "rjeangilles@metropolis.io", + "goAuthenticationType": "0", + "email": "rjeangilles@metropolis.io" + }, + { + "fullname": "Hill Place Apartments", + "username": "hillplace", + "goAgencyName": "Hill Place Apartments", + "id": "1092", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Hollins University", + "username": "hollinsshuttle", + "goAgencyName": null, + "id": "3014", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "hello@goridesource.com", + "goAuthenticationType": "0", + "email": "hello@goridesource.com" + }, + { + "fullname": "Hotel Indigo Flushing", + "username": "indigoflushing", + "goAgencyName": "Hotel Indigo Flushing", + "id": "5525", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#9467bd", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Houston Airport (SP+)", + "username": "houstonairport", + "goAgencyName": "Houston Airport (SP+)", + "id": "4919", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Hutch Metro Center", + "username": "simonedev", + "goAgencyName": null, + "id": "1569", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Interurban Trolley", + "username": "macog", + "goAgencyName": "Interurban Trolley", + "id": "3639", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#355e3b", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Jasper Transit", + "username": "jaspercan", + "goAgencyName": "Jasper Transit", + "id": "4294", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "JAX Mass Transit", + "username": "JCMTD", + "goAgencyName": "JAX Mass Transit", + "id": "5153", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#081e3f", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "JFK LGA Shuttles", + "username": "jfkpanynj", + "goAgencyName": "JFK LGA Shuttles", + "id": "2494", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "JPS Health Network", + "username": "jpshealth", + "goAgencyName": null, + "id": "5158", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Kennesaw State University", + "username": "kennesaw", + "goAgencyName": "Kennesaw State University", + "id": "66", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "talonone@kennesaw.edu", + "goAuthenticationType": "0", + "email": "talonone@kennesaw.edu" + }, + { + "fullname": "Kentucky River Foothills", + "username": "kfoothills", + "goAgencyName": null, + "id": "3630", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Key West Transit", + "username": "keywest", + "goAgencyName": "Key West Transit", + "id": "4440", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#b5cf6b", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Lawrence Transit", + "username": "lawrencetransit", + "goAgencyName": "Lawrence Transit", + "id": "4834", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#000435", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Lehigh University", + "username": "lehigh", + "goAgencyName": "Lehigh University", + "id": "1090", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#653818", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Lewiston Transit & Asotin County Transit", + "username": "lewiston", + "goAgencyName": "Lewiston Transit & Asotin County Transit", + "id": "4939", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#000435", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Long Island University", + "username": "longislanduni", + "goAgencyName": "Long Island University", + "id": "5082", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Los Angeles International Airport (LAX)", + "username": "lax", + "goAgencyName": null, + "id": "1421", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Marymount University", + "username": "marymount", + "goAgencyName": "Marymount University", + "id": "4716", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#2C3287", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Mayaguez (Skytec)", + "username": "puertoricotec", + "goAgencyName": null, + "id": "3206", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "McAfee Knob Trailhead (Ridesource)", + "username": "mktrail", + "goAgencyName": null, + "id": "3069", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Mercy University", + "username": "mercy", + "goAgencyName": "Mercy University", + "id": "694", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#DFDEDE", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Metropolis Parking (Anschutz Campus)", + "username": "MetroParking", + "goAgencyName": null, + "id": "3282", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Missouri State University", + "username": "mizzst", + "goAgencyName": null, + "id": "459", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "MIT", + "username": "mit", + "goAgencyName": null, + "id": "94", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "shuttles@mit.edu", + "goAuthenticationType": "0", + "email": "shuttles@mit.edu" + }, + { + "fullname": "Montachusett Regional Transit Authority (MART)", + "username": "montachusett", + "goAgencyName": null, + "id": "2173", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "contactmart@mrta.us", + "goAuthenticationType": "0", + "email": "contactmart@mrta.us" + }, + { + "fullname": "Montana State University", + "username": "montana", + "goAgencyName": "Montana State University", + "id": "5210", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#162960", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "National Cancer Institute", + "username": "NCI", + "goAgencyName": "National Cancer Institute", + "id": "3293", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Naval Base San Diego", + "username": "navysandiego", + "goAgencyName": "Naval Base San Diego", + "id": "5477", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "NC State University", + "username": "ncstateuni", + "goAgencyName": "NC State University", + "id": "3827", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#d62728", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "New Hanover County Airport", + "username": "nhcairport", + "goAgencyName": "New Hanover County Airport", + "id": "5596", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "New River Transit Authority", + "username": "beckley", + "goAgencyName": "New River Transit Authority", + "id": "3362", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "New York University", + "username": "newyork", + "goAgencyName": "New York University", + "id": "1007", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "North Carolina A&T State University", + "username": "ncat", + "goAgencyName": "North Carolina A&T State University", + "id": "261", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "North Fork Area Transit", + "username": "northfork", + "goAgencyName": "North Fork Area Transit", + "id": "2587", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#470a68", + "goSupportEmail": "director@northforkareatransit.com", + "goAuthenticationType": "0", + "email": "director@northforkareatransit.com" + }, + { + "fullname": "NYU Langone Long Island Security", + "username": "nyulangone", + "goAgencyName": null, + "id": "5455", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Orlando International Airport", + "username": "orlandoaviation", + "goAgencyName": "Orlando International Airport", + "id": "4692", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Otter Bus (Ridesource)", + "username": "otterbus", + "goAgencyName": null, + "id": "3015", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "hello@goridesource.com", + "goAuthenticationType": "0", + "email": "hello@goridesource.com" + }, + { + "fullname": "Ozark Regional Transit", + "username": "ozark", + "goAgencyName": "Ozark Regional Transit", + "id": "1589", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "", + "goAuthenticationType": "0" + }, + { + "fullname": "Palm Beach International Airport Parking Shuttle", + "username": "wpbair", + "goAgencyName": "Palm Beach International Airport Parking Shuttle", + "id": "1071", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Pepperdine University", + "username": "pepperdine", + "goAgencyName": null, + "id": "3593", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "transit.services@pepperdine.edu", + "goAuthenticationType": "0", + "email": "transit.services@pepperdine.edu" + }, + { + "fullname": "Perimeter Summit Shuttle", + "username": "cbreperimeter", + "goAgencyName": null, + "id": "5214", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Pittsburgh International Airport (PIT)", + "username": "pittair", + "goAgencyName": null, + "id": "3200", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Port of Galveston", + "username": "Port775", + "goAgencyName": "Port of Galveston", + "id": "3294", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Portage Area Regional Transit Authority (PARTA)", + "username": "parta", + "goAgencyName": null, + "id": "3420", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Providence College", + "username": "providence", + "goAgencyName": "Providence College", + "id": "4147", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#000000", + "goSupportEmail": "pcshuttles@valetparkofamerica.com", + "goAuthenticationType": "0", + "email": "pcshuttles@valetparkofamerica.com" + }, + { + "fullname": "Quinnipiac University", + "username": "quinnUni", + "goAgencyName": "Quinnipiac University", + "id": "3899", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#0C2340", + "goSupportEmail": "qushuttles@valetparkofamerica.com", + "goAuthenticationType": "0", + "email": "qushuttles@valetparkofamerica.com" + }, + { + "fullname": "Radford Transit", + "username": "radford", + "goAgencyName": null, + "id": "1248", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#e41c39", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Ravinia Shuttle", + "username": "raviniabus", + "goAgencyName": "Ravinia Shuttle", + "id": "5231", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Rivendell Properties", + "username": "rivendell", + "goAgencyName": "Rivendell Properties", + "id": "5409", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#2ca02c", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "River Valley Transit", + "username": "9town", + "goAgencyName": "River Valley Transit", + "id": "1726", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#000000", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "River Valley Transit", + "username": "user4d5b", + "goAgencyName": "River Valley Transit", + "id": "5168", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#2ca02c", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Roadrunner Transit", + "username": "roadrunner", + "goAgencyName": "Roadrunner Transit", + "id": "4010", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#17becf", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Rochester Institute of Technology (RIT)", + "username": "ritech", + "goAgencyName": "Rochester Institute of Technology (RIT)", + "id": "4006", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#ff7f0e", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Roger Williams University", + "username": "rogerwu", + "goAgencyName": null, + "id": "1850", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Rural Transit / Beyond the Borders / ATS", + "username": "atstrans", + "goAgencyName": "Rural Transit / Beyond the Borders / ATS", + "id": "4820", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "2", + "email": "support@passiogo.com" + }, + { + "fullname": "Rutgers University", + "username": "rutgers", + "goAgencyName": "Rutgers University", + "id": "1268", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#CC0033", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "2", + "email": "support@passiogo.com" + }, + { + "fullname": "Sacramento Airport Park & Ride", + "username": "sacair", + "goAgencyName": "Sacramento Airport Park & Ride", + "id": "898", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Saint Peter's University", + "username": "spuniv", + "goAgencyName": null, + "id": "493", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiotech.com", + "goAuthenticationType": "0", + "email": "support@passiotech.com" + }, + { + "fullname": "Sales Demo - SR", + "username": "user0701", + "goAgencyName": null, + "id": "5047", + "goTestMode": "1", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "SAT Parking", + "username": "satparking", + "goAgencyName": "SAT Parking", + "id": "5479", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#2ca02c", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "SCAD Atlanta", + "username": "scadatlanta", + "goAgencyName": "SCAD Atlanta", + "id": "5306", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#000000", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "2", + "email": "support@passiogo.com" + }, + { + "fullname": "SCAD Savannah", + "username": "scadsavannah", + "goAgencyName": "SCAD Savannah", + "id": "5305", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#000000", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "2", + "email": "support@passiogo.com" + }, + { + "fullname": "Selkirks-Pend Oreille Transit Authority (SPOT Bus)", + "username": "spotbus", + "goAgencyName": null, + "id": "5698", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Seneca Transit System", + "username": "senecanation", + "goAgencyName": "Seneca Transit System", + "id": "2035", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Sioux City Transit", + "username": "siouxcity", + "goAgencyName": "Sioux City Transit", + "id": "4832", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "SMART Transit", + "username": "smart", + "goAgencyName": "SMART Transit", + "id": "4476", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "SMU", + "username": "smu", + "goAgencyName": "SMU", + "id": "5155", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#354CA1", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Somerset County Transportation", + "username": "somerset", + "goAgencyName": "Somerset County Transportation", + "id": "5160", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#9edae5", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "South Clackamas Transportation District", + "username": "sclackamas", + "goAgencyName": "South Clackamas Transportation District", + "id": "4233", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Southeastern Louisiana University", + "username": "sela", + "goAgencyName": null, + "id": "186", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "parking@southeastern.edu", + "goAuthenticationType": "0", + "email": "parking@southeastern.edu" + }, + { + "fullname": "Southern Connecticut State University", + "username": "scsu", + "goAgencyName": null, + "id": "431", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiotech.com", + "goAuthenticationType": "0", + "email": "support@passiotech.com" + }, + { + "fullname": "St. Lawrence County Public Transit", + "username": "stlawrence", + "goAgencyName": "St. Lawrence County Public Transit", + "id": "4234", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": "#637939", + "goSupportEmail": "info@slcnypublictransit.com", + "goAuthenticationType": "0", + "email": "info@slcnypublictransit.com" + }, + { + "fullname": "St. Vincent's (Pinnacle Transportation Group)", + "username": "stvincent", + "goAgencyName": null, + "id": "2561", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "State Shuttle (Onyx Equities)", + "username": "onyx", + "goAgencyName": null, + "id": "2780", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "STC Atlanta Georgia", + "username": "chickfila", + "goAgencyName": "STC Atlanta Georgia", + "id": "2197", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Stevens Point - Central Transportation", + "username": "centraltrans", + "goAgencyName": "Stevens Point - Central Transportation", + "id": "2556", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "1", + "goColor": "#1f77b4", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Tennessee Technological University", + "username": "tntech", + "goAgencyName": null, + "id": "1736", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Terraces (Pinnacle Transportation Group)", + "username": "Terraces", + "goAgencyName": null, + "id": "3270", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Texas Medical Center", + "username": "txmedctr", + "goAgencyName": "Texas Medical Center", + "id": "5595", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#d62728", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Texas State University ", + "username": "bobcatshuttle", + "goAgencyName": "Texas State University ", + "id": "5078", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#501214", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "The Concord Trolley", + "username": "concordtrolley", + "goAgencyName": null, + "id": "3089", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "The Cottages at Lake Tamaha Tuscaloosa", + "username": "retreatlt", + "goAgencyName": null, + "id": "1093", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "The Galleria (Reef Parking)", + "username": "galleria", + "goAgencyName": null, + "id": "1900", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "The Hartford", + "username": "hartford", + "goAgencyName": "The Hartford", + "id": "4581", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#d62728", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "The U Apartments Raleigh", + "username": "cardgroup", + "goAgencyName": null, + "id": "1650", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Township of West Orange", + "username": "westorange", + "goAgencyName": null, + "id": "3166", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#2ca02c", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Towson Loop (Baltimore County)", + "username": "towson", + "goAgencyName": null, + "id": "2153", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Transpo", + "username": "transpo", + "goAgencyName": "Transpo", + "id": "3490", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Tulane University", + "username": "tulaneshuttles", + "goAgencyName": null, + "id": "353", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "shuttles@tulane.edu", + "goAuthenticationType": "0", + "email": "shuttles@tulane.edu" + }, + { + "fullname": "Tuscaloosa Transit Authority", + "username": "tuscaloosatransit", + "goAgencyName": "Tuscaloosa Transit Authority", + "id": "3817", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#d62728", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "UARK (University of Arkansas)", + "username": "UofArkansas", + "goAgencyName": "UARK (University of Arkansas)", + "id": "3778", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "UB Shuttle", + "username": "univbuffalo", + "goAgencyName": "UB Shuttle", + "id": "5230", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#005bbb", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "UB Stampede", + "username": "ubuffalo", + "goAgencyName": "UB Stampede", + "id": "4882", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#005bbb", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "UCONN/WRTD", + "username": "uconn", + "goAgencyName": "UCONN/WRTD", + "id": "1541", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#202A44", + "goSupportEmail": "support@passiotech.com", + "goAuthenticationType": "0", + "email": "support@passiotech.com" + }, + { + "fullname": "UNC Charlotte", + "username": "uncc", + "goAgencyName": "UNC Charlotte", + "id": "1053", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#005035", + "goSupportEmail": "scott@passiotech.com", + "goAuthenticationType": "0", + "email": "scott@passiotech.com" + }, + { + "fullname": "UNC Greensboro (UNCG)", + "username": "uncg", + "goAgencyName": null, + "id": "2874", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "UNC Wilmington", + "username": "uncw", + "goAgencyName": "UNC Wilmington", + "id": "3952", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#17becf", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "University of Alabama", + "username": "bamabama", + "goAgencyName": "University of Alabama", + "id": "240", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#af002a", + "goSupportEmail": "crimsonride@ua.edu", + "goAuthenticationType": "0", + "email": "crimsonride@ua.edu" + }, + { + "fullname": "University of Chicago", + "username": "chicago", + "goAgencyName": "University of Chicago", + "id": "1068", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#843c39", + "goSupportEmail": "bus@uchicago.edu", + "goAuthenticationType": "0", + "email": "bus@uchicago.edu" + }, + { + "fullname": "University of Florida", + "username": "UniFlorida", + "goAgencyName": "University of Florida", + "id": "3826", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "parking@ufl.edu", + "goAuthenticationType": "0", + "email": "parking@ufl.edu" + }, + { + "fullname": "University of Georgia (UGA)", + "username": "uga", + "goAgencyName": "University of Georgia (UGA)", + "id": "3994", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#d62728", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "University of Hartford", + "username": "HartfordAmerica", + "goAgencyName": "University of Hartford", + "id": "3305", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#DB1E34", + "goSupportEmail": "uhart@valetparkofamerica.com", + "goAuthenticationType": "0", + "email": "uhart@valetparkofamerica.com" + }, + { + "fullname": "University of Miami Hurry ’Canes Shuttle", + "username": "miami", + "goAgencyName": "University of Miami Hurry ’Canes Shuttle", + "id": "5657", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#005030", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "University of Miami Medical Center (Reef Parking)", + "username": "miamimedical", + "goAgencyName": "University of Miami Medical Center (Reef Parking)", + "id": "4201", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#355E3B", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "University of Michigan-Dearborn", + "username": "umdearborn", + "goAgencyName": null, + "id": "1481", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "University of Montana (ASUM)", + "username": "montanau", + "goAgencyName": "University of Montana (ASUM)", + "id": "4041", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#d62728", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "University of New Haven", + "username": "newhaven", + "goAgencyName": "University of New Haven", + "id": "3900", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#002D74", + "goSupportEmail": "Judith.Miller@Propark.com", + "goAuthenticationType": "0", + "email": "Judith.Miller@Propark.com" + }, + { + "fullname": "University of New Mexico (UNM)", + "username": "unm", + "goAgencyName": null, + "id": "2156", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#ba0c2f", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "University of North Georgia", + "username": "northga", + "goAgencyName": "University of North Georgia", + "id": "646", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "University of Rochester", + "username": "urochester", + "goAgencyName": null, + "id": "3214", + "goTestMode": "0", + "name2": "1", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "University of San Diego Tram Services", + "username": "UofSanDTram", + "goAgencyName": null, + "id": "3444", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "trams@sandiego.edu", + "goAuthenticationType": "0", + "email": "trams@sandiego.edu" + }, + { + "fullname": "University of Tennessee, Knoxville (UTK)", + "username": "knoxtn", + "goAgencyName": "University of Tennessee, Knoxville (UTK)", + "id": "4938", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "University of Texas at El Paso (UTEP)", + "username": "utep", + "goAgencyName": null, + "id": "2383", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "University of Wisconsin-Milwaukee", + "username": "milwaukee", + "goAgencyName": null, + "id": "728", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Upper Cumberland Human Resource Agency (UCHRA)", + "username": "uchra", + "goAgencyName": null, + "id": "2875", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Utah State University", + "username": "utahstate", + "goAgencyName": null, + "id": "3499", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Vanderbilt University", + "username": "vandy", + "goAgencyName": "Vanderbilt University", + "id": "3622", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Vanderbilt University Medical Center", + "username": "vandyhealth", + "goAgencyName": "Vanderbilt University Medical Center", + "id": "1332", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Via Mobility Services", + "username": "viaboulder", + "goAgencyName": "Via Mobility Services", + "id": "4729", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#0058a6", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Vincennes Trolley", + "username": "ymcavango", + "goAgencyName": "Vincennes Trolley", + "id": "5365", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#393b79", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "VMware", + "username": "vmware", + "goAgencyName": null, + "id": "1274", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Wake Forest University", + "username": "wakeforest", + "goAgencyName": null, + "id": "3669", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "WaterColor Community Association", + "username": "watercolor", + "goAgencyName": "WaterColor Community Association", + "id": "4842", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": "#2ca02c", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "West Midtown Shuttle", + "username": "westmidtown", + "goAgencyName": "West Midtown Shuttle", + "id": "4473", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": "#1f77b4", + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Western Carolina University", + "username": "wcu", + "goAgencyName": null, + "id": "2597", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "WestMar", + "username": "westmar", + "goAgencyName": null, + "id": "1091", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "Woodbridge Village/Gardens/Colonial", + "username": "woodbridge", + "goAgencyName": null, + "id": "1642", + "goTestMode": "0", + "name2": "0", + "logo": 0, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": null, + "goAuthenticationType": "0" + }, + { + "fullname": "XChange at Secaucus Junction", + "username": "xchange", + "goAgencyName": null, + "id": "432", + "goTestMode": "0", + "name2": "0", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "", + "goAuthenticationType": "0" + }, + { + "fullname": "Yellowknife", + "username": "yellowknife", + "goAgencyName": "Yellowknife", + "id": "4825", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "support@passiogo.com", + "goAuthenticationType": "0", + "email": "support@passiogo.com" + }, + { + "fullname": "Testing", + "username": "scott", + "goAgencyName": "Testing", + "id": "1000000001", + "goTestMode": "1", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "1", + "goColor": null, + "goSupportEmail": "scott@adaptingtech.com", + "goAuthenticationType": "1", + "email": "scott@adaptingtech.com" + }, + { + "fullname": "Fitchburg State University", + "username": "montachusett", + "goAgencyName": "Fitchburg State University", + "id": "1000000002", + "goTestMode": "0", + "name2": "1", + "logo": 1, + "goRoutePlannerEnabled": "0", + "goColor": null, + "goSupportEmail": "contactmart@mrta.us", + "goAuthenticationType": "0", + "email": "contactmart@mrta.us" + } + ], + "lat": 33.7978, + "lng": -117.891, + "IPcoords": { + "lat": 33.7978, + "lng": -117.891, + "comment": "cache", + "IP": "206.211.154.147" + }, + "debug": { + "fromCache": 1, + "myip": "206.211.154.147" + } +}; \ No newline at end of file From 6c9f4691fd7c855ab469882eea2cb537c1c515d0 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 13:44:13 -0800 Subject: [PATCH 06/31] add test case for successful system response --- test/loaders/ApiBasedRepositoryLoaderTests.test.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index f14a794..177cf8b 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -1,6 +1,7 @@ -import { beforeEach, describe, it, jest, test } from "@jest/globals"; +import { beforeEach, describe, expect, it, jest, test } from "@jest/globals"; import { ApiBasedRepositoryLoader } from "../../src/loaders/ApiBasedRepositoryLoader"; import { UnoptimizedInMemoryRepository } from "../../src/repositories/UnoptimizedInMemoryRepository"; +import { getAllSystemsResponse } from "../jsonSnapshots/getAllSystemsResponse"; function updateGlobalFetchMockJson(obj: any) { // @ts-ignore @@ -29,7 +30,17 @@ describe("ApiBasedRepositoryLoader", () => { describe("fetchAndUpdateSystemData", () => { it("updates system data in repository if response received", async () => { + const numberOfSystemsInResponse = getAllSystemsResponse.all.length; + updateGlobalFetchMockJson(getAllSystemsResponse); + await loader.fetchAndUpdateSystemData(); + + const systems = await loader.repository.getSystems(); + if (loader.supportedSystemIds.length < numberOfSystemsInResponse) { + expect(systems).toHaveLength(loader.supportedSystemIds.length); + } else { + expect(systems).toHaveLength(numberOfSystemsInResponse); + } }); it("throws the correct error if the API response contains no data", async () => { From 1b9a77209fa7f79cea261f42770141546d4ed8ef Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:01:57 -0800 Subject: [PATCH 07/31] add error pathway and test case for validation --- .idea/inspectionProfiles/Project_Default.xml | 6 + src/loaders/ApiBasedRepositoryLoader.ts | 43 +- .../fetchSystemDataFailedResponse.ts | 5 + .../fetchSystemDataSuccessfulResponse.ts} | 2 +- .../ApiBasedRepositoryLoaderTests.test.ts | 29 +- test/loaders/temp.ts | 422 ++++++++++++++++++ 6 files changed, 488 insertions(+), 19 deletions(-) create mode 100644 .idea/inspectionProfiles/Project_Default.xml create mode 100644 test/jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse.ts rename test/jsonSnapshots/{getAllSystemsResponse.ts => fetchSystemData/fetchSystemDataSuccessfulResponse.ts} (99%) create mode 100644 test/loaders/temp.ts diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..cb83045 --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index 01e9cec..c5b252d 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -1,6 +1,13 @@ import { GetterSetterRepository } from "../repositories/GetterSetterRepository"; import { IEta, IRoute, IShuttle, IStop, ISystem } from "../entities/entities"; +export class ApiResponseError extends Error { + constructor(message: string) { + super(message); + this.name = "ApiResponseError"; + } +} + export class ApiBasedRepositoryLoader { readonly supportedSystemIds = ["263"]; readonly baseUrl = "https://passiogo.com/mapGetData.php"; @@ -15,20 +22,32 @@ export class ApiBasedRepositoryLoader { getSystems: "2", }; const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`); - const json = await response.json() - if (typeof json.all === "object") { - // filter down to supported systems - const filteredSystems = json.all.filter((jsonSystem: any) => this.supportedSystemIds.includes(jsonSystem.id)); - await Promise.all(filteredSystems.map(async (system: any) => { - const constructedSystem: ISystem = { - id: system.id, - name: system.fullname, - }; + try { + const response = await fetch(`${this.baseUrl}?${query}`); + const json = await response.json(); - await this.repository.addOrUpdateSystem(constructedSystem); - })); + if (!response.ok) { + throw new Error(`HTTP error with status ${response.status}`) + } + + if (typeof json.all === "object") { + // filter down to supported systems + const filteredSystems = json.all.filter((jsonSystem: any) => this.supportedSystemIds.includes(jsonSystem.id)); + await Promise.all(filteredSystems.map(async (system: any) => { + const constructedSystem: ISystem = { + id: system.id, + name: system.fullname, + }; + + await this.repository.addOrUpdateSystem(constructedSystem); + })); + } else { + throw new Error("Received JSON object does not contain `all` field") + } + } catch(e: any) { + console.error("fetchAndUpdateSystemData call failed: ", e); + throw new ApiResponseError(e.message); } } diff --git a/test/jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse.ts b/test/jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse.ts new file mode 100644 index 0000000..ba00384 --- /dev/null +++ b/test/jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse.ts @@ -0,0 +1,5 @@ +// Not an actual response snapshot +// Simulate a case where `all` property of response is unavailable +export const fetchSystemDataFailedResponse = { + "error": "no systems", +}; \ No newline at end of file diff --git a/test/jsonSnapshots/getAllSystemsResponse.ts b/test/jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse.ts similarity index 99% rename from test/jsonSnapshots/getAllSystemsResponse.ts rename to test/jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse.ts index f1e134c..67b77e5 100644 --- a/test/jsonSnapshots/getAllSystemsResponse.ts +++ b/test/jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse.ts @@ -1,4 +1,4 @@ -export const getAllSystemsResponse = { +export const fetchSystemDataSuccessfulResponse = { "all": [ { "fullname": "Chapman University", diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index 177cf8b..45a0742 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -1,13 +1,25 @@ import { beforeEach, describe, expect, it, jest, test } from "@jest/globals"; -import { ApiBasedRepositoryLoader } from "../../src/loaders/ApiBasedRepositoryLoader"; +import { ApiBasedRepositoryLoader, ApiResponseError } from "../../src/loaders/ApiBasedRepositoryLoader"; import { UnoptimizedInMemoryRepository } from "../../src/repositories/UnoptimizedInMemoryRepository"; -import { getAllSystemsResponse } from "../jsonSnapshots/getAllSystemsResponse"; +import { fetchSystemDataSuccessfulResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse"; +import { fetchSystemDataFailedResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse"; -function updateGlobalFetchMockJson(obj: any) { +/** + * Function to update behavior of the global `fetch` function. + * Note that the Passio GO API returns status code 200 for failed responses. + * @param obj + * @param status + */ +function updateGlobalFetchMockJson( + obj: any, + status: number = 200 +) { // @ts-ignore global.fetch = jest.fn(() => { return Promise.resolve({ - json: () => Promise.resolve(obj) + json: () => Promise.resolve(obj), + status, + ok: status.toString().startsWith("2"), // 200-level codes are OK }) }) as jest.Mock; } @@ -30,8 +42,8 @@ describe("ApiBasedRepositoryLoader", () => { describe("fetchAndUpdateSystemData", () => { it("updates system data in repository if response received", async () => { - const numberOfSystemsInResponse = getAllSystemsResponse.all.length; - updateGlobalFetchMockJson(getAllSystemsResponse); + const numberOfSystemsInResponse = fetchSystemDataSuccessfulResponse.all.length; + updateGlobalFetchMockJson(fetchSystemDataSuccessfulResponse); await loader.fetchAndUpdateSystemData(); @@ -44,7 +56,12 @@ describe("ApiBasedRepositoryLoader", () => { }); it("throws the correct error if the API response contains no data", async () => { + updateGlobalFetchMockJson(fetchSystemDataFailedResponse); + // Jest is so confusing + await expect(async () => { + await loader.fetchAndUpdateSystemData(); + }).rejects.toThrow(ApiResponseError); }); }); diff --git a/test/loaders/temp.ts b/test/loaders/temp.ts new file mode 100644 index 0000000..3248494 --- /dev/null +++ b/test/loaders/temp.ts @@ -0,0 +1,422 @@ +import { beforeEach, describe, expect, jest, test } from "@jest/globals"; +import { + ApiBasedRepository, + ApiBasedRepositoryCache, + ApiBasedRepositoryMillisecondTTLs +} from "../../src/repositories/ApiBasedRepository"; +import { IEta, IShuttle, IStop } from "../../src/entities/entities"; +import { genericEtaDataByStopId } from "../jsonSnapshots/genericEtaDataBySystemId"; +import { genericShuttleDataBySystemId } from "../jsonSnapshots/genericShuttleDataBySystemId"; + +/** + * Update the global fetch function to return a specific object. + * @param obj + */ +function updateGlobalFetchMockJson(obj: any) { + // @ts-ignore + global.fetch = jest.fn(() => { + return Promise.resolve({ + json: () => Promise.resolve(obj) + }) + }) as jest.Mock; +} + +/** + * Reset the global fetch function mock's JSON to return an empty object. + * @param obj + */ +function resetGlobalFetchMockJson() { + updateGlobalFetchMockJson({}) +} + +beforeEach(() => { + resetGlobalFetchMockJson(); +}) + + +describe("getEtaForShuttleAndStopId", () => { + test("getEtaForShuttleAndStopId returns correct ETA data", async () => { + updateGlobalFetchMockJson(genericEtaDataByStopId); + + const initialCache: ApiBasedRepositoryCache = { + etasForStopId: { + "177666": [ + { + secondsRemaining: 587, + shuttleId: "5577", + stopId: "177666", + millisecondsSinceEpoch: Date.now(), + }, + { + secondsRemaining: 226, + shuttleId: "9909", + stopId: "177666", + millisecondsSinceEpoch: Date.now(), + } + ], + }, + } + + const repository = new ApiBasedRepository(initialCache); + + repository.getShuttleById = jest.fn(async () => { + const shuttle: IShuttle = { + id: "5577", + name: "08", + coordinates: { + latitude: 33.7933406, + longitude: -117.8539321, + }, + routeId: "53966", + systemId: "1", + }; + return shuttle; + }); + + repository.updateEtasForSystemIfTTL = jest.fn(async () => { + }); + + const result = await repository.getEtaForShuttleAndStopId("5577", "177666"); + + expect(result?.secondsRemaining).toEqual(587); + expect(result?.millisecondsSinceEpoch).toBeDefined(); + expect(result?.shuttleId).toEqual("5577"); + expect(result?.stopId).toEqual("177666"); + }); + + test("getEtaForShuttleAndStopId returns null if API call is invalid and cache is empty", async () => { + const repository = new ApiBasedRepository(); + const result = await repository.getEtaForShuttleAndStopId("5577", "177666"); + + expect(result).toEqual(null); + }); +}); + +describe("getEtasForShuttleId", () => { + test("getEtasForShuttleId returns correct ETA data", async () => { + updateGlobalFetchMockJson(genericEtaDataByStopId); + + const initialCache: ApiBasedRepositoryCache = { + etasForStopId: {}, + etasForShuttleId: { + "5577": [ + { + secondsRemaining: 587, + shuttleId: "5577", + stopId: "177666", + millisecondsSinceEpoch: Date.now(), + } + ] + }, + }; + + const ttls: ApiBasedRepositoryMillisecondTTLs = { + etasForShuttleId: 100000, + etasForStopId: 100000, + }; + + const repository = new ApiBasedRepository(initialCache, ttls); + repository.updateEtasForSystemIfTTL = jest.fn(async () => { + }); + repository.getShuttleById = jest.fn(async () => { + const shuttle: IShuttle = { + id: "5577", + name: "08", + coordinates: { + latitude: 33.7933406, + longitude: -117.8539321, + }, + routeId: "53966", + systemId: "1", + }; + return shuttle; + }); + const result = await repository.getEtasForShuttleId("5577"); + + // @ts-ignore + expect(result).toEqual(initialCache.etasForShuttleId["5577"]); + }); + + test("getEtasForShuttleId returns empty array if no data available", async () => { + const repository = new ApiBasedRepository(); + repository.updateEtasForSystemIfTTL = jest.fn(async () => { + }); + const result = await repository.getEtasForShuttleId("5577"); + + expect(result).toEqual([]); + }); +}); + +describe("getEtasForStopId", () => { + test("getEtasForStopId returns correct ETA data", async () => { + // Because I'm testing updateEtasForSystemIfTTL separately, + // stub it out here + + updateGlobalFetchMockJson(genericEtaDataByStopId); + + const initialCache: ApiBasedRepositoryCache = { + etasForStopId: { + "177666": [ + { + secondsRemaining: 587, + shuttleId: "5577", + stopId: "177666", + millisecondsSinceEpoch: Date.now(), + } + ] + }, + etasForShuttleId: {} + }; + + const ttls: ApiBasedRepositoryMillisecondTTLs = { + etasForShuttleId: 100000, + etasForStopId: 100000, + }; + + const repository = new ApiBasedRepository(initialCache, ttls); + repository.getStopById = jest.fn(async () => { + const stop: IStop = { + name: "Chapman Court", + systemId: "1", + id: "177666", + coordinates: { + latitude: 33.796796, + longitude: -117.889293 + }, + }; + return stop; + }); + repository.updateEtasForSystemIfTTL = jest.fn(async () => { + }); + const result = await repository.getEtasForStopId("177666"); + + expect(result).toEqual(initialCache.etasForStopId!["177666"]); + }); + + test("getEtasForStopId returns empty array if no data available", async () => { + const repository = new ApiBasedRepository(); + repository.updateEtasForSystemIfTTL = jest.fn(async () => { + }); + const result = await repository.getEtasForShuttleId("5577"); + + expect(result).toEqual([]); + }); +}); + +describe("updateEtasForSystemIfTTL", () => { + // test("updateEtasForSystemIfTTL does nothing if data is not TTL", async () => { + // updateGlobalFetchMockJson(genericEtaDataByStopId); + // + // // If ETA data is not TTL, then don't do anything + // const expectedEta: IEta = { + // secondsRemaining: 587, + // shuttleId: "5577", + // stopId: "177666", + // millisecondsSinceEpoch: Date.now() - 1000, + // }; + // + // const initialCache: ApiBasedRepositoryCache = { + // etasForShuttleId: { + // "5577": [ + // expectedEta, + // ], + // }, + // etasForStopId: { + // "177666": [ + // expectedEta, + // ], + // }, + // stopsBySystemId: { + // "1": [ + // { + // systemId: "1", + // millisecondsSinceEpoch: Date.now() - 1000, + // name: "Chapman Court", + // id: "177666", + // coordinates: { + // latitude: 33.796796, + // longitude: -117.889293 + // }, + // } + // ], + // }, + // }; + // + // const ttls: ApiBasedRepositoryMillisecondTTLs = { + // etasForShuttleId: 100000, + // etasForStopId: 100000, + // }; + // + // const repository = new ApiBasedRepository(initialCache, ttls); + // await repository.updateEtasForSystemIfTTL("1"); + // + // const updatedResult = await repository.getEtaForShuttleAndStopId( + // "5577", + // "177666", + // ); + // expect(updatedResult?.millisecondsSinceEpoch).toEqual(expectedEta.millisecondsSinceEpoch); + // }); + + test("updateEtasForSystemIfTTL updates all ETA data if data is TTL", async () => { + updateGlobalFetchMockJson(genericEtaDataByStopId); + + const sampleStop: IStop = { + name: "Chapman Court", + systemId: "1", + id: "177666", + coordinates: { + latitude: 33.796796, + longitude: -117.889293 + }, + } + + const repository = new ApiBasedRepository(); + repository.getStopsBySystemId = jest.fn(async () => { + return [ + sampleStop + ]; + }); + + repository.getStopById = jest.fn(async () => { + return sampleStop; + }); + + await repository.updateEtasForSystemIfTTL("1"); + + const updatedResult = await repository.getEtasForStopId("177666"); + expect(updatedResult.length).toEqual(2); + }); +}); + +describe("getShuttleById", () => { + test("getShuttleById returns null if unseeded cache", async () => { + updateGlobalFetchMockJson(genericShuttleDataBySystemId); + + const initialCache: ApiBasedRepositoryCache = {}; + const repository = new ApiBasedRepository(initialCache); + + const shuttle = await repository.getShuttleById("5577"); + expect(shuttle).toBeNull(); + }); + + test("getShuttleById returns data if present", async () => { + updateGlobalFetchMockJson(genericShuttleDataBySystemId); + + const initialCacheShuttle = { + coordinates: { + latitude: 33.7917818, + longitude: -117.8589646, + }, + name: "08", + routeId: "53966", + systemId: "1", + id: "5577", + } + + const initialCache: ApiBasedRepositoryCache = { + shuttleByShuttleId: { + "5577": initialCacheShuttle + } + }; + + const ttls: ApiBasedRepositoryMillisecondTTLs = { + shuttleByShuttleId: 1000, + }; + + const repository = new ApiBasedRepository(initialCache, ttls); + repository.updateStopsForSystemIdIfTTL = jest.fn(async () => { + }) + + const shuttle = await repository.getShuttleById("5577"); + expect(shuttle).toEqual(initialCacheShuttle); + }); +}); + +// TODO: enable when implemented +// describe("getShuttlesBySystemId", () => { +// test("getShuttlesBySystemId returns old data if not expired", async () => { +// updateGlobalFetchMockJson(genericShuttleDataBySystemId); +// +// const initialCacheShuttle = { +// coordinates: { +// latitude: 33.791781, +// longitude: -117.8589646, +// }, +// name: "08", +// routeId: "53966", +// systemId: "1", +// id: "5577", +// millisecondsSinceEpoch: Date.now() - 1000, +// }; +// +// const initialCache: ApiBasedRepositoryCache = { +// shuttlesBySystemId: { +// "1": [ +// initialCacheShuttle, +// ] +// }, +// shuttleByShuttleId: { +// "5577": initialCacheShuttle, +// } +// }; +// +// const ttls: ApiBasedRepositoryMillisecondTTLs = { +// shuttleByShuttleId: 100000, +// shuttlesBySystemId: 100000, +// }; +// +// const repository = new ApiBasedRepository(initialCache, ttls); +// const shuttles = await repository.getShuttlesBySystemId("1"); +// expect(shuttles.length).toEqual(1); +// expect(shuttles[0].id).toEqual(initialCacheShuttle.id); +// }); +// +// test("getShuttlesBySystemId returns fresh data if expired", async () => { +// updateGlobalFetchMockJson(genericShuttleDataBySystemId); +// +// // TODO: move construction of shuttle into method +// const initialCacheShuttle = { +// coordinates: { +// latitude: 33.791781, +// longitude: -117.8589646, +// }, +// name: "08", +// routeId: "53966", +// systemId: "1", +// id: "5577", +// millisecondsSinceEpoch: Date.now() - 100000, +// }; +// +// const initialCache: ApiBasedRepositoryCache = { +// shuttlesBySystemId: { +// "1": [ +// initialCacheShuttle, +// ] +// }, +// shuttleByShuttleId: { +// "5577": initialCacheShuttle, +// } +// }; +// +// const ttls: ApiBasedRepositoryMillisecondTTLs = { +// shuttleByShuttleId: 1000, +// shuttlesBySystemId: 1000, +// }; +// +// const repository = new ApiBasedRepository(initialCache, ttls); +// const shuttles = await repository.getShuttlesBySystemId("1"); +// +// expect(shuttles.length).toEqual(1); +// expect(shuttles[0].id).toEqual("5577"); +// expect(shuttles[0].millisecondsSinceEpoch).not.toEqual(initialCacheShuttle.millisecondsSinceEpoch); +// }); +// +// test("getShuttlesBySystemId returns fresh data if no seeded data", async () => { +// updateGlobalFetchMockJson(genericShuttleDataBySystemId); +// +// const repository = new ApiBasedRepository(); +// const shuttles = await repository.getShuttlesBySystemId("1"); +// +// expect(shuttles.length).toEqual(1); +// }); +// }); From bbe2c4c7aa31d43172b9b714fa6fceb203a8db36 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:03:43 -0800 Subject: [PATCH 08/31] add additional test for HTTP status code --- test/loaders/ApiBasedRepositoryLoaderTests.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index 45a0742..3b7b633 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -63,6 +63,14 @@ describe("ApiBasedRepositoryLoader", () => { await loader.fetchAndUpdateSystemData(); }).rejects.toThrow(ApiResponseError); }); + + it("throws the correct error if HTTP status code is not 200", async () => { + updateGlobalFetchMockJson(fetchSystemDataFailedResponse, 400); + + await expect(async () => { + await loader.fetchAndUpdateSystemData(); + }).rejects.toThrow(ApiResponseError); + }); }); describe("fetchAndUpdateRouteDataForExistingSystems", () => { From 0fe279f06909bd03cbb6337883beecccbdb65523 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:16:02 -0800 Subject: [PATCH 09/31] refactor ApiResponseError check into a function --- .../loaders/ApiBasedRepositoryLoaderTests.test.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index 3b7b633..bc8000d 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -29,7 +29,11 @@ function updateGlobalFetchMockJson( * @param obj */ function resetGlobalFetchMockJson() { - updateGlobalFetchMockJson({}) + updateGlobalFetchMockJson({}); +} + +async function assertAsyncCallbackThrowsApiResponseError(callback: () => Promise) { + await expect(callback).rejects.toThrow(ApiResponseError); } describe("ApiBasedRepositoryLoader", () => { @@ -58,18 +62,17 @@ describe("ApiBasedRepositoryLoader", () => { it("throws the correct error if the API response contains no data", async () => { updateGlobalFetchMockJson(fetchSystemDataFailedResponse); - // Jest is so confusing - await expect(async () => { + await assertAsyncCallbackThrowsApiResponseError(async () => { await loader.fetchAndUpdateSystemData(); - }).rejects.toThrow(ApiResponseError); + }); }); it("throws the correct error if HTTP status code is not 200", async () => { updateGlobalFetchMockJson(fetchSystemDataFailedResponse, 400); - await expect(async () => { + await assertAsyncCallbackThrowsApiResponseError(async () => { await loader.fetchAndUpdateSystemData(); - }).rejects.toThrow(ApiResponseError); + }); }); }); From 5e5f76afcc0ae1526e8273a95f873096ae42ce65 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:22:45 -0800 Subject: [PATCH 10/31] add json snapshot for successful routes response --- .../fetchRouteDataSuccessfulResponse.ts | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 test/jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse.ts diff --git a/test/jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse.ts b/test/jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse.ts new file mode 100644 index 0000000..0a06f12 --- /dev/null +++ b/test/jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse.ts @@ -0,0 +1,153 @@ +export const fetchRouteDataSuccessfulResponse = { + "all": [ + { + "name": "Rinker Route", + "shortName": null, + "color": "#696969", + "userId": "263", + "myid": "53970", + "mapApp": "1", + "archive": "0", + "goPrefixRouteName": "1", + "goShowSchedule": 0, + "outdated": "0", + "id": "5902", + "distance": 1900, + "latitude": "33.656851000", + "longitude": "-117.733221000", + "timezone": "America/Los_Angeles", + "fullname": "Chapman University", + "nameOrig": "Rinker Route", + "groupId": "6706", + "groupColor": "#696969" + }, + { + "name": "Red Route", + "shortName": null, + "color": "#d62728", + "userId": "263", + "myid": "53966", + "mapApp": "1", + "archive": "0", + "goPrefixRouteName": "1", + "goShowSchedule": 0, + "outdated": "0", + "id": "2032", + "distance": 1905, + "latitude": "33.793325000", + "longitude": "-117.852810000", + "timezone": "America/Los_Angeles", + "fullname": "Chapman University", + "nameOrig": "Red Route", + "groupId": "6703", + "groupColor": "#d62728" + }, + { + "name": "Teal Route", + "shortName": null, + "color": "#096e90", + "userId": "263", + "myid": "54191", + "mapApp": "1", + "archive": "0", + "goPrefixRouteName": "1", + "goShowSchedule": 0, + "outdated": "0", + "id": "2032", + "distance": 1905, + "latitude": "33.793325000", + "longitude": "-117.852810000", + "timezone": "America/Los_Angeles", + "fullname": "Chapman University", + "nameOrig": "Teal Route", + "groupId": "6705", + "groupColor": "#096e90" + }, + { + "name": "Gold Route", + "shortName": null, + "color": "#bd9e39", + "userId": "263", + "myid": "54256", + "mapApp": "1", + "archive": "0", + "goPrefixRouteName": "1", + "goShowSchedule": 0, + "outdated": "0", + "id": "2032", + "distance": 1905, + "latitude": "33.793325000", + "longitude": "-117.852810000", + "timezone": "America/Los_Angeles", + "fullname": "Chapman University", + "nameOrig": "Gold Route", + "groupId": "6707", + "groupColor": "#bd9e39" + }, + { + "name": "Black Route", + "shortName": null, + "color": "#000000", + "userId": "263", + "myid": "54257", + "mapApp": "1", + "archive": "0", + "goPrefixRouteName": "1", + "goShowSchedule": 0, + "outdated": "0", + "id": "2032", + "distance": 1905, + "latitude": "33.793325000", + "longitude": "-117.852810000", + "timezone": "America/Los_Angeles", + "fullname": "Chapman University", + "nameOrig": "Black Route", + "groupId": "6704", + "groupColor": "#000000" + }, + { + "name": "Weekend Route", + "shortName": null, + "color": "#510094", + "userId": "263", + "myid": "54282", + "mapApp": "1", + "archive": "0", + "goPrefixRouteName": "1", + "goShowSchedule": 0, + "outdated": "1", + "id": "2032", + "distance": 1905, + "latitude": "33.793325000", + "longitude": "-117.852810000", + "timezone": "America/Los_Angeles", + "fullname": "Chapman University", + "nameOrig": "Weekend Route", + "groupId": "6710", + "groupColor": "#510094", + "serviceTime": "is not provided: no bus on the route", + "serviceTimeShort": "No bus in service" + }, + { + "name": "Parking Lot", + "shortName": null, + "color": "#000000", + "userId": "263", + "myid": "54529", + "mapApp": "1", + "archive": "0", + "goPrefixRouteName": "1", + "goShowSchedule": 0, + "outdated": "0", + "id": "2032", + "distance": 1905, + "latitude": "33.793325000", + "longitude": "-117.852810000", + "timezone": "America/Los_Angeles", + "fullname": "Chapman University", + "nameOrig": "Parking Lot", + "groupId": "6731", + "groupColor": "#393838" + } + ] +} From f1fd7748213f17603fed0984355507eb759d4c99 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:27:12 -0800 Subject: [PATCH 11/31] refactor route fetching logic for single system ID to external function --- src/loaders/ApiBasedRepositoryLoader.ts | 72 +++++++++++--------- src/loaders/TimedApiBasedRepositoryLoader.ts | 2 +- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index c5b252d..66ea4b7 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -9,8 +9,8 @@ export class ApiResponseError extends Error { } export class ApiBasedRepositoryLoader { - readonly supportedSystemIds = ["263"]; - readonly baseUrl = "https://passiogo.com/mapGetData.php"; + supportedSystemIds = ["263"]; + baseUrl = "https://passiogo.com/mapGetData.php"; constructor( public repository: GetterSetterRepository, @@ -51,43 +51,47 @@ export class ApiBasedRepositoryLoader { } } - public async fetchAndUpdateRouteDataForExistingSystems() { + public async fetchAndUpdateRouteDataForExistingSystemsInRepository() { const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system) => { - const params = { - getRoutes: "2", - }; - - const formDataJsonObject = { - "systemSelected0": system.id, - "amount": "1", - } - const formData = new FormData(); - formData.set("json", JSON.stringify(formDataJsonObject)); - - const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "POST", - body: formData, - }); - const json = await response.json(); - - if (typeof json.all === "object") { - await Promise.all(json.all.map(async (jsonRoute: any) => { - const constructedRoute: IRoute = { - name: jsonRoute.name, - color: jsonRoute.color, - id: jsonRoute.myid, - polylineCoordinates: [], - systemId: system.id, - }; - - await this.repository.addOrUpdateRoute(constructedRoute); - })) - } + await this.fetchAndUpdateRouteDataForSystemId(system.id); })); } + public async fetchAndUpdateRouteDataForSystemId(systemId: string) { + const params = { + getRoutes: "2", + }; + + const formDataJsonObject = { + "systemSelected0": systemId, + "amount": "1", + } + const formData = new FormData(); + formData.set("json", JSON.stringify(formDataJsonObject)); + + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "POST", + body: formData, + }); + const json = await response.json(); + + if (typeof json.all === "object") { + await Promise.all(json.all.map(async (jsonRoute: any) => { + const constructedRoute: IRoute = { + name: jsonRoute.name, + color: jsonRoute.color, + id: jsonRoute.myid, + polylineCoordinates: [], + systemId: systemId, + }; + + await this.repository.addOrUpdateRoute(constructedRoute); + })) + } + } + public async fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems() { // Fetch from the API // Pass JSON output into two different methods to update repository diff --git a/src/loaders/TimedApiBasedRepositoryLoader.ts b/src/loaders/TimedApiBasedRepositoryLoader.ts index 6fd40f4..be806d7 100644 --- a/src/loaders/TimedApiBasedRepositoryLoader.ts +++ b/src/loaders/TimedApiBasedRepositoryLoader.ts @@ -50,7 +50,7 @@ export class TimedApiBasedRepositoryLoader extends ApiBasedRepositoryLoader { await this.repository.clearSystemData(); await this.fetchAndUpdateSystemData(); await this.repository.clearRouteData(); - await this.fetchAndUpdateRouteDataForExistingSystems(); + await this.fetchAndUpdateRouteDataForExistingSystemsInRepository(); await this.repository.clearStopData(); await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems(); await this.repository.clearShuttleData(); From 420b71258ebf1c7ce3a1437b3aa490de140b8448 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:35:11 -0800 Subject: [PATCH 12/31] add test cases for fetchANdUpdateRouteDataForSystemId --- .../ApiBasedRepositoryLoaderTests.test.ts | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index bc8000d..adc48eb 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -3,6 +3,7 @@ import { ApiBasedRepositoryLoader, ApiResponseError } from "../../src/loaders/Ap import { UnoptimizedInMemoryRepository } from "../../src/repositories/UnoptimizedInMemoryRepository"; import { fetchSystemDataSuccessfulResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse"; import { fetchSystemDataFailedResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse"; +import { fetchRouteDataSuccessfulResponse } from "../jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse"; /** * Function to update behavior of the global `fetch` function. @@ -76,13 +77,40 @@ describe("ApiBasedRepositoryLoader", () => { }); }); - describe("fetchAndUpdateRouteDataForExistingSystems", () => { - it("updates route data in repository if there are systems and response received", async () => { + describe("fetchAndUpdateRouteDataForExistingSystemsInRepository", () => { + // TODO + // Add a test case to ensure that fetchAndUpdateRouteDataForSystemId + // was called for every available system ID + }); + + describe("fetchAndUpdateRouteDataForSystemId", () => { + it("updates route data in repository if there are systems and response received", async () => { + updateGlobalFetchMockJson(fetchRouteDataSuccessfulResponse); + + await loader.fetchAndUpdateRouteDataForSystemId("263"); + + const routes = await loader.repository.getRoutesBySystemId("263"); + + expect(routes.length).toEqual(fetchRouteDataSuccessfulResponse.all.length) }); it("throws the correct error if the API response contains no data", async () => { + // The Passio API returns some invalid JSON if there is no data, + // so simulate a JSON parsing error + // @ts-ignore + global.fetch = jest.fn(() => { + return Promise.resolve({ + json: () => Promise.reject(new SyntaxError("Unable to parse JSON")), + status: 200, + ok: true, + }) + }) as jest.Mock; + + await assertAsyncCallbackThrowsApiResponseError(async () => { + await loader.fetchAndUpdateRouteDataForSystemId("263"); + }); }); }); From 9fda898ecb0fee1e5f8efd849bd129e8bec20bf2 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:36:49 -0800 Subject: [PATCH 13/31] update fetchAndUpdateRouteDataForSystemId to include try/catch --- src/loaders/ApiBasedRepositoryLoader.ts | 38 ++++++++++++++----------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index 66ea4b7..d93000a 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -71,24 +71,30 @@ export class ApiBasedRepositoryLoader { formData.set("json", JSON.stringify(formDataJsonObject)); const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "POST", - body: formData, - }); - const json = await response.json(); - if (typeof json.all === "object") { - await Promise.all(json.all.map(async (jsonRoute: any) => { - const constructedRoute: IRoute = { - name: jsonRoute.name, - color: jsonRoute.color, - id: jsonRoute.myid, - polylineCoordinates: [], - systemId: systemId, - }; + try { + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "POST", + body: formData, + }); + const json = await response.json(); - await this.repository.addOrUpdateRoute(constructedRoute); - })) + if (typeof json.all === "object") { + await Promise.all(json.all.map(async (jsonRoute: any) => { + const constructedRoute: IRoute = { + name: jsonRoute.name, + color: jsonRoute.color, + id: jsonRoute.myid, + polylineCoordinates: [], + systemId: systemId, + }; + + await this.repository.addOrUpdateRoute(constructedRoute); + })) + } + } catch(e: any) { + console.error(`fetchAndUpdateRouteDataForSystemId failed for system ID ${systemId}: ${e}`); + throw new ApiResponseError(e.message); } } From 1fea82179a578836fd2f13ba298f9c513628836f Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:43:09 -0800 Subject: [PATCH 14/31] add test case for fetch existing systems method --- .../ApiBasedRepositoryLoaderTests.test.ts | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index adc48eb..41da8be 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -4,6 +4,7 @@ import { UnoptimizedInMemoryRepository } from "../../src/repositories/Unoptimize import { fetchSystemDataSuccessfulResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse"; import { fetchSystemDataFailedResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse"; import { fetchRouteDataSuccessfulResponse } from "../jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse"; +import { ISystem } from "../../src/entities/entities"; /** * Function to update behavior of the global `fetch` function. @@ -79,9 +80,28 @@ describe("ApiBasedRepositoryLoader", () => { describe("fetchAndUpdateRouteDataForExistingSystemsInRepository", () => { - // TODO - // Add a test case to ensure that fetchAndUpdateRouteDataForSystemId - // was called for every available system ID + test("calls fetchAndUpdateRouteDataForSystemId for all systems in repository", async () => { + const spy = jest.spyOn(loader, "fetchAndUpdateRouteDataForSystemId"); + + const systems: ISystem[] = [ + { + name: "Chapman University", + id: "1", + }, + { + name: "City of Monterey Park", + id: "2", + } + ]; + + await Promise.all(systems.map(async (system) => { + await loader.repository.addOrUpdateSystem(system); + })); + + await loader.fetchAndUpdateRouteDataForExistingSystemsInRepository(); + + expect(spy.mock.calls.length).toBe(2); + }); }); describe("fetchAndUpdateRouteDataForSystemId", () => { From 4d5e563f9c22ec82618c46c9e590781560f603ed Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:49:05 -0800 Subject: [PATCH 15/31] add stops and polyline data object --- ...chStopAndPolylineDataSuccessfulResponse.ts | 12687 ++++++++++++++++ 1 file changed, 12687 insertions(+) create mode 100644 test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts diff --git a/test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts b/test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts new file mode 100644 index 0000000..98465b4 --- /dev/null +++ b/test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts @@ -0,0 +1,12687 @@ +export const fetchStopAndPolylineDataForRoutesWithSystemId = { + "stops": { + "ID2032": { + "routeId": "54529", + "stopId": "2032", + "position": "5", + "name": "Schmid Gate", + "latitude": 33.793325, + "longitude": -117.85281, + "id": "2032", + "userId": "263", + "radius": 75, + "routeName": "Parking Lot", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID2033": { + "routeId": "54282", + "stopId": "2033", + "position": "3", + "name": "Panther Village OB", + "latitude": 33.789670544, + "longitude": -117.886282327, + "id": "2033", + "userId": "263", + "radius": 70, + "routeName": "Weekend Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID177666": { + "routeId": "54282", + "stopId": "177666", + "position": "5", + "name": "Chapman Court", + "latitude": 33.796601, + "longitude": -117.8892805, + "id": "177666", + "userId": "263", + "radius": 50, + "routeName": "Weekend Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID20738": { + "routeId": "54282", + "stopId": "20738", + "position": "6", + "name": "Panther Village IB", + "latitude": 33.78966221, + "longitude": -117.886293064, + "id": "20738", + "userId": "263", + "radius": 70, + "routeName": "Weekend Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID5902": { + "routeId": "53970", + "stopId": "5902", + "position": "6", + "name": "Irvine Train Station", + "latitude": 33.656851, + "longitude": -117.733221, + "id": "5902", + "userId": "263", + "radius": 50, + "routeName": "Rinker Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID177759": { + "routeId": "53970", + "stopId": "177759", + "position": "3", + "name": "9401 Rinker", + "latitude": 33.65090784, + "longitude": -117.718687088, + "id": "177759", + "userId": "263", + "radius": 50, + "routeName": "Rinker Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID177760": { + "routeId": "53970", + "stopId": "177760", + "position": "5", + "name": "9405 Rinker", + "latitude": 33.650064432, + "longitude": -117.717134189, + "id": "177760", + "userId": "263", + "radius": 50, + "routeName": "Rinker Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID13027": { + "routeId": "54282", + "stopId": "13027", + "position": "4", + "name": "Chapman Grand", + "latitude": 33.804433, + "longitude": -117.895966, + "id": "13027", + "userId": "263", + "radius": 98, + "routeName": "Weekend Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID177802": { + "routeId": "54282", + "stopId": "177802", + "position": "2", + "name": "Ralph's OB", + "latitude": 33.788104697, + "longitude": -117.868068553, + "id": "177802", + "userId": "263", + "radius": 50, + "routeName": "Weekend Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID177764": { + "routeId": "54282", + "stopId": "177764", + "position": "7", + "name": "Ralph's IB", + "latitude": 33.787774882, + "longitude": -117.868395657, + "id": "177764", + "userId": "263", + "radius": 50, + "routeName": "Weekend Route", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID2035": { + "routeId": "54529", + "stopId": "2035", + "position": "2", + "name": "West Palm Lot", + "latitude": 33.79245127, + "longitude": -117.858878931, + "id": "2035", + "userId": "263", + "radius": 75, + "routeName": "Parking Lot", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID2276": { + "routeId": "54529", + "stopId": "2276", + "position": "3", + "name": "West Campus Parking", + "latitude": 33.790398301, + "longitude": -117.8566779, + "id": "2276", + "userId": "263", + "radius": 50, + "routeName": "Parking Lot", + "routeShortname": null, + "routeGroupId": 0 + }, + "ID2277": { + "routeId": "54529", + "stopId": "2277", + "position": "4", + "name": "Train Depot", + "latitude": 33.789359552, + "longitude": -117.857087589, + "id": "2277", + "userId": "263", + "radius": 50, + "routeName": "Parking Lot", + "routeShortname": null, + "routeGroupId": 0 + } + }, + "routes": { + "53966": [ + "Red Route", + "#d62728", + [ + "1", + "2032", + 0 + ], + [ + "2", + "2033", + 0 + ], + [ + "3", + "177666", + 0 + ], + [ + "4", + "20738", + 0 + ], + [ + "5", + "2032", + 0 + ] + ], + "53970": [ + "Rinker Route", + "#696969", + [ + "1", + "5902", + 0 + ], + [ + "3", + "177759", + 0 + ], + [ + "5", + "177760", + 0 + ], + [ + "6", + "5902", + 1 + ] + ], + "54191": [ + "Teal Route", + "#096e90", + [ + "1", + "2032", + 0 + ], + [ + "2", + "2033", + 0 + ], + [ + "3", + "177666", + 0 + ], + [ + "4", + "13027", + 0 + ], + [ + "5", + "20738", + 0 + ], + [ + "6", + "2032", + 0 + ] + ], + "54256": [ + "Gold Route", + "#bd9e39", + [ + "1", + "2032", + 0 + ], + [ + "2", + "2033", + 0 + ], + [ + "4", + "13027", + 0 + ], + [ + "5", + "20738", + 0 + ], + [ + "6", + "2032", + 0 + ] + ], + "54257": [ + "Black Route", + "#000000", + [ + "1", + "2032", + 0 + ], + [ + "2", + "2033", + 0 + ], + [ + "3", + "13027", + 0 + ], + [ + "4", + "177666", + 0 + ], + [ + "5", + "20738", + 0 + ], + [ + "6", + "2032", + 0 + ] + ], + "54282": [ + "Weekend Route", + "#510094", + [ + "1", + "2032", + 0 + ], + [ + "2", + "177802", + 0 + ], + [ + "3", + "2033", + 0 + ], + [ + "4", + "13027", + 0 + ], + [ + "5", + "177666", + 0 + ], + [ + "6", + "20738", + 0 + ], + [ + "7", + "177764", + 0 + ], + [ + "8", + "2032", + 0 + ] + ], + "54529": [ + "Parking Lot", + "#000000", + [ + "1", + "2032", + 0 + ], + [ + "2", + "2035", + 0 + ], + [ + "3", + "2276", + 0 + ], + [ + "4", + "2277", + 0 + ], + [ + "5", + "2032", + 0 + ] + ] + }, + "routePoints": { + "53966": [ + [ + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793230000", + "lng": "-117.856356000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787891000", + "lng": "-117.856783000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787893000", + "lng": "-117.856979000" + }, + { + "lat": "33.787933000", + "lng": "-117.857043000" + }, + { + "lat": "33.787933000", + "lng": "-117.857458000" + }, + { + "lat": "33.787933000", + "lng": "-117.857518000" + }, + { + "lat": "33.787933000", + "lng": "-117.857827000" + }, + { + "lat": "33.787933000", + "lng": "-117.857907000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787938000", + "lng": "-117.865679000" + }, + { + "lat": "33.787938000", + "lng": "-117.866004000" + }, + { + "lat": "33.787939000", + "lng": "-117.866335000" + }, + { + "lat": "33.787940000", + "lng": "-117.866502000" + }, + { + "lat": "33.787940000", + "lng": "-117.866645000" + }, + { + "lat": "33.787941000", + "lng": "-117.866964000" + }, + { + "lat": "33.787942000", + "lng": "-117.867104000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.872161000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787940000", + "lng": "-117.878721000" + }, + { + "lat": "33.787946000", + "lng": "-117.878943000" + }, + { + "lat": "33.787950000", + "lng": "-117.879220000" + }, + { + "lat": "33.787947000", + "lng": "-117.879543000" + }, + { + "lat": "33.787932000", + "lng": "-117.880310000" + }, + { + "lat": "33.787929000", + "lng": "-117.880465000" + }, + { + "lat": "33.787930000", + "lng": "-117.880566000" + }, + { + "lat": "33.787930000", + "lng": "-117.880625000" + }, + { + "lat": "33.787932000", + "lng": "-117.881015000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789638000", + "lng": "-117.886143000" + }, + { + "lat": "33.789733000", + "lng": "-117.886236000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789573000", + "lng": "-117.886197000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789306000", + "lng": "-117.886505000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789467000", + "lng": "-117.888536000" + }, + { + "lat": "33.789477000", + "lng": "-117.888629000" + }, + { + "lat": "33.789431000", + "lng": "-117.888858000" + }, + { + "lat": "33.789193000", + "lng": "-117.889833000" + }, + { + "lat": "33.789079000", + "lng": "-117.890474000" + }, + { + "lat": "33.789070000", + "lng": "-117.890540000" + }, + { + "lat": "33.789050000", + "lng": "-117.890692000" + }, + { + "lat": "33.789213000", + "lng": "-117.890685000" + }, + { + "lat": "33.789240000", + "lng": "-117.890682000" + }, + { + "lat": "33.789443000", + "lng": "-117.890661000" + }, + { + "lat": "33.789572000", + "lng": "-117.890639000" + }, + { + "lat": "33.789673000", + "lng": "-117.890617000" + }, + { + "lat": "33.789791000", + "lng": "-117.890583000" + }, + { + "lat": "33.789972000", + "lng": "-117.890523000" + }, + { + "lat": "33.789994000", + "lng": "-117.890515000" + }, + { + "lat": "33.790393000", + "lng": "-117.890382000" + }, + { + "lat": "33.790715000", + "lng": "-117.890275000" + }, + { + "lat": "33.790840000", + "lng": "-117.890233000" + }, + { + "lat": "33.791287000", + "lng": "-117.890090000" + }, + { + "lat": "33.791676000", + "lng": "-117.889959000" + }, + { + "lat": "33.791969000", + "lng": "-117.889853000" + }, + { + "lat": "33.792429000", + "lng": "-117.889707000" + }, + { + "lat": "33.792554000", + "lng": "-117.889667000" + }, + { + "lat": "33.792652000", + "lng": "-117.889635000" + }, + { + "lat": "33.793067000", + "lng": "-117.889526000" + }, + { + "lat": "33.793455000", + "lng": "-117.889409000" + }, + { + "lat": "33.793623000", + "lng": "-117.889359000" + }, + { + "lat": "33.794047000", + "lng": "-117.889238000" + }, + { + "lat": "33.794232000", + "lng": "-117.889198000" + }, + { + "lat": "33.794418000", + "lng": "-117.889168000" + }, + { + "lat": "33.794570000", + "lng": "-117.889154000" + }, + { + "lat": "33.794724000", + "lng": "-117.889139000" + }, + { + "lat": "33.794892000", + "lng": "-117.889128000" + }, + { + "lat": "33.795108000", + "lng": "-117.889122000" + }, + { + "lat": "33.795424000", + "lng": "-117.889117000" + }, + { + "lat": "33.795532000", + "lng": "-117.889111000" + }, + { + "lat": "33.795727000", + "lng": "-117.889100000" + }, + { + "lat": "33.795934000", + "lng": "-117.889091000" + }, + { + "lat": "33.796137000", + "lng": "-117.889082000" + }, + { + "lat": "33.796513000", + "lng": "-117.889083000" + }, + { + "lat": "33.796740000", + "lng": "-117.889083000" + }, + { + "lat": "33.797121000", + "lng": "-117.889083000" + }, + { + "lat": "33.797353000", + "lng": "-117.889084000" + }, + { + "lat": "33.797687000", + "lng": "-117.889084000" + }, + { + "lat": "33.797876000", + "lng": "-117.889085000" + }, + { + "lat": "33.798169000", + "lng": "-117.889089000" + }, + { + "lat": "33.798868000", + "lng": "-117.889102000" + }, + { + "lat": "33.799531000", + "lng": "-117.889114000" + }, + { + "lat": "33.799563000", + "lng": "-117.889117000" + }, + { + "lat": "33.799711000", + "lng": "-117.889176000" + }, + { + "lat": "33.799711000", + "lng": "-117.889396000" + }, + { + "lat": "33.799712000", + "lng": "-117.889838000" + }, + { + "lat": "33.799712000", + "lng": "-117.890642000" + }, + { + "lat": "33.799556000", + "lng": "-117.890647000" + }, + { + "lat": "33.799500000", + "lng": "-117.890647000" + }, + { + "lat": "33.797874000", + "lng": "-117.890640000" + }, + { + "lat": "33.797874000", + "lng": "-117.890360000" + }, + { + "lat": "33.797874000", + "lng": "-117.889265000" + }, + { + "lat": "33.797506000", + "lng": "-117.889272000" + }, + { + "lat": "33.797103000", + "lng": "-117.889280000" + }, + { + "lat": "33.796975000", + "lng": "-117.889282000" + }, + { + "lat": "33.796354000", + "lng": "-117.889295000" + }, + { + "lat": "33.796134000", + "lng": "-117.889299000" + }, + { + "lat": "33.795536000", + "lng": "-117.889327000" + }, + { + "lat": "33.794906000", + "lng": "-117.889329000" + }, + { + "lat": "33.794596000", + "lng": "-117.889345000" + }, + { + "lat": "33.794387000", + "lng": "-117.889372000" + }, + { + "lat": "33.794267000", + "lng": "-117.889394000" + }, + { + "lat": "33.793940000", + "lng": "-117.889494000" + }, + { + "lat": "33.793821000", + "lng": "-117.889529000" + }, + { + "lat": "33.793667000", + "lng": "-117.889574000" + }, + { + "lat": "33.793509000", + "lng": "-117.889624000" + }, + { + "lat": "33.793349000", + "lng": "-117.889674000" + }, + { + "lat": "33.792856000", + "lng": "-117.889863000" + }, + { + "lat": "33.792685000", + "lng": "-117.889920000" + }, + { + "lat": "33.792476000", + "lng": "-117.889990000" + }, + { + "lat": "33.791770000", + "lng": "-117.890225000" + }, + { + "lat": "33.791177000", + "lng": "-117.890419000" + }, + { + "lat": "33.791019000", + "lng": "-117.890471000" + }, + { + "lat": "33.790887000", + "lng": "-117.890516000" + }, + { + "lat": "33.790764000", + "lng": "-117.890559000" + }, + { + "lat": "33.790126000", + "lng": "-117.890770000" + }, + { + "lat": "33.789925000", + "lng": "-117.890837000" + }, + { + "lat": "33.789802000", + "lng": "-117.890868000" + }, + { + "lat": "33.789759000", + "lng": "-117.890877000" + }, + { + "lat": "33.789675000", + "lng": "-117.890893000" + }, + { + "lat": "33.789591000", + "lng": "-117.890907000" + }, + { + "lat": "33.789475000", + "lng": "-117.890916000" + }, + { + "lat": "33.789328000", + "lng": "-117.890924000" + }, + { + "lat": "33.789202000", + "lng": "-117.890932000" + }, + { + "lat": "33.789041000", + "lng": "-117.890936000" + }, + { + "lat": "33.788903000", + "lng": "-117.890936000" + }, + { + "lat": "33.788904000", + "lng": "-117.890700000" + }, + { + "lat": "33.788909000", + "lng": "-117.890516000" + }, + { + "lat": "33.788913000", + "lng": "-117.890489000" + }, + { + "lat": "33.788954000", + "lng": "-117.890197000" + }, + { + "lat": "33.789050000", + "lng": "-117.889708000" + }, + { + "lat": "33.789086000", + "lng": "-117.889537000" + }, + { + "lat": "33.789321000", + "lng": "-117.888520000" + }, + { + "lat": "33.789397000", + "lng": "-117.888460000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789336000", + "lng": "-117.886428000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789732000", + "lng": "-117.886235000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789589000", + "lng": "-117.886174000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789241000", + "lng": "-117.886328000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787837000", + "lng": "-117.881017000" + }, + { + "lat": "33.787840000", + "lng": "-117.880648000" + }, + { + "lat": "33.787840000", + "lng": "-117.880625000" + }, + { + "lat": "33.787841000", + "lng": "-117.880435000" + }, + { + "lat": "33.787847000", + "lng": "-117.879556000" + }, + { + "lat": "33.787844000", + "lng": "-117.879130000" + }, + { + "lat": "33.787844000", + "lng": "-117.879052000" + }, + { + "lat": "33.787843000", + "lng": "-117.878851000" + }, + { + "lat": "33.787842000", + "lng": "-117.878720000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787887000", + "lng": "-117.875554000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787838000", + "lng": "-117.867107000" + }, + { + "lat": "33.787838000", + "lng": "-117.866715000" + }, + { + "lat": "33.787838000", + "lng": "-117.866531000" + }, + { + "lat": "33.787838000", + "lng": "-117.866114000" + }, + { + "lat": "33.787838000", + "lng": "-117.865902000" + }, + { + "lat": "33.787838000", + "lng": "-117.865670000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787846000", + "lng": "-117.857894000" + }, + { + "lat": "33.787846000", + "lng": "-117.857828000" + }, + { + "lat": "33.787846000", + "lng": "-117.857771000" + }, + { + "lat": "33.787847000", + "lng": "-117.857518000" + }, + { + "lat": "33.787848000", + "lng": "-117.857460000" + }, + { + "lat": "33.787848000", + "lng": "-117.857265000" + }, + { + "lat": "33.787849000", + "lng": "-117.857090000" + }, + { + "lat": "33.787849000", + "lng": "-117.857041000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.788076000", + "lng": "-117.856372000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793322000", + "lng": "-117.855591000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793325000", + "lng": "-117.852810000" + } + ] + ], + "53970": [ + [ + { + "lat": "33.656785000", + "lng": "-117.733145000" + }, + { + "lat": "33.656732000", + "lng": "-117.733169000" + }, + { + "lat": "33.656674000", + "lng": "-117.733161000" + }, + { + "lat": "33.656611000", + "lng": "-117.733132000" + }, + { + "lat": "33.656510000", + "lng": "-117.732988000" + }, + { + "lat": "33.656130000", + "lng": "-117.732448000" + }, + { + "lat": "33.656101000", + "lng": "-117.732397000" + }, + { + "lat": "33.656076000", + "lng": "-117.732351000" + }, + { + "lat": "33.655526000", + "lng": "-117.732453000" + }, + { + "lat": "33.655369000", + "lng": "-117.732536000" + }, + { + "lat": "33.655088000", + "lng": "-117.732804000" + }, + { + "lat": "33.654978000", + "lng": "-117.732909000" + }, + { + "lat": "33.654905000", + "lng": "-117.732979000" + }, + { + "lat": "33.654820000", + "lng": "-117.733067000" + }, + { + "lat": "33.654500000", + "lng": "-117.732640000" + }, + { + "lat": "33.654235000", + "lng": "-117.732257000" + }, + { + "lat": "33.654046000", + "lng": "-117.732005000" + }, + { + "lat": "33.653960000", + "lng": "-117.731890000" + }, + { + "lat": "33.653876000", + "lng": "-117.731768000" + }, + { + "lat": "33.653829000", + "lng": "-117.731700000" + }, + { + "lat": "33.653736000", + "lng": "-117.731564000" + }, + { + "lat": "33.653589000", + "lng": "-117.731344000" + }, + { + "lat": "33.653307000", + "lng": "-117.730942000" + }, + { + "lat": "33.653063000", + "lng": "-117.730609000" + }, + { + "lat": "33.653021000", + "lng": "-117.730549000" + }, + { + "lat": "33.652803000", + "lng": "-117.730235000" + }, + { + "lat": "33.652756000", + "lng": "-117.730170000" + }, + { + "lat": "33.652598000", + "lng": "-117.729952000" + }, + { + "lat": "33.652362000", + "lng": "-117.729629000" + }, + { + "lat": "33.652349000", + "lng": "-117.729610000" + }, + { + "lat": "33.652269000", + "lng": "-117.729485000" + }, + { + "lat": "33.652192000", + "lng": "-117.729365000" + }, + { + "lat": "33.652101000", + "lng": "-117.729224000" + }, + { + "lat": "33.651934000", + "lng": "-117.728984000" + }, + { + "lat": "33.651757000", + "lng": "-117.728739000" + }, + { + "lat": "33.651590000", + "lng": "-117.728479000" + }, + { + "lat": "33.651444000", + "lng": "-117.728267000" + }, + { + "lat": "33.651245000", + "lng": "-117.727989000" + }, + { + "lat": "33.651149000", + "lng": "-117.727865000" + }, + { + "lat": "33.651099000", + "lng": "-117.727801000" + }, + { + "lat": "33.651077000", + "lng": "-117.727772000" + }, + { + "lat": "33.650864000", + "lng": "-117.727478000" + }, + { + "lat": "33.650616000", + "lng": "-117.727120000" + }, + { + "lat": "33.650542000", + "lng": "-117.727019000" + }, + { + "lat": "33.650441000", + "lng": "-117.726883000" + }, + { + "lat": "33.650367000", + "lng": "-117.726782000" + }, + { + "lat": "33.650164000", + "lng": "-117.726535000" + }, + { + "lat": "33.649869000", + "lng": "-117.726265000" + }, + { + "lat": "33.649658000", + "lng": "-117.726087000" + }, + { + "lat": "33.649501000", + "lng": "-117.725965000" + }, + { + "lat": "33.649365000", + "lng": "-117.725863000" + }, + { + "lat": "33.649307000", + "lng": "-117.725823000" + }, + { + "lat": "33.649155000", + "lng": "-117.725720000" + }, + { + "lat": "33.648915000", + "lng": "-117.725580000" + }, + { + "lat": "33.648690000", + "lng": "-117.725464000" + }, + { + "lat": "33.648478000", + "lng": "-117.725378000" + }, + { + "lat": "33.648191000", + "lng": "-117.725279000" + }, + { + "lat": "33.648167000", + "lng": "-117.725271000" + }, + { + "lat": "33.648061000", + "lng": "-117.725160000" + }, + { + "lat": "33.647928000", + "lng": "-117.725115000" + }, + { + "lat": "33.647964000", + "lng": "-117.724934000" + }, + { + "lat": "33.647994000", + "lng": "-117.724803000" + }, + { + "lat": "33.648032000", + "lng": "-117.724639000" + }, + { + "lat": "33.648082000", + "lng": "-117.724447000" + }, + { + "lat": "33.648141000", + "lng": "-117.724263000" + }, + { + "lat": "33.648221000", + "lng": "-117.724052000" + }, + { + "lat": "33.648306000", + "lng": "-117.723846000" + }, + { + "lat": "33.648385000", + "lng": "-117.723668000" + }, + { + "lat": "33.648466000", + "lng": "-117.723491000" + }, + { + "lat": "33.648596000", + "lng": "-117.723235000" + }, + { + "lat": "33.648667000", + "lng": "-117.723105000" + }, + { + "lat": "33.648740000", + "lng": "-117.722978000" + }, + { + "lat": "33.649200000", + "lng": "-117.722206000" + }, + { + "lat": "33.649565000", + "lng": "-117.721583000" + }, + { + "lat": "33.650139000", + "lng": "-117.720608000" + }, + { + "lat": "33.650313000", + "lng": "-117.720310000" + }, + { + "lat": "33.650493000", + "lng": "-117.720000000" + }, + { + "lat": "33.650609000", + "lng": "-117.719812000" + }, + { + "lat": "33.650665000", + "lng": "-117.719535000" + }, + { + "lat": "33.650666000", + "lng": "-117.719513000" + }, + { + "lat": "33.650667000", + "lng": "-117.719489000" + }, + { + "lat": "33.650656000", + "lng": "-117.719415000" + }, + { + "lat": "33.650611000", + "lng": "-117.719233000" + }, + { + "lat": "33.650594000", + "lng": "-117.719166000" + }, + { + "lat": "33.650347000", + "lng": "-117.718813000" + }, + { + "lat": "33.650181000", + "lng": "-117.718579000" + }, + { + "lat": "33.649887000", + "lng": "-117.718154000" + }, + { + "lat": "33.649758000", + "lng": "-117.717961000" + }, + { + "lat": "33.649834000", + "lng": "-117.717895000" + }, + { + "lat": "33.650000000", + "lng": "-117.717751000" + }, + { + "lat": "33.650053000", + "lng": "-117.717824000" + }, + { + "lat": "33.650159000", + "lng": "-117.717968000" + }, + { + "lat": "33.650460000", + "lng": "-117.718379000" + }, + { + "lat": "33.650855000", + "lng": "-117.718919000" + }, + { + "lat": "33.651006000", + "lng": "-117.718657000" + }, + { + "lat": "33.651203000", + "lng": "-117.718314000" + }, + { + "lat": "33.650630000", + "lng": "-117.717499000" + }, + { + "lat": "33.650529000", + "lng": "-117.717354000" + }, + { + "lat": "33.650422000", + "lng": "-117.717201000" + }, + { + "lat": "33.650313000", + "lng": "-117.717044000" + }, + { + "lat": "33.649989000", + "lng": "-117.717360000" + }, + { + "lat": "33.649834000", + "lng": "-117.717510000" + }, + { + "lat": "33.649939000", + "lng": "-117.717666000" + }, + { + "lat": "33.650000000", + "lng": "-117.717751000" + }, + { + "lat": "33.649758000", + "lng": "-117.717961000" + }, + { + "lat": "33.649887000", + "lng": "-117.718154000" + }, + { + "lat": "33.650181000", + "lng": "-117.718579000" + }, + { + "lat": "33.650347000", + "lng": "-117.718813000" + }, + { + "lat": "33.650594000", + "lng": "-117.719166000" + }, + { + "lat": "33.650743000", + "lng": "-117.719372000" + }, + { + "lat": "33.650809000", + "lng": "-117.719463000" + }, + { + "lat": "33.650920000", + "lng": "-117.719587000" + }, + { + "lat": "33.650844000", + "lng": "-117.719704000" + }, + { + "lat": "33.650718000", + "lng": "-117.719924000" + }, + { + "lat": "33.650618000", + "lng": "-117.720084000" + }, + { + "lat": "33.650326000", + "lng": "-117.720582000" + }, + { + "lat": "33.649993000", + "lng": "-117.721139000" + }, + { + "lat": "33.649649000", + "lng": "-117.721714000" + }, + { + "lat": "33.649295000", + "lng": "-117.722307000" + }, + { + "lat": "33.649188000", + "lng": "-117.722484000" + }, + { + "lat": "33.649069000", + "lng": "-117.722687000" + }, + { + "lat": "33.648916000", + "lng": "-117.722946000" + }, + { + "lat": "33.648842000", + "lng": "-117.723073000" + }, + { + "lat": "33.648740000", + "lng": "-117.723265000" + }, + { + "lat": "33.648666000", + "lng": "-117.723406000" + }, + { + "lat": "33.648610000", + "lng": "-117.723528000" + }, + { + "lat": "33.648574000", + "lng": "-117.723605000" + }, + { + "lat": "33.648526000", + "lng": "-117.723713000" + }, + { + "lat": "33.648420000", + "lng": "-117.723964000" + }, + { + "lat": "33.648359000", + "lng": "-117.724118000" + }, + { + "lat": "33.648314000", + "lng": "-117.724240000" + }, + { + "lat": "33.648236000", + "lng": "-117.724482000" + }, + { + "lat": "33.648191000", + "lng": "-117.724635000" + }, + { + "lat": "33.648207000", + "lng": "-117.724890000" + }, + { + "lat": "33.648234000", + "lng": "-117.724990000" + }, + { + "lat": "33.648244000", + "lng": "-117.725005000" + }, + { + "lat": "33.648309000", + "lng": "-117.725098000" + }, + { + "lat": "33.648511000", + "lng": "-117.725255000" + }, + { + "lat": "33.648637000", + "lng": "-117.725308000" + }, + { + "lat": "33.648839000", + "lng": "-117.725393000" + }, + { + "lat": "33.648959000", + "lng": "-117.725444000" + }, + { + "lat": "33.649341000", + "lng": "-117.725681000" + }, + { + "lat": "33.649542000", + "lng": "-117.725832000" + }, + { + "lat": "33.649669000", + "lng": "-117.725929000" + }, + { + "lat": "33.649828000", + "lng": "-117.726058000" + }, + { + "lat": "33.650044000", + "lng": "-117.726253000" + }, + { + "lat": "33.650265000", + "lng": "-117.726473000" + }, + { + "lat": "33.650539000", + "lng": "-117.726786000" + }, + { + "lat": "33.650637000", + "lng": "-117.726927000" + }, + { + "lat": "33.651363000", + "lng": "-117.727909000" + }, + { + "lat": "33.651818000", + "lng": "-117.728548000" + }, + { + "lat": "33.651925000", + "lng": "-117.728702000" + }, + { + "lat": "33.652189000", + "lng": "-117.729080000" + }, + { + "lat": "33.652243000", + "lng": "-117.729154000" + }, + { + "lat": "33.652334000", + "lng": "-117.729281000" + }, + { + "lat": "33.652410000", + "lng": "-117.729396000" + }, + { + "lat": "33.653339000", + "lng": "-117.730764000" + }, + { + "lat": "33.653763000", + "lng": "-117.731387000" + }, + { + "lat": "33.653820000", + "lng": "-117.731471000" + }, + { + "lat": "33.653913000", + "lng": "-117.731608000" + }, + { + "lat": "33.654905000", + "lng": "-117.732979000" + }, + { + "lat": "33.654978000", + "lng": "-117.732909000" + }, + { + "lat": "33.655088000", + "lng": "-117.732804000" + }, + { + "lat": "33.655369000", + "lng": "-117.732536000" + }, + { + "lat": "33.655526000", + "lng": "-117.732453000" + }, + { + "lat": "33.656076000", + "lng": "-117.732351000" + }, + { + "lat": "33.656169000", + "lng": "-117.732338000" + }, + { + "lat": "33.656268000", + "lng": "-117.732328000" + }, + { + "lat": "33.656408000", + "lng": "-117.732314000" + }, + { + "lat": "33.656481000", + "lng": "-117.732417000" + }, + { + "lat": "33.656845000", + "lng": "-117.732932000" + }, + { + "lat": "33.656848000", + "lng": "-117.733019000" + }, + { + "lat": "33.656827000", + "lng": "-117.733099000" + }, + { + "lat": "33.656822000", + "lng": "-117.733111000" + }, + { + "lat": "33.656785000", + "lng": "-117.733145000" + } + ] + ], + "54191": [ + [ + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793230000", + "lng": "-117.856356000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787891000", + "lng": "-117.856783000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787893000", + "lng": "-117.856979000" + }, + { + "lat": "33.787933000", + "lng": "-117.857043000" + }, + { + "lat": "33.787933000", + "lng": "-117.857458000" + }, + { + "lat": "33.787933000", + "lng": "-117.857518000" + }, + { + "lat": "33.787933000", + "lng": "-117.857827000" + }, + { + "lat": "33.787933000", + "lng": "-117.857907000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787938000", + "lng": "-117.865679000" + }, + { + "lat": "33.787938000", + "lng": "-117.866004000" + }, + { + "lat": "33.787939000", + "lng": "-117.866335000" + }, + { + "lat": "33.787940000", + "lng": "-117.866502000" + }, + { + "lat": "33.787940000", + "lng": "-117.866645000" + }, + { + "lat": "33.787941000", + "lng": "-117.866964000" + }, + { + "lat": "33.787942000", + "lng": "-117.867104000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.872161000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787940000", + "lng": "-117.878721000" + }, + { + "lat": "33.787946000", + "lng": "-117.878943000" + }, + { + "lat": "33.787950000", + "lng": "-117.879220000" + }, + { + "lat": "33.787947000", + "lng": "-117.879543000" + }, + { + "lat": "33.787932000", + "lng": "-117.880310000" + }, + { + "lat": "33.787929000", + "lng": "-117.880465000" + }, + { + "lat": "33.787930000", + "lng": "-117.880566000" + }, + { + "lat": "33.787930000", + "lng": "-117.880625000" + }, + { + "lat": "33.787932000", + "lng": "-117.881015000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789638000", + "lng": "-117.886143000" + }, + { + "lat": "33.789733000", + "lng": "-117.886236000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789573000", + "lng": "-117.886197000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789306000", + "lng": "-117.886505000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789467000", + "lng": "-117.888536000" + }, + { + "lat": "33.789477000", + "lng": "-117.888629000" + }, + { + "lat": "33.789431000", + "lng": "-117.888858000" + }, + { + "lat": "33.789193000", + "lng": "-117.889833000" + }, + { + "lat": "33.789079000", + "lng": "-117.890474000" + }, + { + "lat": "33.789070000", + "lng": "-117.890540000" + }, + { + "lat": "33.789050000", + "lng": "-117.890692000" + }, + { + "lat": "33.789213000", + "lng": "-117.890685000" + }, + { + "lat": "33.789240000", + "lng": "-117.890682000" + }, + { + "lat": "33.789443000", + "lng": "-117.890661000" + }, + { + "lat": "33.789572000", + "lng": "-117.890639000" + }, + { + "lat": "33.789673000", + "lng": "-117.890617000" + }, + { + "lat": "33.789791000", + "lng": "-117.890583000" + }, + { + "lat": "33.789972000", + "lng": "-117.890523000" + }, + { + "lat": "33.789994000", + "lng": "-117.890515000" + }, + { + "lat": "33.790393000", + "lng": "-117.890382000" + }, + { + "lat": "33.790715000", + "lng": "-117.890275000" + }, + { + "lat": "33.790840000", + "lng": "-117.890233000" + }, + { + "lat": "33.791287000", + "lng": "-117.890090000" + }, + { + "lat": "33.791676000", + "lng": "-117.889959000" + }, + { + "lat": "33.791969000", + "lng": "-117.889853000" + }, + { + "lat": "33.792429000", + "lng": "-117.889707000" + }, + { + "lat": "33.792554000", + "lng": "-117.889667000" + }, + { + "lat": "33.792652000", + "lng": "-117.889635000" + }, + { + "lat": "33.793067000", + "lng": "-117.889526000" + }, + { + "lat": "33.793455000", + "lng": "-117.889409000" + }, + { + "lat": "33.793623000", + "lng": "-117.889359000" + }, + { + "lat": "33.794047000", + "lng": "-117.889238000" + }, + { + "lat": "33.794232000", + "lng": "-117.889198000" + }, + { + "lat": "33.794418000", + "lng": "-117.889168000" + }, + { + "lat": "33.794570000", + "lng": "-117.889154000" + }, + { + "lat": "33.794724000", + "lng": "-117.889139000" + }, + { + "lat": "33.794892000", + "lng": "-117.889128000" + }, + { + "lat": "33.795108000", + "lng": "-117.889122000" + }, + { + "lat": "33.795424000", + "lng": "-117.889117000" + }, + { + "lat": "33.795532000", + "lng": "-117.889111000" + }, + { + "lat": "33.795727000", + "lng": "-117.889100000" + }, + { + "lat": "33.795934000", + "lng": "-117.889091000" + }, + { + "lat": "33.796137000", + "lng": "-117.889082000" + }, + { + "lat": "33.796513000", + "lng": "-117.889083000" + }, + { + "lat": "33.796740000", + "lng": "-117.889083000" + }, + { + "lat": "33.797121000", + "lng": "-117.889083000" + }, + { + "lat": "33.797353000", + "lng": "-117.889084000" + }, + { + "lat": "33.797687000", + "lng": "-117.889084000" + }, + { + "lat": "33.797876000", + "lng": "-117.889085000" + }, + { + "lat": "33.798169000", + "lng": "-117.889089000" + }, + { + "lat": "33.798868000", + "lng": "-117.889102000" + }, + { + "lat": "33.799531000", + "lng": "-117.889114000" + }, + { + "lat": "33.799563000", + "lng": "-117.889117000" + }, + { + "lat": "33.799711000", + "lng": "-117.889176000" + }, + { + "lat": "33.799711000", + "lng": "-117.889396000" + }, + { + "lat": "33.799711500", + "lng": "-117.889617000" + }, + { + "lat": "33.799712000", + "lng": "-117.889838000" + }, + { + "lat": "33.799712000", + "lng": "-117.890642000" + }, + { + "lat": "33.799556000", + "lng": "-117.890647000" + }, + { + "lat": "33.799500000", + "lng": "-117.890647000" + }, + { + "lat": "33.797874000", + "lng": "-117.890640000" + }, + { + "lat": "33.797874000", + "lng": "-117.890360000" + }, + { + "lat": "33.797874000", + "lng": "-117.889265000" + }, + { + "lat": "33.797849000", + "lng": "-117.889265000" + }, + { + "lat": "33.797103000", + "lng": "-117.889280000" + }, + { + "lat": "33.796975000", + "lng": "-117.889282000" + }, + { + "lat": "33.796354000", + "lng": "-117.889295000" + }, + { + "lat": "33.796134000", + "lng": "-117.889299000" + }, + { + "lat": "33.796133000", + "lng": "-117.889494000" + }, + { + "lat": "33.796133000", + "lng": "-117.889536000" + }, + { + "lat": "33.796132000", + "lng": "-117.890043000" + }, + { + "lat": "33.796132000", + "lng": "-117.890170000" + }, + { + "lat": "33.796130000", + "lng": "-117.890704000" + }, + { + "lat": "33.796123000", + "lng": "-117.891098000" + }, + { + "lat": "33.796187000", + "lng": "-117.891393000" + }, + { + "lat": "33.796219000", + "lng": "-117.891505000" + }, + { + "lat": "33.796219000", + "lng": "-117.891519000" + }, + { + "lat": "33.796220000", + "lng": "-117.891705000" + }, + { + "lat": "33.796220000", + "lng": "-117.892011000" + }, + { + "lat": "33.796221000", + "lng": "-117.892156000" + }, + { + "lat": "33.796220000", + "lng": "-117.892656000" + }, + { + "lat": "33.796218000", + "lng": "-117.893194000" + }, + { + "lat": "33.796221000", + "lng": "-117.893779000" + }, + { + "lat": "33.796221000", + "lng": "-117.893826000" + }, + { + "lat": "33.796222000", + "lng": "-117.893992000" + }, + { + "lat": "33.796349000", + "lng": "-117.894127000" + }, + { + "lat": "33.796970000", + "lng": "-117.894781000" + }, + { + "lat": "33.797375000", + "lng": "-117.895274000" + }, + { + "lat": "33.797553000", + "lng": "-117.895460000" + }, + { + "lat": "33.797906000", + "lng": "-117.895831000" + }, + { + "lat": "33.798837000", + "lng": "-117.896728000" + }, + { + "lat": "33.799199000", + "lng": "-117.897077000" + }, + { + "lat": "33.799409000", + "lng": "-117.897262000" + }, + { + "lat": "33.799531000", + "lng": "-117.897349000" + }, + { + "lat": "33.799914000", + "lng": "-117.897622000" + }, + { + "lat": "33.800647000", + "lng": "-117.898145000" + }, + { + "lat": "33.800834000", + "lng": "-117.898141000" + }, + { + "lat": "33.800882000", + "lng": "-117.898130000" + }, + { + "lat": "33.800913000", + "lng": "-117.898110000" + }, + { + "lat": "33.800971000", + "lng": "-117.898060000" + }, + { + "lat": "33.801007000", + "lng": "-117.898010000" + }, + { + "lat": "33.801065000", + "lng": "-117.897961000" + }, + { + "lat": "33.801111000", + "lng": "-117.897921000" + }, + { + "lat": "33.801157000", + "lng": "-117.897885000" + }, + { + "lat": "33.801252000", + "lng": "-117.897844000" + }, + { + "lat": "33.801328000", + "lng": "-117.897829000" + }, + { + "lat": "33.801397000", + "lng": "-117.897823000" + }, + { + "lat": "33.801400000", + "lng": "-117.897823000" + }, + { + "lat": "33.801560000", + "lng": "-117.897830000" + }, + { + "lat": "33.801856000", + "lng": "-117.897841000" + }, + { + "lat": "33.801885000", + "lng": "-117.897842000" + }, + { + "lat": "33.802027000", + "lng": "-117.897848000" + }, + { + "lat": "33.802583000", + "lng": "-117.897870000" + }, + { + "lat": "33.802692000", + "lng": "-117.897874000" + }, + { + "lat": "33.802740000", + "lng": "-117.897876000" + }, + { + "lat": "33.802863000", + "lng": "-117.897881000" + }, + { + "lat": "33.802899000", + "lng": "-117.897882000" + }, + { + "lat": "33.802955000", + "lng": "-117.897884000" + }, + { + "lat": "33.803170000", + "lng": "-117.897893000" + }, + { + "lat": "33.803276000", + "lng": "-117.897904000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803855000", + "lng": "-117.897913000" + }, + { + "lat": "33.804052000", + "lng": "-117.897914000" + }, + { + "lat": "33.804235000", + "lng": "-117.897916000" + }, + { + "lat": "33.804746000", + "lng": "-117.897919000" + }, + { + "lat": "33.805197000", + "lng": "-117.897922000" + }, + { + "lat": "33.805198000", + "lng": "-117.897256000" + }, + { + "lat": "33.805199000", + "lng": "-117.896883000" + }, + { + "lat": "33.805194000", + "lng": "-117.895951000" + }, + { + "lat": "33.805184000", + "lng": "-117.895913000" + }, + { + "lat": "33.805155000", + "lng": "-117.895877000" + }, + { + "lat": "33.805109000", + "lng": "-117.895855000" + }, + { + "lat": "33.804577000", + "lng": "-117.895853000" + }, + { + "lat": "33.804278000", + "lng": "-117.895852000" + }, + { + "lat": "33.803586000", + "lng": "-117.895845000" + }, + { + "lat": "33.803438000", + "lng": "-117.895845000" + }, + { + "lat": "33.803435000", + "lng": "-117.896293000" + }, + { + "lat": "33.803431000", + "lng": "-117.896870000" + }, + { + "lat": "33.803428000", + "lng": "-117.897051000" + }, + { + "lat": "33.803425000", + "lng": "-117.897278000" + }, + { + "lat": "33.803424000", + "lng": "-117.897351000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803404000", + "lng": "-117.898058000" + }, + { + "lat": "33.803411000", + "lng": "-117.898721000" + }, + { + "lat": "33.803415000", + "lng": "-117.899152000" + }, + { + "lat": "33.803418000", + "lng": "-117.899238000" + }, + { + "lat": "33.803422000", + "lng": "-117.899462000" + }, + { + "lat": "33.803435000", + "lng": "-117.899958000" + }, + { + "lat": "33.803436000", + "lng": "-117.900207000" + }, + { + "lat": "33.803441000", + "lng": "-117.900911000" + }, + { + "lat": "33.803438000", + "lng": "-117.901150000" + }, + { + "lat": "33.803434000", + "lng": "-117.901409000" + }, + { + "lat": "33.803424000", + "lng": "-117.903146000" + }, + { + "lat": "33.803436000", + "lng": "-117.903749000" + }, + { + "lat": "33.803445000", + "lng": "-117.904164000" + }, + { + "lat": "33.803257000", + "lng": "-117.904204000" + }, + { + "lat": "33.803135000", + "lng": "-117.904206000" + }, + { + "lat": "33.803043000", + "lng": "-117.904209000" + }, + { + "lat": "33.802649000", + "lng": "-117.904221000" + }, + { + "lat": "33.802399000", + "lng": "-117.904180000" + }, + { + "lat": "33.802255000", + "lng": "-117.904083000" + }, + { + "lat": "33.802167000", + "lng": "-117.903990000" + }, + { + "lat": "33.802157000", + "lng": "-117.903976000" + }, + { + "lat": "33.802120000", + "lng": "-117.903921000" + }, + { + "lat": "33.802043000", + "lng": "-117.903771000" + }, + { + "lat": "33.802017000", + "lng": "-117.903673000" + }, + { + "lat": "33.801993000", + "lng": "-117.903558000" + }, + { + "lat": "33.801987000", + "lng": "-117.903450000" + }, + { + "lat": "33.801983000", + "lng": "-117.902367000" + }, + { + "lat": "33.801948000", + "lng": "-117.902095000" + }, + { + "lat": "33.801926000", + "lng": "-117.902026000" + }, + { + "lat": "33.801903000", + "lng": "-117.901956000" + }, + { + "lat": "33.801839000", + "lng": "-117.901826000" + }, + { + "lat": "33.801786000", + "lng": "-117.901719000" + }, + { + "lat": "33.801701000", + "lng": "-117.901609000" + }, + { + "lat": "33.801253000", + "lng": "-117.901144000" + }, + { + "lat": "33.801145000", + "lng": "-117.901027000" + }, + { + "lat": "33.801071000", + "lng": "-117.900947000" + }, + { + "lat": "33.801056000", + "lng": "-117.900930000" + }, + { + "lat": "33.800919000", + "lng": "-117.900784000" + }, + { + "lat": "33.800634000", + "lng": "-117.900488000" + }, + { + "lat": "33.800628000", + "lng": "-117.900482000" + }, + { + "lat": "33.800479000", + "lng": "-117.900333000" + }, + { + "lat": "33.799921000", + "lng": "-117.899744000" + }, + { + "lat": "33.799472000", + "lng": "-117.899273000" + }, + { + "lat": "33.799209000", + "lng": "-117.898995000" + }, + { + "lat": "33.799060000", + "lng": "-117.898839000" + }, + { + "lat": "33.798842000", + "lng": "-117.898600000" + }, + { + "lat": "33.798741000", + "lng": "-117.898492000" + }, + { + "lat": "33.798514000", + "lng": "-117.898254000" + }, + { + "lat": "33.798244000", + "lng": "-117.897975000" + }, + { + "lat": "33.797300000", + "lng": "-117.896978000" + }, + { + "lat": "33.797195000", + "lng": "-117.896868000" + }, + { + "lat": "33.796934000", + "lng": "-117.896600000" + }, + { + "lat": "33.796921000", + "lng": "-117.896587000" + }, + { + "lat": "33.796358000", + "lng": "-117.896012000" + }, + { + "lat": "33.796335000", + "lng": "-117.895988000" + }, + { + "lat": "33.796200000", + "lng": "-117.895850000" + }, + { + "lat": "33.796072000", + "lng": "-117.895716000" + }, + { + "lat": "33.795970000", + "lng": "-117.895613000" + }, + { + "lat": "33.795890000", + "lng": "-117.895532000" + }, + { + "lat": "33.795832000", + "lng": "-117.895474000" + }, + { + "lat": "33.795668000", + "lng": "-117.895309000" + }, + { + "lat": "33.795460000", + "lng": "-117.895097000" + }, + { + "lat": "33.795195000", + "lng": "-117.894826000" + }, + { + "lat": "33.794579000", + "lng": "-117.894189000" + }, + { + "lat": "33.794425000", + "lng": "-117.894039000" + }, + { + "lat": "33.794288000", + "lng": "-117.893906000" + }, + { + "lat": "33.794180000", + "lng": "-117.893804000" + }, + { + "lat": "33.794062000", + "lng": "-117.893702000" + }, + { + "lat": "33.793960000", + "lng": "-117.893618000" + }, + { + "lat": "33.793937000", + "lng": "-117.893601000" + }, + { + "lat": "33.793865000", + "lng": "-117.893551000" + }, + { + "lat": "33.793759000", + "lng": "-117.893476000" + }, + { + "lat": "33.793631000", + "lng": "-117.893388000" + }, + { + "lat": "33.793332000", + "lng": "-117.893181000" + }, + { + "lat": "33.793226000", + "lng": "-117.893108000" + }, + { + "lat": "33.793044000", + "lng": "-117.892984000" + }, + { + "lat": "33.792893000", + "lng": "-117.892889000" + }, + { + "lat": "33.792622000", + "lng": "-117.892731000" + }, + { + "lat": "33.792372000", + "lng": "-117.892583000" + }, + { + "lat": "33.792252000", + "lng": "-117.892527000" + }, + { + "lat": "33.792160000", + "lng": "-117.892494000" + }, + { + "lat": "33.792070000", + "lng": "-117.892472000" + }, + { + "lat": "33.791975000", + "lng": "-117.892457000" + }, + { + "lat": "33.791875000", + "lng": "-117.892450000" + }, + { + "lat": "33.791768000", + "lng": "-117.892452000" + }, + { + "lat": "33.791662000", + "lng": "-117.892462000" + }, + { + "lat": "33.791550000", + "lng": "-117.892486000" + }, + { + "lat": "33.791502000", + "lng": "-117.892502000" + }, + { + "lat": "33.791409000", + "lng": "-117.892539000" + }, + { + "lat": "33.791328000", + "lng": "-117.892581000" + }, + { + "lat": "33.791066000", + "lng": "-117.892748000" + }, + { + "lat": "33.790967000", + "lng": "-117.892830000" + }, + { + "lat": "33.790931000", + "lng": "-117.892855000" + }, + { + "lat": "33.790832000", + "lng": "-117.892915000" + }, + { + "lat": "33.790730000", + "lng": "-117.892990000" + }, + { + "lat": "33.790693000", + "lng": "-117.893015000" + }, + { + "lat": "33.790582000", + "lng": "-117.893076000" + }, + { + "lat": "33.790522000", + "lng": "-117.893100000" + }, + { + "lat": "33.790457000", + "lng": "-117.893121000" + }, + { + "lat": "33.790396000", + "lng": "-117.893138000" + }, + { + "lat": "33.790328000", + "lng": "-117.893149000" + }, + { + "lat": "33.790258000", + "lng": "-117.893155000" + }, + { + "lat": "33.790169000", + "lng": "-117.893159000" + }, + { + "lat": "33.790044000", + "lng": "-117.893159000" + }, + { + "lat": "33.789930000", + "lng": "-117.893134000" + }, + { + "lat": "33.789683000", + "lng": "-117.893146000" + }, + { + "lat": "33.789567000", + "lng": "-117.893145000" + }, + { + "lat": "33.789512000", + "lng": "-117.893146000" + }, + { + "lat": "33.789169000", + "lng": "-117.893144000" + }, + { + "lat": "33.789145000", + "lng": "-117.893144000" + }, + { + "lat": "33.789016000", + "lng": "-117.893145000" + }, + { + "lat": "33.788898000", + "lng": "-117.893146000" + }, + { + "lat": "33.788902000", + "lng": "-117.892245000" + }, + { + "lat": "33.788902000", + "lng": "-117.892228000" + }, + { + "lat": "33.788905000", + "lng": "-117.892119000" + }, + { + "lat": "33.788903000", + "lng": "-117.891973000" + }, + { + "lat": "33.788903000", + "lng": "-117.891704000" + }, + { + "lat": "33.788903000", + "lng": "-117.891117000" + }, + { + "lat": "33.788903000", + "lng": "-117.890936000" + }, + { + "lat": "33.788904000", + "lng": "-117.890700000" + }, + { + "lat": "33.788909000", + "lng": "-117.890516000" + }, + { + "lat": "33.788913000", + "lng": "-117.890489000" + }, + { + "lat": "33.788954000", + "lng": "-117.890197000" + }, + { + "lat": "33.789050000", + "lng": "-117.889708000" + }, + { + "lat": "33.789086000", + "lng": "-117.889537000" + }, + { + "lat": "33.789321000", + "lng": "-117.888520000" + }, + { + "lat": "33.789397000", + "lng": "-117.888460000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789336000", + "lng": "-117.886428000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789732000", + "lng": "-117.886235000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789589000", + "lng": "-117.886174000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789241000", + "lng": "-117.886328000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787837000", + "lng": "-117.881017000" + }, + { + "lat": "33.787840000", + "lng": "-117.880648000" + }, + { + "lat": "33.787840000", + "lng": "-117.880625000" + }, + { + "lat": "33.787841000", + "lng": "-117.880435000" + }, + { + "lat": "33.787847000", + "lng": "-117.879556000" + }, + { + "lat": "33.787844000", + "lng": "-117.879130000" + }, + { + "lat": "33.787844000", + "lng": "-117.879052000" + }, + { + "lat": "33.787843000", + "lng": "-117.878851000" + }, + { + "lat": "33.787842000", + "lng": "-117.878720000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787887000", + "lng": "-117.875554000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787838000", + "lng": "-117.867107000" + }, + { + "lat": "33.787838000", + "lng": "-117.866715000" + }, + { + "lat": "33.787838000", + "lng": "-117.866531000" + }, + { + "lat": "33.787838000", + "lng": "-117.866114000" + }, + { + "lat": "33.787838000", + "lng": "-117.865902000" + }, + { + "lat": "33.787838000", + "lng": "-117.865670000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787846000", + "lng": "-117.857894000" + }, + { + "lat": "33.787846000", + "lng": "-117.857828000" + }, + { + "lat": "33.787846000", + "lng": "-117.857771000" + }, + { + "lat": "33.787847000", + "lng": "-117.857518000" + }, + { + "lat": "33.787848000", + "lng": "-117.857460000" + }, + { + "lat": "33.787848000", + "lng": "-117.857265000" + }, + { + "lat": "33.787849000", + "lng": "-117.857090000" + }, + { + "lat": "33.787849000", + "lng": "-117.857041000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.788076000", + "lng": "-117.856372000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793322000", + "lng": "-117.855591000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793325000", + "lng": "-117.852810000" + } + ] + ], + "54256": [ + [ + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793230000", + "lng": "-117.856356000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787891000", + "lng": "-117.856783000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787893000", + "lng": "-117.856979000" + }, + { + "lat": "33.787933000", + "lng": "-117.857043000" + }, + { + "lat": "33.787933000", + "lng": "-117.857458000" + }, + { + "lat": "33.787933000", + "lng": "-117.857518000" + }, + { + "lat": "33.787933000", + "lng": "-117.857827000" + }, + { + "lat": "33.787933000", + "lng": "-117.857907000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787938000", + "lng": "-117.865679000" + }, + { + "lat": "33.787938000", + "lng": "-117.866004000" + }, + { + "lat": "33.787939000", + "lng": "-117.866335000" + }, + { + "lat": "33.787940000", + "lng": "-117.866502000" + }, + { + "lat": "33.787940000", + "lng": "-117.866645000" + }, + { + "lat": "33.787941000", + "lng": "-117.866964000" + }, + { + "lat": "33.787942000", + "lng": "-117.867104000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.872161000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787940000", + "lng": "-117.878721000" + }, + { + "lat": "33.787946000", + "lng": "-117.878943000" + }, + { + "lat": "33.787950000", + "lng": "-117.879220000" + }, + { + "lat": "33.787947000", + "lng": "-117.879543000" + }, + { + "lat": "33.787932000", + "lng": "-117.880310000" + }, + { + "lat": "33.787929000", + "lng": "-117.880465000" + }, + { + "lat": "33.787930000", + "lng": "-117.880566000" + }, + { + "lat": "33.787930000", + "lng": "-117.880625000" + }, + { + "lat": "33.787932000", + "lng": "-117.881015000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789638000", + "lng": "-117.886143000" + }, + { + "lat": "33.789733000", + "lng": "-117.886236000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789573000", + "lng": "-117.886197000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789306000", + "lng": "-117.886505000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789467000", + "lng": "-117.888536000" + }, + { + "lat": "33.789477000", + "lng": "-117.888629000" + }, + { + "lat": "33.789431000", + "lng": "-117.888858000" + }, + { + "lat": "33.789193000", + "lng": "-117.889833000" + }, + { + "lat": "33.789079000", + "lng": "-117.890474000" + }, + { + "lat": "33.789070000", + "lng": "-117.890540000" + }, + { + "lat": "33.789050000", + "lng": "-117.890692000" + }, + { + "lat": "33.789213000", + "lng": "-117.890685000" + }, + { + "lat": "33.789240000", + "lng": "-117.890682000" + }, + { + "lat": "33.789443000", + "lng": "-117.890661000" + }, + { + "lat": "33.789572000", + "lng": "-117.890639000" + }, + { + "lat": "33.789673000", + "lng": "-117.890617000" + }, + { + "lat": "33.789791000", + "lng": "-117.890583000" + }, + { + "lat": "33.789972000", + "lng": "-117.890523000" + }, + { + "lat": "33.789994000", + "lng": "-117.890515000" + }, + { + "lat": "33.790393000", + "lng": "-117.890382000" + }, + { + "lat": "33.790715000", + "lng": "-117.890275000" + }, + { + "lat": "33.790840000", + "lng": "-117.890233000" + }, + { + "lat": "33.791287000", + "lng": "-117.890090000" + }, + { + "lat": "33.791676000", + "lng": "-117.889959000" + }, + { + "lat": "33.791969000", + "lng": "-117.889853000" + }, + { + "lat": "33.792429000", + "lng": "-117.889707000" + }, + { + "lat": "33.792554000", + "lng": "-117.889667000" + }, + { + "lat": "33.792652000", + "lng": "-117.889635000" + }, + { + "lat": "33.792685000", + "lng": "-117.889920000" + }, + { + "lat": "33.792730000", + "lng": "-117.890076000" + }, + { + "lat": "33.792770000", + "lng": "-117.890207000" + }, + { + "lat": "33.792786000", + "lng": "-117.890241000" + }, + { + "lat": "33.792827000", + "lng": "-117.890330000" + }, + { + "lat": "33.792888000", + "lng": "-117.890452000" + }, + { + "lat": "33.792974000", + "lng": "-117.890591000" + }, + { + "lat": "33.793067000", + "lng": "-117.890702000" + }, + { + "lat": "33.795778000", + "lng": "-117.893533000" + }, + { + "lat": "33.795942000", + "lng": "-117.893702000" + }, + { + "lat": "33.795971000", + "lng": "-117.893732000" + }, + { + "lat": "33.796079000", + "lng": "-117.893843000" + }, + { + "lat": "33.796222000", + "lng": "-117.893992000" + }, + { + "lat": "33.796349000", + "lng": "-117.894127000" + }, + { + "lat": "33.796970000", + "lng": "-117.894781000" + }, + { + "lat": "33.797375000", + "lng": "-117.895274000" + }, + { + "lat": "33.797906000", + "lng": "-117.895831000" + }, + { + "lat": "33.798837000", + "lng": "-117.896728000" + }, + { + "lat": "33.799199000", + "lng": "-117.897077000" + }, + { + "lat": "33.800647000", + "lng": "-117.898145000" + }, + { + "lat": "33.800834000", + "lng": "-117.898141000" + }, + { + "lat": "33.800882000", + "lng": "-117.898130000" + }, + { + "lat": "33.800928000", + "lng": "-117.898100000" + }, + { + "lat": "33.800932000", + "lng": "-117.898098000" + }, + { + "lat": "33.800971000", + "lng": "-117.898060000" + }, + { + "lat": "33.801007000", + "lng": "-117.898010000" + }, + { + "lat": "33.801111000", + "lng": "-117.897921000" + }, + { + "lat": "33.801157000", + "lng": "-117.897885000" + }, + { + "lat": "33.801252000", + "lng": "-117.897844000" + }, + { + "lat": "33.801328000", + "lng": "-117.897829000" + }, + { + "lat": "33.801397000", + "lng": "-117.897823000" + }, + { + "lat": "33.801400000", + "lng": "-117.897823000" + }, + { + "lat": "33.801560000", + "lng": "-117.897830000" + }, + { + "lat": "33.801856000", + "lng": "-117.897841000" + }, + { + "lat": "33.801885000", + "lng": "-117.897842000" + }, + { + "lat": "33.802027000", + "lng": "-117.897848000" + }, + { + "lat": "33.802583000", + "lng": "-117.897870000" + }, + { + "lat": "33.802692000", + "lng": "-117.897874000" + }, + { + "lat": "33.802740000", + "lng": "-117.897876000" + }, + { + "lat": "33.802863000", + "lng": "-117.897881000" + }, + { + "lat": "33.802899000", + "lng": "-117.897882000" + }, + { + "lat": "33.802955000", + "lng": "-117.897884000" + }, + { + "lat": "33.803170000", + "lng": "-117.897893000" + }, + { + "lat": "33.803276000", + "lng": "-117.897904000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803855000", + "lng": "-117.897913000" + }, + { + "lat": "33.804052000", + "lng": "-117.897914000" + }, + { + "lat": "33.804235000", + "lng": "-117.897916000" + }, + { + "lat": "33.804746000", + "lng": "-117.897919000" + }, + { + "lat": "33.805197000", + "lng": "-117.897922000" + }, + { + "lat": "33.805198000", + "lng": "-117.897512000" + }, + { + "lat": "33.805199000", + "lng": "-117.896883000" + }, + { + "lat": "33.805194000", + "lng": "-117.895951000" + }, + { + "lat": "33.805184000", + "lng": "-117.895913000" + }, + { + "lat": "33.805155000", + "lng": "-117.895877000" + }, + { + "lat": "33.805109000", + "lng": "-117.895855000" + }, + { + "lat": "33.804853000", + "lng": "-117.895854000" + }, + { + "lat": "33.804278000", + "lng": "-117.895852000" + }, + { + "lat": "33.803586000", + "lng": "-117.895845000" + }, + { + "lat": "33.803438000", + "lng": "-117.895845000" + }, + { + "lat": "33.803437000", + "lng": "-117.895988000" + }, + { + "lat": "33.803431000", + "lng": "-117.896870000" + }, + { + "lat": "33.803428000", + "lng": "-117.897051000" + }, + { + "lat": "33.803425000", + "lng": "-117.897278000" + }, + { + "lat": "33.803424000", + "lng": "-117.897351000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803404000", + "lng": "-117.898058000" + }, + { + "lat": "33.803411000", + "lng": "-117.898721000" + }, + { + "lat": "33.803415000", + "lng": "-117.899152000" + }, + { + "lat": "33.803418000", + "lng": "-117.899238000" + }, + { + "lat": "33.803422000", + "lng": "-117.899462000" + }, + { + "lat": "33.803435000", + "lng": "-117.899958000" + }, + { + "lat": "33.803436000", + "lng": "-117.900207000" + }, + { + "lat": "33.803441000", + "lng": "-117.900911000" + }, + { + "lat": "33.803438000", + "lng": "-117.901150000" + }, + { + "lat": "33.803434000", + "lng": "-117.901409000" + }, + { + "lat": "33.803424000", + "lng": "-117.903146000" + }, + { + "lat": "33.803424000", + "lng": "-117.903750000" + }, + { + "lat": "33.803424000", + "lng": "-117.904166000" + }, + { + "lat": "33.803259000", + "lng": "-117.904204000" + }, + { + "lat": "33.803135000", + "lng": "-117.904206000" + }, + { + "lat": "33.802649000", + "lng": "-117.904221000" + }, + { + "lat": "33.802399000", + "lng": "-117.904180000" + }, + { + "lat": "33.802255000", + "lng": "-117.904083000" + }, + { + "lat": "33.802167000", + "lng": "-117.903990000" + }, + { + "lat": "33.802157000", + "lng": "-117.903976000" + }, + { + "lat": "33.802120000", + "lng": "-117.903921000" + }, + { + "lat": "33.802043000", + "lng": "-117.903771000" + }, + { + "lat": "33.802017000", + "lng": "-117.903673000" + }, + { + "lat": "33.801993000", + "lng": "-117.903558000" + }, + { + "lat": "33.801987000", + "lng": "-117.903450000" + }, + { + "lat": "33.801983000", + "lng": "-117.902367000" + }, + { + "lat": "33.801948000", + "lng": "-117.902095000" + }, + { + "lat": "33.801926000", + "lng": "-117.902026000" + }, + { + "lat": "33.801903000", + "lng": "-117.901956000" + }, + { + "lat": "33.801839000", + "lng": "-117.901826000" + }, + { + "lat": "33.801786000", + "lng": "-117.901719000" + }, + { + "lat": "33.801701000", + "lng": "-117.901609000" + }, + { + "lat": "33.801253000", + "lng": "-117.901144000" + }, + { + "lat": "33.801145000", + "lng": "-117.901027000" + }, + { + "lat": "33.801071000", + "lng": "-117.900947000" + }, + { + "lat": "33.801056000", + "lng": "-117.900930000" + }, + { + "lat": "33.800919000", + "lng": "-117.900784000" + }, + { + "lat": "33.800634000", + "lng": "-117.900488000" + }, + { + "lat": "33.800628000", + "lng": "-117.900482000" + }, + { + "lat": "33.800479000", + "lng": "-117.900333000" + }, + { + "lat": "33.799921000", + "lng": "-117.899744000" + }, + { + "lat": "33.799472000", + "lng": "-117.899273000" + }, + { + "lat": "33.799209000", + "lng": "-117.898995000" + }, + { + "lat": "33.799060000", + "lng": "-117.898839000" + }, + { + "lat": "33.798842000", + "lng": "-117.898600000" + }, + { + "lat": "33.798741000", + "lng": "-117.898492000" + }, + { + "lat": "33.798514000", + "lng": "-117.898254000" + }, + { + "lat": "33.798244000", + "lng": "-117.897975000" + }, + { + "lat": "33.797300000", + "lng": "-117.896978000" + }, + { + "lat": "33.797195000", + "lng": "-117.896868000" + }, + { + "lat": "33.796934000", + "lng": "-117.896600000" + }, + { + "lat": "33.796921000", + "lng": "-117.896587000" + }, + { + "lat": "33.796358000", + "lng": "-117.896012000" + }, + { + "lat": "33.796335000", + "lng": "-117.895988000" + }, + { + "lat": "33.796200000", + "lng": "-117.895850000" + }, + { + "lat": "33.796072000", + "lng": "-117.895716000" + }, + { + "lat": "33.795970000", + "lng": "-117.895613000" + }, + { + "lat": "33.795890000", + "lng": "-117.895532000" + }, + { + "lat": "33.795832000", + "lng": "-117.895474000" + }, + { + "lat": "33.795668000", + "lng": "-117.895309000" + }, + { + "lat": "33.795460000", + "lng": "-117.895097000" + }, + { + "lat": "33.795195000", + "lng": "-117.894826000" + }, + { + "lat": "33.794579000", + "lng": "-117.894189000" + }, + { + "lat": "33.794288000", + "lng": "-117.893906000" + }, + { + "lat": "33.794180000", + "lng": "-117.893804000" + }, + { + "lat": "33.794062000", + "lng": "-117.893702000" + }, + { + "lat": "33.793960000", + "lng": "-117.893618000" + }, + { + "lat": "33.793937000", + "lng": "-117.893601000" + }, + { + "lat": "33.793865000", + "lng": "-117.893551000" + }, + { + "lat": "33.793759000", + "lng": "-117.893476000" + }, + { + "lat": "33.793631000", + "lng": "-117.893388000" + }, + { + "lat": "33.793332000", + "lng": "-117.893181000" + }, + { + "lat": "33.793226000", + "lng": "-117.893108000" + }, + { + "lat": "33.793044000", + "lng": "-117.892984000" + }, + { + "lat": "33.792893000", + "lng": "-117.892889000" + }, + { + "lat": "33.792622000", + "lng": "-117.892731000" + }, + { + "lat": "33.792372000", + "lng": "-117.892583000" + }, + { + "lat": "33.792252000", + "lng": "-117.892527000" + }, + { + "lat": "33.792160000", + "lng": "-117.892494000" + }, + { + "lat": "33.792070000", + "lng": "-117.892472000" + }, + { + "lat": "33.791975000", + "lng": "-117.892457000" + }, + { + "lat": "33.791875000", + "lng": "-117.892450000" + }, + { + "lat": "33.791768000", + "lng": "-117.892452000" + }, + { + "lat": "33.791662000", + "lng": "-117.892462000" + }, + { + "lat": "33.791550000", + "lng": "-117.892486000" + }, + { + "lat": "33.791502000", + "lng": "-117.892502000" + }, + { + "lat": "33.791458000", + "lng": "-117.892519000" + }, + { + "lat": "33.791409000", + "lng": "-117.892539000" + }, + { + "lat": "33.791328000", + "lng": "-117.892581000" + }, + { + "lat": "33.791066000", + "lng": "-117.892748000" + }, + { + "lat": "33.790967000", + "lng": "-117.892830000" + }, + { + "lat": "33.790931000", + "lng": "-117.892855000" + }, + { + "lat": "33.790832000", + "lng": "-117.892915000" + }, + { + "lat": "33.790730000", + "lng": "-117.892990000" + }, + { + "lat": "33.790693000", + "lng": "-117.893015000" + }, + { + "lat": "33.790582000", + "lng": "-117.893076000" + }, + { + "lat": "33.790522000", + "lng": "-117.893100000" + }, + { + "lat": "33.790457000", + "lng": "-117.893121000" + }, + { + "lat": "33.790396000", + "lng": "-117.893138000" + }, + { + "lat": "33.790328000", + "lng": "-117.893149000" + }, + { + "lat": "33.790258000", + "lng": "-117.893155000" + }, + { + "lat": "33.790169000", + "lng": "-117.893159000" + }, + { + "lat": "33.790044000", + "lng": "-117.893159000" + }, + { + "lat": "33.789930000", + "lng": "-117.893134000" + }, + { + "lat": "33.789683000", + "lng": "-117.893146000" + }, + { + "lat": "33.789567000", + "lng": "-117.893145000" + }, + { + "lat": "33.789512000", + "lng": "-117.893146000" + }, + { + "lat": "33.789169000", + "lng": "-117.893144000" + }, + { + "lat": "33.789145000", + "lng": "-117.893144000" + }, + { + "lat": "33.789016000", + "lng": "-117.893145000" + }, + { + "lat": "33.788898000", + "lng": "-117.893146000" + }, + { + "lat": "33.788899000", + "lng": "-117.892842000" + }, + { + "lat": "33.788904000", + "lng": "-117.890700000" + }, + { + "lat": "33.788909000", + "lng": "-117.890516000" + }, + { + "lat": "33.788913000", + "lng": "-117.890489000" + }, + { + "lat": "33.788954000", + "lng": "-117.890197000" + }, + { + "lat": "33.789050000", + "lng": "-117.889708000" + }, + { + "lat": "33.789086000", + "lng": "-117.889537000" + }, + { + "lat": "33.789321000", + "lng": "-117.888520000" + }, + { + "lat": "33.789397000", + "lng": "-117.888460000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789336000", + "lng": "-117.886428000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789732000", + "lng": "-117.886235000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789589000", + "lng": "-117.886174000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789241000", + "lng": "-117.886328000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787837000", + "lng": "-117.881017000" + }, + { + "lat": "33.787840000", + "lng": "-117.880648000" + }, + { + "lat": "33.787840000", + "lng": "-117.880625000" + }, + { + "lat": "33.787841000", + "lng": "-117.880435000" + }, + { + "lat": "33.787847000", + "lng": "-117.879556000" + }, + { + "lat": "33.787844000", + "lng": "-117.879130000" + }, + { + "lat": "33.787844000", + "lng": "-117.879052000" + }, + { + "lat": "33.787843000", + "lng": "-117.878851000" + }, + { + "lat": "33.787842000", + "lng": "-117.878720000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787887000", + "lng": "-117.875554000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787838000", + "lng": "-117.867107000" + }, + { + "lat": "33.787838000", + "lng": "-117.866715000" + }, + { + "lat": "33.787838000", + "lng": "-117.866531000" + }, + { + "lat": "33.787838000", + "lng": "-117.866114000" + }, + { + "lat": "33.787838000", + "lng": "-117.865902000" + }, + { + "lat": "33.787838000", + "lng": "-117.865670000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787846000", + "lng": "-117.857894000" + }, + { + "lat": "33.787846000", + "lng": "-117.857828000" + }, + { + "lat": "33.787846000", + "lng": "-117.857771000" + }, + { + "lat": "33.787847000", + "lng": "-117.857518000" + }, + { + "lat": "33.787848000", + "lng": "-117.857460000" + }, + { + "lat": "33.787848000", + "lng": "-117.857265000" + }, + { + "lat": "33.787849000", + "lng": "-117.857090000" + }, + { + "lat": "33.787849000", + "lng": "-117.857041000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.788076000", + "lng": "-117.856372000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793322000", + "lng": "-117.855591000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793325000", + "lng": "-117.852810000" + } + ] + ], + "54257": [ + [ + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793230000", + "lng": "-117.856356000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787891000", + "lng": "-117.856783000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787893000", + "lng": "-117.856979000" + }, + { + "lat": "33.787933000", + "lng": "-117.857043000" + }, + { + "lat": "33.787933000", + "lng": "-117.857458000" + }, + { + "lat": "33.787933000", + "lng": "-117.857518000" + }, + { + "lat": "33.787933000", + "lng": "-117.857827000" + }, + { + "lat": "33.787933000", + "lng": "-117.857907000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787938000", + "lng": "-117.865679000" + }, + { + "lat": "33.787938000", + "lng": "-117.866004000" + }, + { + "lat": "33.787939000", + "lng": "-117.866335000" + }, + { + "lat": "33.787940000", + "lng": "-117.866502000" + }, + { + "lat": "33.787940000", + "lng": "-117.866645000" + }, + { + "lat": "33.787941000", + "lng": "-117.866964000" + }, + { + "lat": "33.787942000", + "lng": "-117.867104000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.872161000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787940000", + "lng": "-117.878721000" + }, + { + "lat": "33.787946000", + "lng": "-117.878943000" + }, + { + "lat": "33.787950000", + "lng": "-117.879220000" + }, + { + "lat": "33.787947000", + "lng": "-117.879543000" + }, + { + "lat": "33.787932000", + "lng": "-117.880310000" + }, + { + "lat": "33.787929000", + "lng": "-117.880465000" + }, + { + "lat": "33.787930000", + "lng": "-117.880566000" + }, + { + "lat": "33.787930000", + "lng": "-117.880625000" + }, + { + "lat": "33.787932000", + "lng": "-117.881015000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789638000", + "lng": "-117.886143000" + }, + { + "lat": "33.789733000", + "lng": "-117.886236000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789573000", + "lng": "-117.886197000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789306000", + "lng": "-117.886505000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789467000", + "lng": "-117.888536000" + }, + { + "lat": "33.789477000", + "lng": "-117.888629000" + }, + { + "lat": "33.789431000", + "lng": "-117.888858000" + }, + { + "lat": "33.789193000", + "lng": "-117.889833000" + }, + { + "lat": "33.789079000", + "lng": "-117.890474000" + }, + { + "lat": "33.789070000", + "lng": "-117.890540000" + }, + { + "lat": "33.789050000", + "lng": "-117.890692000" + }, + { + "lat": "33.789213000", + "lng": "-117.890685000" + }, + { + "lat": "33.789240000", + "lng": "-117.890682000" + }, + { + "lat": "33.789443000", + "lng": "-117.890661000" + }, + { + "lat": "33.789572000", + "lng": "-117.890639000" + }, + { + "lat": "33.789673000", + "lng": "-117.890617000" + }, + { + "lat": "33.789791000", + "lng": "-117.890583000" + }, + { + "lat": "33.789972000", + "lng": "-117.890523000" + }, + { + "lat": "33.789994000", + "lng": "-117.890515000" + }, + { + "lat": "33.790393000", + "lng": "-117.890382000" + }, + { + "lat": "33.790715000", + "lng": "-117.890275000" + }, + { + "lat": "33.790840000", + "lng": "-117.890233000" + }, + { + "lat": "33.791287000", + "lng": "-117.890090000" + }, + { + "lat": "33.791676000", + "lng": "-117.889959000" + }, + { + "lat": "33.791969000", + "lng": "-117.889853000" + }, + { + "lat": "33.792429000", + "lng": "-117.889707000" + }, + { + "lat": "33.792554000", + "lng": "-117.889667000" + }, + { + "lat": "33.792652000", + "lng": "-117.889635000" + }, + { + "lat": "33.792685000", + "lng": "-117.889920000" + }, + { + "lat": "33.792730000", + "lng": "-117.890076000" + }, + { + "lat": "33.792770000", + "lng": "-117.890207000" + }, + { + "lat": "33.792786000", + "lng": "-117.890241000" + }, + { + "lat": "33.792827000", + "lng": "-117.890330000" + }, + { + "lat": "33.792888000", + "lng": "-117.890452000" + }, + { + "lat": "33.792974000", + "lng": "-117.890591000" + }, + { + "lat": "33.793067000", + "lng": "-117.890702000" + }, + { + "lat": "33.795778000", + "lng": "-117.893533000" + }, + { + "lat": "33.795942000", + "lng": "-117.893702000" + }, + { + "lat": "33.795971000", + "lng": "-117.893732000" + }, + { + "lat": "33.796079000", + "lng": "-117.893843000" + }, + { + "lat": "33.796222000", + "lng": "-117.893992000" + }, + { + "lat": "33.796349000", + "lng": "-117.894127000" + }, + { + "lat": "33.796970000", + "lng": "-117.894781000" + }, + { + "lat": "33.797375000", + "lng": "-117.895274000" + }, + { + "lat": "33.797906000", + "lng": "-117.895831000" + }, + { + "lat": "33.798837000", + "lng": "-117.896728000" + }, + { + "lat": "33.799199000", + "lng": "-117.897077000" + }, + { + "lat": "33.799409000", + "lng": "-117.897262000" + }, + { + "lat": "33.799531000", + "lng": "-117.897349000" + }, + { + "lat": "33.799914000", + "lng": "-117.897622000" + }, + { + "lat": "33.800647000", + "lng": "-117.898145000" + }, + { + "lat": "33.800834000", + "lng": "-117.898141000" + }, + { + "lat": "33.800882000", + "lng": "-117.898130000" + }, + { + "lat": "33.800928000", + "lng": "-117.898100000" + }, + { + "lat": "33.800932000", + "lng": "-117.898098000" + }, + { + "lat": "33.800971000", + "lng": "-117.898060000" + }, + { + "lat": "33.801007000", + "lng": "-117.898010000" + }, + { + "lat": "33.801111000", + "lng": "-117.897921000" + }, + { + "lat": "33.801157000", + "lng": "-117.897885000" + }, + { + "lat": "33.801252000", + "lng": "-117.897844000" + }, + { + "lat": "33.801328000", + "lng": "-117.897829000" + }, + { + "lat": "33.801397000", + "lng": "-117.897823000" + }, + { + "lat": "33.801400000", + "lng": "-117.897823000" + }, + { + "lat": "33.801560000", + "lng": "-117.897830000" + }, + { + "lat": "33.801856000", + "lng": "-117.897841000" + }, + { + "lat": "33.801885000", + "lng": "-117.897842000" + }, + { + "lat": "33.802027000", + "lng": "-117.897848000" + }, + { + "lat": "33.802583000", + "lng": "-117.897870000" + }, + { + "lat": "33.802692000", + "lng": "-117.897874000" + }, + { + "lat": "33.802740000", + "lng": "-117.897876000" + }, + { + "lat": "33.802863000", + "lng": "-117.897881000" + }, + { + "lat": "33.802899000", + "lng": "-117.897882000" + }, + { + "lat": "33.802955000", + "lng": "-117.897884000" + }, + { + "lat": "33.803170000", + "lng": "-117.897893000" + }, + { + "lat": "33.803276000", + "lng": "-117.897904000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803855000", + "lng": "-117.897913000" + }, + { + "lat": "33.804052000", + "lng": "-117.897914000" + }, + { + "lat": "33.804235000", + "lng": "-117.897916000" + }, + { + "lat": "33.804746000", + "lng": "-117.897919000" + }, + { + "lat": "33.805197000", + "lng": "-117.897922000" + }, + { + "lat": "33.805198000", + "lng": "-117.897512000" + }, + { + "lat": "33.805199000", + "lng": "-117.896883000" + }, + { + "lat": "33.805194000", + "lng": "-117.895951000" + }, + { + "lat": "33.805184000", + "lng": "-117.895913000" + }, + { + "lat": "33.805155000", + "lng": "-117.895877000" + }, + { + "lat": "33.805109000", + "lng": "-117.895855000" + }, + { + "lat": "33.804853000", + "lng": "-117.895854000" + }, + { + "lat": "33.804278000", + "lng": "-117.895852000" + }, + { + "lat": "33.803586000", + "lng": "-117.895845000" + }, + { + "lat": "33.803438000", + "lng": "-117.895845000" + }, + { + "lat": "33.803437000", + "lng": "-117.895988000" + }, + { + "lat": "33.803431000", + "lng": "-117.896870000" + }, + { + "lat": "33.803428000", + "lng": "-117.897051000" + }, + { + "lat": "33.803425000", + "lng": "-117.897278000" + }, + { + "lat": "33.803424000", + "lng": "-117.897351000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803404000", + "lng": "-117.898058000" + }, + { + "lat": "33.803411000", + "lng": "-117.898721000" + }, + { + "lat": "33.803415000", + "lng": "-117.899152000" + }, + { + "lat": "33.803418000", + "lng": "-117.899238000" + }, + { + "lat": "33.803422000", + "lng": "-117.899462000" + }, + { + "lat": "33.803435000", + "lng": "-117.899958000" + }, + { + "lat": "33.803436000", + "lng": "-117.900207000" + }, + { + "lat": "33.803441000", + "lng": "-117.900911000" + }, + { + "lat": "33.803438000", + "lng": "-117.901150000" + }, + { + "lat": "33.803434000", + "lng": "-117.901409000" + }, + { + "lat": "33.803424000", + "lng": "-117.903146000" + }, + { + "lat": "33.803436000", + "lng": "-117.903749000" + }, + { + "lat": "33.803445000", + "lng": "-117.904164000" + }, + { + "lat": "33.803445000", + "lng": "-117.904331000" + }, + { + "lat": "33.803445000", + "lng": "-117.904491000" + }, + { + "lat": "33.803444000", + "lng": "-117.905057000" + }, + { + "lat": "33.803413000", + "lng": "-117.905482000" + }, + { + "lat": "33.803417000", + "lng": "-117.906404000" + }, + { + "lat": "33.803418000", + "lng": "-117.906531000" + }, + { + "lat": "33.803413000", + "lng": "-117.906725000" + }, + { + "lat": "33.803262000", + "lng": "-117.906598000" + }, + { + "lat": "33.803133000", + "lng": "-117.906593000" + }, + { + "lat": "33.803018000", + "lng": "-117.906588000" + }, + { + "lat": "33.802832000", + "lng": "-117.906580000" + }, + { + "lat": "33.802654000", + "lng": "-117.906570000" + }, + { + "lat": "33.802522000", + "lng": "-117.906566000" + }, + { + "lat": "33.802251000", + "lng": "-117.906557000" + }, + { + "lat": "33.801658000", + "lng": "-117.906544000" + }, + { + "lat": "33.801513000", + "lng": "-117.906541000" + }, + { + "lat": "33.801192000", + "lng": "-117.906532000" + }, + { + "lat": "33.801102000", + "lng": "-117.906529000" + }, + { + "lat": "33.800653000", + "lng": "-117.906520000" + }, + { + "lat": "33.800562000", + "lng": "-117.906518000" + }, + { + "lat": "33.799993000", + "lng": "-117.906505000" + }, + { + "lat": "33.799848000", + "lng": "-117.906501000" + }, + { + "lat": "33.799849000", + "lng": "-117.906156000" + }, + { + "lat": "33.799852000", + "lng": "-117.905575000" + }, + { + "lat": "33.799869000", + "lng": "-117.902210000" + }, + { + "lat": "33.799860000", + "lng": "-117.901886000" + }, + { + "lat": "33.799843000", + "lng": "-117.901683000" + }, + { + "lat": "33.799801000", + "lng": "-117.901415000" + }, + { + "lat": "33.799739000", + "lng": "-117.901146000" + }, + { + "lat": "33.799693000", + "lng": "-117.900885000" + }, + { + "lat": "33.799668000", + "lng": "-117.900673000" + }, + { + "lat": "33.799652000", + "lng": "-117.900467000" + }, + { + "lat": "33.799647000", + "lng": "-117.900366000" + }, + { + "lat": "33.799646000", + "lng": "-117.900266000" + }, + { + "lat": "33.799651000", + "lng": "-117.899753000" + }, + { + "lat": "33.799646000", + "lng": "-117.898481000" + }, + { + "lat": "33.799646000", + "lng": "-117.898376000" + }, + { + "lat": "33.799644000", + "lng": "-117.897954000" + }, + { + "lat": "33.799641000", + "lng": "-117.897267000" + }, + { + "lat": "33.799642000", + "lng": "-117.896444000" + }, + { + "lat": "33.799644000", + "lng": "-117.895941000" + }, + { + "lat": "33.799653000", + "lng": "-117.895205000" + }, + { + "lat": "33.799670000", + "lng": "-117.893200000" + }, + { + "lat": "33.799715000", + "lng": "-117.892732000" + }, + { + "lat": "33.799715000", + "lng": "-117.892703000" + }, + { + "lat": "33.799714000", + "lng": "-117.892163000" + }, + { + "lat": "33.799713000", + "lng": "-117.891623000" + }, + { + "lat": "33.799713000", + "lng": "-117.891442000" + }, + { + "lat": "33.799713000", + "lng": "-117.891212000" + }, + { + "lat": "33.799712000", + "lng": "-117.890642000" + }, + { + "lat": "33.799712000", + "lng": "-117.889838000" + }, + { + "lat": "33.799711000", + "lng": "-117.889396000" + }, + { + "lat": "33.799711000", + "lng": "-117.889176000" + }, + { + "lat": "33.799558000", + "lng": "-117.889273000" + }, + { + "lat": "33.799333000", + "lng": "-117.889271000" + }, + { + "lat": "33.798370000", + "lng": "-117.889263000" + }, + { + "lat": "33.797874000", + "lng": "-117.889265000" + }, + { + "lat": "33.797783000", + "lng": "-117.889267000" + }, + { + "lat": "33.797103000", + "lng": "-117.889280000" + }, + { + "lat": "33.796975000", + "lng": "-117.889282000" + }, + { + "lat": "33.796354000", + "lng": "-117.889295000" + }, + { + "lat": "33.796134000", + "lng": "-117.889299000" + }, + { + "lat": "33.795536000", + "lng": "-117.889327000" + }, + { + "lat": "33.794906000", + "lng": "-117.889329000" + }, + { + "lat": "33.794596000", + "lng": "-117.889345000" + }, + { + "lat": "33.794387000", + "lng": "-117.889372000" + }, + { + "lat": "33.794267000", + "lng": "-117.889394000" + }, + { + "lat": "33.793940000", + "lng": "-117.889494000" + }, + { + "lat": "33.793821000", + "lng": "-117.889529000" + }, + { + "lat": "33.793667000", + "lng": "-117.889574000" + }, + { + "lat": "33.793509000", + "lng": "-117.889624000" + }, + { + "lat": "33.793349000", + "lng": "-117.889674000" + }, + { + "lat": "33.792856000", + "lng": "-117.889863000" + }, + { + "lat": "33.792685000", + "lng": "-117.889920000" + }, + { + "lat": "33.792476000", + "lng": "-117.889990000" + }, + { + "lat": "33.791840000", + "lng": "-117.890202000" + }, + { + "lat": "33.791770000", + "lng": "-117.890225000" + }, + { + "lat": "33.791177000", + "lng": "-117.890419000" + }, + { + "lat": "33.791019000", + "lng": "-117.890471000" + }, + { + "lat": "33.790887000", + "lng": "-117.890516000" + }, + { + "lat": "33.790764000", + "lng": "-117.890559000" + }, + { + "lat": "33.790126000", + "lng": "-117.890770000" + }, + { + "lat": "33.789925000", + "lng": "-117.890837000" + }, + { + "lat": "33.789802000", + "lng": "-117.890868000" + }, + { + "lat": "33.789759000", + "lng": "-117.890877000" + }, + { + "lat": "33.789675000", + "lng": "-117.890893000" + }, + { + "lat": "33.789591000", + "lng": "-117.890907000" + }, + { + "lat": "33.789475000", + "lng": "-117.890916000" + }, + { + "lat": "33.789328000", + "lng": "-117.890924000" + }, + { + "lat": "33.789202000", + "lng": "-117.890932000" + }, + { + "lat": "33.789041000", + "lng": "-117.890936000" + }, + { + "lat": "33.788903000", + "lng": "-117.890936000" + }, + { + "lat": "33.788904000", + "lng": "-117.890700000" + }, + { + "lat": "33.788909000", + "lng": "-117.890516000" + }, + { + "lat": "33.788913000", + "lng": "-117.890489000" + }, + { + "lat": "33.788954000", + "lng": "-117.890197000" + }, + { + "lat": "33.789050000", + "lng": "-117.889708000" + }, + { + "lat": "33.789086000", + "lng": "-117.889537000" + }, + { + "lat": "33.789321000", + "lng": "-117.888520000" + }, + { + "lat": "33.789397000", + "lng": "-117.888460000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789336000", + "lng": "-117.886428000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789732000", + "lng": "-117.886235000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789589000", + "lng": "-117.886174000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789241000", + "lng": "-117.886328000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787837000", + "lng": "-117.881017000" + }, + { + "lat": "33.787840000", + "lng": "-117.880648000" + }, + { + "lat": "33.787840000", + "lng": "-117.880625000" + }, + { + "lat": "33.787841000", + "lng": "-117.880435000" + }, + { + "lat": "33.787847000", + "lng": "-117.879556000" + }, + { + "lat": "33.787844000", + "lng": "-117.879130000" + }, + { + "lat": "33.787844000", + "lng": "-117.879052000" + }, + { + "lat": "33.787843000", + "lng": "-117.878851000" + }, + { + "lat": "33.787842000", + "lng": "-117.878720000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787887000", + "lng": "-117.875554000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787838000", + "lng": "-117.867107000" + }, + { + "lat": "33.787838000", + "lng": "-117.866715000" + }, + { + "lat": "33.787838000", + "lng": "-117.866531000" + }, + { + "lat": "33.787838000", + "lng": "-117.866114000" + }, + { + "lat": "33.787838000", + "lng": "-117.865902000" + }, + { + "lat": "33.787838000", + "lng": "-117.865670000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787846000", + "lng": "-117.857894000" + }, + { + "lat": "33.787846000", + "lng": "-117.857828000" + }, + { + "lat": "33.787846000", + "lng": "-117.857771000" + }, + { + "lat": "33.787847000", + "lng": "-117.857518000" + }, + { + "lat": "33.787848000", + "lng": "-117.857460000" + }, + { + "lat": "33.787848000", + "lng": "-117.857265000" + }, + { + "lat": "33.787849000", + "lng": "-117.857090000" + }, + { + "lat": "33.787849000", + "lng": "-117.857041000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.788076000", + "lng": "-117.856372000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793322000", + "lng": "-117.855591000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793325000", + "lng": "-117.852810000" + } + ] + ], + "54282": [ + [ + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793230000", + "lng": "-117.856356000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787891000", + "lng": "-117.856783000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787893000", + "lng": "-117.856979000" + }, + { + "lat": "33.787933000", + "lng": "-117.857043000" + }, + { + "lat": "33.787933000", + "lng": "-117.857458000" + }, + { + "lat": "33.787933000", + "lng": "-117.857518000" + }, + { + "lat": "33.787933000", + "lng": "-117.857827000" + }, + { + "lat": "33.787933000", + "lng": "-117.857907000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787938000", + "lng": "-117.865679000" + }, + { + "lat": "33.787938000", + "lng": "-117.865702000" + }, + { + "lat": "33.787938000", + "lng": "-117.866004000" + }, + { + "lat": "33.787939000", + "lng": "-117.866335000" + }, + { + "lat": "33.787940000", + "lng": "-117.866502000" + }, + { + "lat": "33.787940000", + "lng": "-117.866645000" + }, + { + "lat": "33.787941000", + "lng": "-117.866964000" + }, + { + "lat": "33.787942000", + "lng": "-117.867081000" + }, + { + "lat": "33.787942000", + "lng": "-117.867104000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.872161000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787940000", + "lng": "-117.878721000" + }, + { + "lat": "33.787946000", + "lng": "-117.878943000" + }, + { + "lat": "33.787950000", + "lng": "-117.879220000" + }, + { + "lat": "33.787947000", + "lng": "-117.879543000" + }, + { + "lat": "33.787932000", + "lng": "-117.880310000" + }, + { + "lat": "33.787929000", + "lng": "-117.880465000" + }, + { + "lat": "33.787930000", + "lng": "-117.880566000" + }, + { + "lat": "33.787930000", + "lng": "-117.880625000" + }, + { + "lat": "33.787932000", + "lng": "-117.881015000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789638000", + "lng": "-117.886143000" + }, + { + "lat": "33.789733000", + "lng": "-117.886236000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789573000", + "lng": "-117.886197000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789306000", + "lng": "-117.886505000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789467000", + "lng": "-117.888536000" + }, + { + "lat": "33.789477000", + "lng": "-117.888629000" + }, + { + "lat": "33.789431000", + "lng": "-117.888858000" + }, + { + "lat": "33.789193000", + "lng": "-117.889833000" + }, + { + "lat": "33.789079000", + "lng": "-117.890474000" + }, + { + "lat": "33.789070000", + "lng": "-117.890540000" + }, + { + "lat": "33.789050000", + "lng": "-117.890692000" + }, + { + "lat": "33.789213000", + "lng": "-117.890685000" + }, + { + "lat": "33.789240000", + "lng": "-117.890682000" + }, + { + "lat": "33.789443000", + "lng": "-117.890661000" + }, + { + "lat": "33.789572000", + "lng": "-117.890639000" + }, + { + "lat": "33.789673000", + "lng": "-117.890617000" + }, + { + "lat": "33.789791000", + "lng": "-117.890583000" + }, + { + "lat": "33.789972000", + "lng": "-117.890523000" + }, + { + "lat": "33.789994000", + "lng": "-117.890515000" + }, + { + "lat": "33.790393000", + "lng": "-117.890382000" + }, + { + "lat": "33.790715000", + "lng": "-117.890275000" + }, + { + "lat": "33.790840000", + "lng": "-117.890233000" + }, + { + "lat": "33.791287000", + "lng": "-117.890090000" + }, + { + "lat": "33.791676000", + "lng": "-117.889959000" + }, + { + "lat": "33.791969000", + "lng": "-117.889853000" + }, + { + "lat": "33.792429000", + "lng": "-117.889707000" + }, + { + "lat": "33.792554000", + "lng": "-117.889667000" + }, + { + "lat": "33.792652000", + "lng": "-117.889635000" + }, + { + "lat": "33.792685000", + "lng": "-117.889920000" + }, + { + "lat": "33.792730000", + "lng": "-117.890076000" + }, + { + "lat": "33.792770000", + "lng": "-117.890207000" + }, + { + "lat": "33.792786000", + "lng": "-117.890241000" + }, + { + "lat": "33.792827000", + "lng": "-117.890330000" + }, + { + "lat": "33.792888000", + "lng": "-117.890452000" + }, + { + "lat": "33.792974000", + "lng": "-117.890591000" + }, + { + "lat": "33.793067000", + "lng": "-117.890702000" + }, + { + "lat": "33.795778000", + "lng": "-117.893533000" + }, + { + "lat": "33.795942000", + "lng": "-117.893702000" + }, + { + "lat": "33.795971000", + "lng": "-117.893732000" + }, + { + "lat": "33.796079000", + "lng": "-117.893843000" + }, + { + "lat": "33.796222000", + "lng": "-117.893992000" + }, + { + "lat": "33.796349000", + "lng": "-117.894127000" + }, + { + "lat": "33.796970000", + "lng": "-117.894781000" + }, + { + "lat": "33.797375000", + "lng": "-117.895274000" + }, + { + "lat": "33.797906000", + "lng": "-117.895831000" + }, + { + "lat": "33.798837000", + "lng": "-117.896728000" + }, + { + "lat": "33.799199000", + "lng": "-117.897077000" + }, + { + "lat": "33.799409000", + "lng": "-117.897262000" + }, + { + "lat": "33.799531000", + "lng": "-117.897349000" + }, + { + "lat": "33.799914000", + "lng": "-117.897622000" + }, + { + "lat": "33.800647000", + "lng": "-117.898145000" + }, + { + "lat": "33.800834000", + "lng": "-117.898141000" + }, + { + "lat": "33.800882000", + "lng": "-117.898130000" + }, + { + "lat": "33.800928000", + "lng": "-117.898100000" + }, + { + "lat": "33.800932000", + "lng": "-117.898098000" + }, + { + "lat": "33.800971000", + "lng": "-117.898060000" + }, + { + "lat": "33.801007000", + "lng": "-117.898010000" + }, + { + "lat": "33.801111000", + "lng": "-117.897921000" + }, + { + "lat": "33.801157000", + "lng": "-117.897885000" + }, + { + "lat": "33.801252000", + "lng": "-117.897844000" + }, + { + "lat": "33.801328000", + "lng": "-117.897829000" + }, + { + "lat": "33.801397000", + "lng": "-117.897823000" + }, + { + "lat": "33.801400000", + "lng": "-117.897823000" + }, + { + "lat": "33.801560000", + "lng": "-117.897830000" + }, + { + "lat": "33.801856000", + "lng": "-117.897841000" + }, + { + "lat": "33.801885000", + "lng": "-117.897842000" + }, + { + "lat": "33.802027000", + "lng": "-117.897848000" + }, + { + "lat": "33.802583000", + "lng": "-117.897870000" + }, + { + "lat": "33.802692000", + "lng": "-117.897874000" + }, + { + "lat": "33.802740000", + "lng": "-117.897876000" + }, + { + "lat": "33.802863000", + "lng": "-117.897881000" + }, + { + "lat": "33.802899000", + "lng": "-117.897882000" + }, + { + "lat": "33.802955000", + "lng": "-117.897884000" + }, + { + "lat": "33.803170000", + "lng": "-117.897893000" + }, + { + "lat": "33.803276000", + "lng": "-117.897904000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803855000", + "lng": "-117.897913000" + }, + { + "lat": "33.804052000", + "lng": "-117.897914000" + }, + { + "lat": "33.804235000", + "lng": "-117.897916000" + }, + { + "lat": "33.804746000", + "lng": "-117.897919000" + }, + { + "lat": "33.805197000", + "lng": "-117.897922000" + }, + { + "lat": "33.805198000", + "lng": "-117.897512000" + }, + { + "lat": "33.805199000", + "lng": "-117.896883000" + }, + { + "lat": "33.805194000", + "lng": "-117.895951000" + }, + { + "lat": "33.805184000", + "lng": "-117.895913000" + }, + { + "lat": "33.805155000", + "lng": "-117.895877000" + }, + { + "lat": "33.805109000", + "lng": "-117.895855000" + }, + { + "lat": "33.804853000", + "lng": "-117.895854000" + }, + { + "lat": "33.804278000", + "lng": "-117.895852000" + }, + { + "lat": "33.803586000", + "lng": "-117.895845000" + }, + { + "lat": "33.803438000", + "lng": "-117.895845000" + }, + { + "lat": "33.803437000", + "lng": "-117.895988000" + }, + { + "lat": "33.803431000", + "lng": "-117.896870000" + }, + { + "lat": "33.803428000", + "lng": "-117.897051000" + }, + { + "lat": "33.803425000", + "lng": "-117.897278000" + }, + { + "lat": "33.803424000", + "lng": "-117.897351000" + }, + { + "lat": "33.803420000", + "lng": "-117.897907000" + }, + { + "lat": "33.803404000", + "lng": "-117.898058000" + }, + { + "lat": "33.803411000", + "lng": "-117.898721000" + }, + { + "lat": "33.803415000", + "lng": "-117.899152000" + }, + { + "lat": "33.803418000", + "lng": "-117.899238000" + }, + { + "lat": "33.803422000", + "lng": "-117.899462000" + }, + { + "lat": "33.803435000", + "lng": "-117.899958000" + }, + { + "lat": "33.803436000", + "lng": "-117.900207000" + }, + { + "lat": "33.803441000", + "lng": "-117.900911000" + }, + { + "lat": "33.803438000", + "lng": "-117.901150000" + }, + { + "lat": "33.803434000", + "lng": "-117.901409000" + }, + { + "lat": "33.803424000", + "lng": "-117.903146000" + }, + { + "lat": "33.803436000", + "lng": "-117.903749000" + }, + { + "lat": "33.803445000", + "lng": "-117.904164000" + }, + { + "lat": "33.803445000", + "lng": "-117.904331000" + }, + { + "lat": "33.803445000", + "lng": "-117.904491000" + }, + { + "lat": "33.803444000", + "lng": "-117.905057000" + }, + { + "lat": "33.803413000", + "lng": "-117.905482000" + }, + { + "lat": "33.803417000", + "lng": "-117.906404000" + }, + { + "lat": "33.803418000", + "lng": "-117.906531000" + }, + { + "lat": "33.803413000", + "lng": "-117.906725000" + }, + { + "lat": "33.803262000", + "lng": "-117.906598000" + }, + { + "lat": "33.803133000", + "lng": "-117.906593000" + }, + { + "lat": "33.803018000", + "lng": "-117.906588000" + }, + { + "lat": "33.802832000", + "lng": "-117.906580000" + }, + { + "lat": "33.802654000", + "lng": "-117.906570000" + }, + { + "lat": "33.802522000", + "lng": "-117.906566000" + }, + { + "lat": "33.802251000", + "lng": "-117.906557000" + }, + { + "lat": "33.801658000", + "lng": "-117.906544000" + }, + { + "lat": "33.801513000", + "lng": "-117.906541000" + }, + { + "lat": "33.801192000", + "lng": "-117.906532000" + }, + { + "lat": "33.801102000", + "lng": "-117.906529000" + }, + { + "lat": "33.800653000", + "lng": "-117.906520000" + }, + { + "lat": "33.800562000", + "lng": "-117.906518000" + }, + { + "lat": "33.799993000", + "lng": "-117.906505000" + }, + { + "lat": "33.799848000", + "lng": "-117.906501000" + }, + { + "lat": "33.799849000", + "lng": "-117.906156000" + }, + { + "lat": "33.799852000", + "lng": "-117.905575000" + }, + { + "lat": "33.799869000", + "lng": "-117.902210000" + }, + { + "lat": "33.799860000", + "lng": "-117.901886000" + }, + { + "lat": "33.799843000", + "lng": "-117.901683000" + }, + { + "lat": "33.799801000", + "lng": "-117.901415000" + }, + { + "lat": "33.799739000", + "lng": "-117.901146000" + }, + { + "lat": "33.799693000", + "lng": "-117.900885000" + }, + { + "lat": "33.799668000", + "lng": "-117.900673000" + }, + { + "lat": "33.799652000", + "lng": "-117.900467000" + }, + { + "lat": "33.799647000", + "lng": "-117.900366000" + }, + { + "lat": "33.799646000", + "lng": "-117.900266000" + }, + { + "lat": "33.799651000", + "lng": "-117.899753000" + }, + { + "lat": "33.799646000", + "lng": "-117.898481000" + }, + { + "lat": "33.799646000", + "lng": "-117.898376000" + }, + { + "lat": "33.799644000", + "lng": "-117.897954000" + }, + { + "lat": "33.799641000", + "lng": "-117.897267000" + }, + { + "lat": "33.799642000", + "lng": "-117.896444000" + }, + { + "lat": "33.799644000", + "lng": "-117.895941000" + }, + { + "lat": "33.799653000", + "lng": "-117.895205000" + }, + { + "lat": "33.799670000", + "lng": "-117.893200000" + }, + { + "lat": "33.799715000", + "lng": "-117.892732000" + }, + { + "lat": "33.799715000", + "lng": "-117.892703000" + }, + { + "lat": "33.799714000", + "lng": "-117.892163000" + }, + { + "lat": "33.799713000", + "lng": "-117.891623000" + }, + { + "lat": "33.799713000", + "lng": "-117.891442000" + }, + { + "lat": "33.799713000", + "lng": "-117.891212000" + }, + { + "lat": "33.799712000", + "lng": "-117.890642000" + }, + { + "lat": "33.799712000", + "lng": "-117.889838000" + }, + { + "lat": "33.799711000", + "lng": "-117.889396000" + }, + { + "lat": "33.799711000", + "lng": "-117.889176000" + }, + { + "lat": "33.799558000", + "lng": "-117.889273000" + }, + { + "lat": "33.799333000", + "lng": "-117.889271000" + }, + { + "lat": "33.798370000", + "lng": "-117.889263000" + }, + { + "lat": "33.797874000", + "lng": "-117.889265000" + }, + { + "lat": "33.797783000", + "lng": "-117.889267000" + }, + { + "lat": "33.797103000", + "lng": "-117.889280000" + }, + { + "lat": "33.796975000", + "lng": "-117.889282000" + }, + { + "lat": "33.796354000", + "lng": "-117.889295000" + }, + { + "lat": "33.796134000", + "lng": "-117.889299000" + }, + { + "lat": "33.795536000", + "lng": "-117.889327000" + }, + { + "lat": "33.794906000", + "lng": "-117.889329000" + }, + { + "lat": "33.794596000", + "lng": "-117.889345000" + }, + { + "lat": "33.794387000", + "lng": "-117.889372000" + }, + { + "lat": "33.794267000", + "lng": "-117.889394000" + }, + { + "lat": "33.793940000", + "lng": "-117.889494000" + }, + { + "lat": "33.793821000", + "lng": "-117.889529000" + }, + { + "lat": "33.793667000", + "lng": "-117.889574000" + }, + { + "lat": "33.793509000", + "lng": "-117.889624000" + }, + { + "lat": "33.793349000", + "lng": "-117.889674000" + }, + { + "lat": "33.792856000", + "lng": "-117.889863000" + }, + { + "lat": "33.792685000", + "lng": "-117.889920000" + }, + { + "lat": "33.792476000", + "lng": "-117.889990000" + }, + { + "lat": "33.791840000", + "lng": "-117.890202000" + }, + { + "lat": "33.791770000", + "lng": "-117.890225000" + }, + { + "lat": "33.791177000", + "lng": "-117.890419000" + }, + { + "lat": "33.791019000", + "lng": "-117.890471000" + }, + { + "lat": "33.790887000", + "lng": "-117.890516000" + }, + { + "lat": "33.790764000", + "lng": "-117.890559000" + }, + { + "lat": "33.790126000", + "lng": "-117.890770000" + }, + { + "lat": "33.789925000", + "lng": "-117.890837000" + }, + { + "lat": "33.789802000", + "lng": "-117.890868000" + }, + { + "lat": "33.789759000", + "lng": "-117.890877000" + }, + { + "lat": "33.789675000", + "lng": "-117.890893000" + }, + { + "lat": "33.789591000", + "lng": "-117.890907000" + }, + { + "lat": "33.789475000", + "lng": "-117.890916000" + }, + { + "lat": "33.789328000", + "lng": "-117.890924000" + }, + { + "lat": "33.789202000", + "lng": "-117.890932000" + }, + { + "lat": "33.789041000", + "lng": "-117.890936000" + }, + { + "lat": "33.788903000", + "lng": "-117.890936000" + }, + { + "lat": "33.788904000", + "lng": "-117.890700000" + }, + { + "lat": "33.788909000", + "lng": "-117.890516000" + }, + { + "lat": "33.788913000", + "lng": "-117.890489000" + }, + { + "lat": "33.788954000", + "lng": "-117.890197000" + }, + { + "lat": "33.789050000", + "lng": "-117.889708000" + }, + { + "lat": "33.789086000", + "lng": "-117.889537000" + }, + { + "lat": "33.789321000", + "lng": "-117.888520000" + }, + { + "lat": "33.789397000", + "lng": "-117.888460000" + }, + { + "lat": "33.789454000", + "lng": "-117.888414000" + }, + { + "lat": "33.789481000", + "lng": "-117.888098000" + }, + { + "lat": "33.789504000", + "lng": "-117.887942000" + }, + { + "lat": "33.789519000", + "lng": "-117.887449000" + }, + { + "lat": "33.789507000", + "lng": "-117.887303000" + }, + { + "lat": "33.789494000", + "lng": "-117.887171000" + }, + { + "lat": "33.789392000", + "lng": "-117.886814000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789336000", + "lng": "-117.886428000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789583000", + "lng": "-117.886182000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789732000", + "lng": "-117.886235000" + }, + { + "lat": "33.789622000", + "lng": "-117.886127000" + }, + { + "lat": "33.789589000", + "lng": "-117.886174000" + }, + { + "lat": "33.789491000", + "lng": "-117.886321000" + }, + { + "lat": "33.789293000", + "lng": "-117.886458000" + }, + { + "lat": "33.789241000", + "lng": "-117.886328000" + }, + { + "lat": "33.789139000", + "lng": "-117.886074000" + }, + { + "lat": "33.789115000", + "lng": "-117.886014000" + }, + { + "lat": "33.788893000", + "lng": "-117.885639000" + }, + { + "lat": "33.788819000", + "lng": "-117.885531000" + }, + { + "lat": "33.788446000", + "lng": "-117.884941000" + }, + { + "lat": "33.788366000", + "lng": "-117.884815000" + }, + { + "lat": "33.788229000", + "lng": "-117.884547000" + }, + { + "lat": "33.788216000", + "lng": "-117.884521000" + }, + { + "lat": "33.788100000", + "lng": "-117.884219000" + }, + { + "lat": "33.788014000", + "lng": "-117.883957000" + }, + { + "lat": "33.787992000", + "lng": "-117.883830000" + }, + { + "lat": "33.787956000", + "lng": "-117.883695000" + }, + { + "lat": "33.787909000", + "lng": "-117.883363000" + }, + { + "lat": "33.787901000", + "lng": "-117.883304000" + }, + { + "lat": "33.787883000", + "lng": "-117.882974000" + }, + { + "lat": "33.787878000", + "lng": "-117.881727000" + }, + { + "lat": "33.787877000", + "lng": "-117.881621000" + }, + { + "lat": "33.787874000", + "lng": "-117.881424000" + }, + { + "lat": "33.787869000", + "lng": "-117.881189000" + }, + { + "lat": "33.787837000", + "lng": "-117.881017000" + }, + { + "lat": "33.787840000", + "lng": "-117.880648000" + }, + { + "lat": "33.787840000", + "lng": "-117.880625000" + }, + { + "lat": "33.787841000", + "lng": "-117.880435000" + }, + { + "lat": "33.787847000", + "lng": "-117.879556000" + }, + { + "lat": "33.787844000", + "lng": "-117.879130000" + }, + { + "lat": "33.787844000", + "lng": "-117.879052000" + }, + { + "lat": "33.787843000", + "lng": "-117.878851000" + }, + { + "lat": "33.787842000", + "lng": "-117.878720000" + }, + { + "lat": "33.787891000", + "lng": "-117.878628000" + }, + { + "lat": "33.787891000", + "lng": "-117.878604000" + }, + { + "lat": "33.787890000", + "lng": "-117.878542000" + }, + { + "lat": "33.787890000", + "lng": "-117.878380000" + }, + { + "lat": "33.787890000", + "lng": "-117.878150000" + }, + { + "lat": "33.787890000", + "lng": "-117.878024000" + }, + { + "lat": "33.787889000", + "lng": "-117.877933000" + }, + { + "lat": "33.787889000", + "lng": "-117.877739000" + }, + { + "lat": "33.787889000", + "lng": "-117.877685000" + }, + { + "lat": "33.787888000", + "lng": "-117.877601000" + }, + { + "lat": "33.787888000", + "lng": "-117.877582000" + }, + { + "lat": "33.787889000", + "lng": "-117.877097000" + }, + { + "lat": "33.787888000", + "lng": "-117.876796000" + }, + { + "lat": "33.787888000", + "lng": "-117.876702000" + }, + { + "lat": "33.787888000", + "lng": "-117.876358000" + }, + { + "lat": "33.787889000", + "lng": "-117.876046000" + }, + { + "lat": "33.787887000", + "lng": "-117.875705000" + }, + { + "lat": "33.787887000", + "lng": "-117.875554000" + }, + { + "lat": "33.787887000", + "lng": "-117.875389000" + }, + { + "lat": "33.787887000", + "lng": "-117.875270000" + }, + { + "lat": "33.787887000", + "lng": "-117.875020000" + }, + { + "lat": "33.787886000", + "lng": "-117.874578000" + }, + { + "lat": "33.787887000", + "lng": "-117.874561000" + }, + { + "lat": "33.787886000", + "lng": "-117.874423000" + }, + { + "lat": "33.787884000", + "lng": "-117.873824000" + }, + { + "lat": "33.787884000", + "lng": "-117.873785000" + }, + { + "lat": "33.787883000", + "lng": "-117.873361000" + }, + { + "lat": "33.787883000", + "lng": "-117.873275000" + }, + { + "lat": "33.787883000", + "lng": "-117.873109000" + }, + { + "lat": "33.787883000", + "lng": "-117.873037000" + }, + { + "lat": "33.787883000", + "lng": "-117.872802000" + }, + { + "lat": "33.787883000", + "lng": "-117.872633000" + }, + { + "lat": "33.787883000", + "lng": "-117.872562000" + }, + { + "lat": "33.787883000", + "lng": "-117.872335000" + }, + { + "lat": "33.787883000", + "lng": "-117.871983000" + }, + { + "lat": "33.787883000", + "lng": "-117.871711000" + }, + { + "lat": "33.787884000", + "lng": "-117.871607000" + }, + { + "lat": "33.787883000", + "lng": "-117.871513000" + }, + { + "lat": "33.787883000", + "lng": "-117.871162000" + }, + { + "lat": "33.787883000", + "lng": "-117.870965000" + }, + { + "lat": "33.787883000", + "lng": "-117.870767000" + }, + { + "lat": "33.787883000", + "lng": "-117.870517000" + }, + { + "lat": "33.787881000", + "lng": "-117.870171000" + }, + { + "lat": "33.787882000", + "lng": "-117.869975000" + }, + { + "lat": "33.787882000", + "lng": "-117.869589000" + }, + { + "lat": "33.787886000", + "lng": "-117.869190000" + }, + { + "lat": "33.787884000", + "lng": "-117.869024000" + }, + { + "lat": "33.787885000", + "lng": "-117.868824000" + }, + { + "lat": "33.787883000", + "lng": "-117.868666000" + }, + { + "lat": "33.787881000", + "lng": "-117.868433000" + }, + { + "lat": "33.787881000", + "lng": "-117.868308000" + }, + { + "lat": "33.787881000", + "lng": "-117.868222000" + }, + { + "lat": "33.787880000", + "lng": "-117.868030000" + }, + { + "lat": "33.787880000", + "lng": "-117.867944000" + }, + { + "lat": "33.787888000", + "lng": "-117.867306000" + }, + { + "lat": "33.787838000", + "lng": "-117.867107000" + }, + { + "lat": "33.787838000", + "lng": "-117.866715000" + }, + { + "lat": "33.787838000", + "lng": "-117.866531000" + }, + { + "lat": "33.787838000", + "lng": "-117.866439000" + }, + { + "lat": "33.787838000", + "lng": "-117.866114000" + }, + { + "lat": "33.787838000", + "lng": "-117.865902000" + }, + { + "lat": "33.787838000", + "lng": "-117.865670000" + }, + { + "lat": "33.787881000", + "lng": "-117.865554000" + }, + { + "lat": "33.787881000", + "lng": "-117.865442000" + }, + { + "lat": "33.787881000", + "lng": "-117.865167000" + }, + { + "lat": "33.787882000", + "lng": "-117.865075000" + }, + { + "lat": "33.787882000", + "lng": "-117.864810000" + }, + { + "lat": "33.787882000", + "lng": "-117.864681000" + }, + { + "lat": "33.787882000", + "lng": "-117.864622000" + }, + { + "lat": "33.787883000", + "lng": "-117.864010000" + }, + { + "lat": "33.787883000", + "lng": "-117.863948000" + }, + { + "lat": "33.787883000", + "lng": "-117.863697000" + }, + { + "lat": "33.787883000", + "lng": "-117.863160000" + }, + { + "lat": "33.787884000", + "lng": "-117.862915000" + }, + { + "lat": "33.787884000", + "lng": "-117.862841000" + }, + { + "lat": "33.787884000", + "lng": "-117.862684000" + }, + { + "lat": "33.787884000", + "lng": "-117.862405000" + }, + { + "lat": "33.787884000", + "lng": "-117.862261000" + }, + { + "lat": "33.787885000", + "lng": "-117.861974000" + }, + { + "lat": "33.787884000", + "lng": "-117.861825000" + }, + { + "lat": "33.787885000", + "lng": "-117.861692000" + }, + { + "lat": "33.787885000", + "lng": "-117.861519000" + }, + { + "lat": "33.787886000", + "lng": "-117.861197000" + }, + { + "lat": "33.787887000", + "lng": "-117.860739000" + }, + { + "lat": "33.787887000", + "lng": "-117.860435000" + }, + { + "lat": "33.787887000", + "lng": "-117.860392000" + }, + { + "lat": "33.787888000", + "lng": "-117.860093000" + }, + { + "lat": "33.787888000", + "lng": "-117.859990000" + }, + { + "lat": "33.787889000", + "lng": "-117.859655000" + }, + { + "lat": "33.787888000", + "lng": "-117.859323000" + }, + { + "lat": "33.787888000", + "lng": "-117.859286000" + }, + { + "lat": "33.787888000", + "lng": "-117.858868000" + }, + { + "lat": "33.787888000", + "lng": "-117.858716000" + }, + { + "lat": "33.787887000", + "lng": "-117.858556000" + }, + { + "lat": "33.787887000", + "lng": "-117.858476000" + }, + { + "lat": "33.787887000", + "lng": "-117.858293000" + }, + { + "lat": "33.787887000", + "lng": "-117.858081000" + }, + { + "lat": "33.787886000", + "lng": "-117.857986000" + }, + { + "lat": "33.787846000", + "lng": "-117.857894000" + }, + { + "lat": "33.787846000", + "lng": "-117.857828000" + }, + { + "lat": "33.787846000", + "lng": "-117.857771000" + }, + { + "lat": "33.787847000", + "lng": "-117.857518000" + }, + { + "lat": "33.787848000", + "lng": "-117.857460000" + }, + { + "lat": "33.787848000", + "lng": "-117.857265000" + }, + { + "lat": "33.787849000", + "lng": "-117.857090000" + }, + { + "lat": "33.787849000", + "lng": "-117.857041000" + }, + { + "lat": "33.787891000", + "lng": "-117.856976000" + }, + { + "lat": "33.787891000", + "lng": "-117.856888000" + }, + { + "lat": "33.787890000", + "lng": "-117.856602000" + }, + { + "lat": "33.787889000", + "lng": "-117.856470000" + }, + { + "lat": "33.787889000", + "lng": "-117.856375000" + }, + { + "lat": "33.787970000", + "lng": "-117.856375000" + }, + { + "lat": "33.788076000", + "lng": "-117.856372000" + }, + { + "lat": "33.788321000", + "lng": "-117.856366000" + }, + { + "lat": "33.789279000", + "lng": "-117.856365000" + }, + { + "lat": "33.789620000", + "lng": "-117.856370000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793322000", + "lng": "-117.855591000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793316000", + "lng": "-117.852810000" + }, + { + "lat": "33.793325000", + "lng": "-117.852810000" + } + ] + ], + "54529": [ + [ + { + "lat": "33.793316000", + "lng": "-117.852811000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793208000", + "lng": "-117.856356000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791515000", + "lng": "-117.856444000" + }, + { + "lat": "33.791515000", + "lng": "-117.856466000" + }, + { + "lat": "33.791514000", + "lng": "-117.856490000" + }, + { + "lat": "33.791542000", + "lng": "-117.856709000" + }, + { + "lat": "33.791549000", + "lng": "-117.857350000" + }, + { + "lat": "33.791549000", + "lng": "-117.857446000" + }, + { + "lat": "33.791549000", + "lng": "-117.857501000" + }, + { + "lat": "33.791549000", + "lng": "-117.857579000" + }, + { + "lat": "33.791545000", + "lng": "-117.857716000" + }, + { + "lat": "33.791540000", + "lng": "-117.857839000" + }, + { + "lat": "33.791539000", + "lng": "-117.857940000" + }, + { + "lat": "33.791538000", + "lng": "-117.858105000" + }, + { + "lat": "33.791507000", + "lng": "-117.858204000" + }, + { + "lat": "33.791505000", + "lng": "-117.858913000" + }, + { + "lat": "33.791600000", + "lng": "-117.858912000" + }, + { + "lat": "33.791659000", + "lng": "-117.858912000" + }, + { + "lat": "33.791908000", + "lng": "-117.858912000" + }, + { + "lat": "33.792059000", + "lng": "-117.858872000" + }, + { + "lat": "33.792314000", + "lng": "-117.858872000" + }, + { + "lat": "33.792312000", + "lng": "-117.858158000" + }, + { + "lat": "33.792312000", + "lng": "-117.858134000" + }, + { + "lat": "33.792478000", + "lng": "-117.858131000" + }, + { + "lat": "33.792659000", + "lng": "-117.858132000" + }, + { + "lat": "33.792658000", + "lng": "-117.858227000" + }, + { + "lat": "33.792655000", + "lng": "-117.858871000" + }, + { + "lat": "33.792602000", + "lng": "-117.858871000" + }, + { + "lat": "33.792481000", + "lng": "-117.858871000" + }, + { + "lat": "33.792314000", + "lng": "-117.858872000" + }, + { + "lat": "33.792059000", + "lng": "-117.858872000" + }, + { + "lat": "33.791908000", + "lng": "-117.858912000" + }, + { + "lat": "33.791659000", + "lng": "-117.858912000" + }, + { + "lat": "33.791505000", + "lng": "-117.858913000" + }, + { + "lat": "33.791507000", + "lng": "-117.858204000" + }, + { + "lat": "33.791491000", + "lng": "-117.858106000" + }, + { + "lat": "33.791491000", + "lng": "-117.858086000" + }, + { + "lat": "33.791493000", + "lng": "-117.857501000" + }, + { + "lat": "33.791493000", + "lng": "-117.857447000" + }, + { + "lat": "33.791494000", + "lng": "-117.856710000" + }, + { + "lat": "33.791514000", + "lng": "-117.856490000" + }, + { + "lat": "33.791515000", + "lng": "-117.856466000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.790354000", + "lng": "-117.856695000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.790279000", + "lng": "-117.856361000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789704000", + "lng": "-117.856466000" + }, + { + "lat": "33.789705000", + "lng": "-117.856787000" + }, + { + "lat": "33.789720000", + "lng": "-117.856889000" + }, + { + "lat": "33.789719000", + "lng": "-117.856967000" + }, + { + "lat": "33.789717000", + "lng": "-117.857152000" + }, + { + "lat": "33.789717000", + "lng": "-117.857169000" + }, + { + "lat": "33.789662000", + "lng": "-117.857182000" + }, + { + "lat": "33.789547000", + "lng": "-117.857208000" + }, + { + "lat": "33.789398000", + "lng": "-117.857172000" + }, + { + "lat": "33.789398000", + "lng": "-117.857084000" + }, + { + "lat": "33.789398000", + "lng": "-117.857020000" + }, + { + "lat": "33.789398000", + "lng": "-117.856947000" + }, + { + "lat": "33.789423000", + "lng": "-117.856947000" + }, + { + "lat": "33.789597000", + "lng": "-117.856945000" + }, + { + "lat": "33.789624000", + "lng": "-117.856935000" + }, + { + "lat": "33.789650000", + "lng": "-117.856915000" + }, + { + "lat": "33.789670000", + "lng": "-117.856886000" + }, + { + "lat": "33.789705000", + "lng": "-117.856787000" + }, + { + "lat": "33.789704000", + "lng": "-117.856466000" + }, + { + "lat": "33.789701000", + "lng": "-117.856365000" + }, + { + "lat": "33.789782000", + "lng": "-117.856364000" + }, + { + "lat": "33.790351000", + "lng": "-117.856360000" + }, + { + "lat": "33.791312000", + "lng": "-117.856358000" + }, + { + "lat": "33.791437000", + "lng": "-117.856363000" + }, + { + "lat": "33.791517000", + "lng": "-117.856367000" + }, + { + "lat": "33.791598000", + "lng": "-117.856366000" + }, + { + "lat": "33.793323000", + "lng": "-117.856355000" + }, + { + "lat": "33.793323000", + "lng": "-117.856178000" + }, + { + "lat": "33.793322000", + "lng": "-117.855284000" + }, + { + "lat": "33.793310000", + "lng": "-117.854187000" + }, + { + "lat": "33.793311000", + "lng": "-117.853698000" + }, + { + "lat": "33.793311000", + "lng": "-117.853367000" + }, + { + "lat": "33.793311000", + "lng": "-117.853212000" + }, + { + "lat": "33.793311000", + "lng": "-117.853097000" + }, + { + "lat": "33.793315000", + "lng": "-117.852996000" + }, + { + "lat": "33.793316000", + "lng": "-117.852810000" + } + ] + ] + }, + "groupRoutes": { + "263": { + "53966": { + "userId": "263", + "color": "#d62728", + "name": "Red Route", + "mapApp": "1", + "id": "6703", + "routeGroupId": "6703" + }, + "53970": { + "userId": "263", + "color": "#696969", + "name": "Rinker Route", + "mapApp": "1", + "id": "6706", + "routeGroupId": "6706" + }, + "54191": { + "userId": "263", + "color": "#096e90", + "name": "Teal Route", + "mapApp": "1", + "id": "6705", + "routeGroupId": "6705" + }, + "54256": { + "userId": "263", + "color": "#bd9e39", + "name": "Gold Route", + "mapApp": "1", + "id": "6707", + "routeGroupId": "6707" + }, + "54257": { + "userId": "263", + "color": "#000000", + "name": "Black Route", + "mapApp": "1", + "id": "6704", + "routeGroupId": "6704" + }, + "54282": { + "userId": "263", + "color": "#510094", + "name": "Weekend Route", + "mapApp": "1", + "id": "6710", + "routeGroupId": "6710" + }, + "54529": { + "userId": "263", + "color": "#393838", + "name": "Parking Lot", + "mapApp": "1", + "id": "6731", + "routeGroupId": "6731" + } + } + }, + "routeShortNames": { + "53966": null, + "53970": null, + "54191": null, + "54256": null, + "54257": null, + "54282": null, + "54529": null + }, + "routeSchedules": { + "stub": "stub" + }, + "routesRR": [], + "excludedRoutesID": [ + -1, + 54282 + ], + "stopsRR": [] +}; \ No newline at end of file From b2be3ae583a29f499a65e95201159740b8b0592e Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:55:51 -0800 Subject: [PATCH 16/31] refactor fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId into separate method --- src/loaders/ApiBasedRepositoryLoader.ts | 50 +++++++++++++------------ 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index d93000a..031d30b 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -103,30 +103,34 @@ export class ApiBasedRepositoryLoader { // Pass JSON output into two different methods to update repository const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system: ISystem) => { - const params = { - getStops: "2", - }; - - const formDataJsonObject = { - "s0": system.id, - "sA": 1 - }; - const formData = new FormData(); - formData.set("json", JSON.stringify(formDataJsonObject)); - - const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "POST", - body: formData, - }); - const json = await response.json(); - - await this.updateStopDataForSystemAndApiResponse(system, json); - await this.updateOrderedStopDataForExistingStops(json); - await this.updatePolylineDataForExistingRoutesAndApiResponse(json); + await this.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(system.id); })); } + public async fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId: string) { + const params = { + getStops: "2", + }; + + const formDataJsonObject = { + "s0": systemId, + "sA": 1 + }; + const formData = new FormData(); + formData.set("json", JSON.stringify(formDataJsonObject)); + + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "POST", + body: formData, + }); + const json = await response.json(); + + await this.updateStopDataForSystemAndApiResponse(systemId, json); + await this.updateOrderedStopDataForExistingStops(json); + await this.updatePolylineDataForExistingRoutesAndApiResponse(json); + } + public async fetchAndUpdateShuttleDataForExistingSystems() { const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system: ISystem) => { @@ -208,7 +212,7 @@ export class ApiBasedRepositoryLoader { })) } - protected async updateStopDataForSystemAndApiResponse(system: ISystem, json: any) { + protected async updateStopDataForSystemAndApiResponse(systemId: string, json: any) { if (json.stops) { const jsonStops = Object.values(json.stops); @@ -216,7 +220,7 @@ export class ApiBasedRepositoryLoader { const constructedStop: IStop = { name: stop.name, id: stop.id, - systemId: system.id, + systemId, coordinates: { latitude: parseFloat(stop.latitude), longitude: parseFloat(stop.longitude), From acc8d562c39bea1a674ccfb05480272177e91530 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:56:02 -0800 Subject: [PATCH 17/31] add json snapshot and test cases for method --- ...chStopAndPolylineDataSuccessfulResponse.ts | 2 +- .../ApiBasedRepositoryLoaderTests.test.ts | 33 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts b/test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts index 98465b4..a19e96f 100644 --- a/test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts +++ b/test/jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse.ts @@ -1,4 +1,4 @@ -export const fetchStopAndPolylineDataForRoutesWithSystemId = { +export const fetchStopAndPolylineDataSuccessfulResponse = { "stops": { "ID2032": { "routeId": "54529", diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index 41da8be..c891dc7 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -5,6 +5,9 @@ import { fetchSystemDataSuccessfulResponse } from "../jsonSnapshots/fetchSystemD import { fetchSystemDataFailedResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse"; import { fetchRouteDataSuccessfulResponse } from "../jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse"; import { ISystem } from "../../src/entities/entities"; +import { + fetchStopAndPolylineDataSuccessfulResponse +} from "../jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse"; /** * Function to update behavior of the global `fetch` function. @@ -134,13 +137,41 @@ describe("ApiBasedRepositoryLoader", () => { }); }); - describe("fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems", () => { + describe("fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId", () => { it("updates stop and polyline data if there are systems and response received", async () => { + updateGlobalFetchMockJson(fetchStopAndPolylineDataSuccessfulResponse); + const stopsArray = Object.values(fetchStopAndPolylineDataSuccessfulResponse.stops); + + await loader.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId("263"); + + const stops = await loader.repository.getStopsBySystemId("263"); + expect(stops.length).toEqual(stopsArray.length); + + await Promise.all(stops.map(async (stop) => { + const orderedStops = await loader.repository.getOrderedStopsByStopId(stop.id) + expect(orderedStops.length).toBeGreaterThan(0); + })); + + const routes = await loader.repository.getRoutesBySystemId("263"); + routes.forEach((route) => { + expect(route.polylineCoordinates.length).toBeGreaterThan(0); + }); }); it("throws the correct error if the API response contains no data", async () => { + // @ts-ignore + global.fetch = jest.fn(() => { + return Promise.resolve({ + json: () => Promise.reject(new SyntaxError("Unable to parse JSON")), + status: 200, + ok: true, + }) + }) as jest.Mock; + await assertAsyncCallbackThrowsApiResponseError(async () => { + await loader.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId("263"); + }); }) }); From df0e1d3d0f066d8acdf1b53e296d7814bac18a72 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:59:04 -0800 Subject: [PATCH 18/31] add error throwing to method --- src/loaders/ApiBasedRepositoryLoader.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index 031d30b..f9f740d 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -120,15 +120,21 @@ export class ApiBasedRepositoryLoader { formData.set("json", JSON.stringify(formDataJsonObject)); const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "POST", - body: formData, - }); - const json = await response.json(); - await this.updateStopDataForSystemAndApiResponse(systemId, json); - await this.updateOrderedStopDataForExistingStops(json); - await this.updatePolylineDataForExistingRoutesAndApiResponse(json); + try { + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "POST", + body: formData, + }); + const json = await response.json(); + + await this.updateStopDataForSystemAndApiResponse(systemId, json); + await this.updateOrderedStopDataForExistingStops(json); + await this.updatePolylineDataForExistingRoutesAndApiResponse(json); + } catch(e: any) { + console.error(`fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId failed for system ID ${systemId}:`, e); + throw new ApiResponseError(e.message); + } } public async fetchAndUpdateShuttleDataForExistingSystems() { From 81d0bb9e01fcd996b619af6c8c79dc0f0733ade1 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 14:59:15 -0800 Subject: [PATCH 19/31] move json syntax error setting to top-level method --- .../ApiBasedRepositoryLoaderTests.test.ts | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index c891dc7..6a3d615 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -41,6 +41,17 @@ async function assertAsyncCallbackThrowsApiResponseError(callback: () => Promise await expect(callback).rejects.toThrow(ApiResponseError); } +function updateGlobalFetchMockJsonToThrowSyntaxError() { + // @ts-ignore + global.fetch = jest.fn(() => { + return Promise.resolve({ + json: () => Promise.reject(new SyntaxError("Unable to parse JSON")), + status: 200, + ok: true, + }) + }) as jest.Mock; +} + describe("ApiBasedRepositoryLoader", () => { let loader: ApiBasedRepositoryLoader; @@ -122,14 +133,7 @@ describe("ApiBasedRepositoryLoader", () => { // The Passio API returns some invalid JSON if there is no data, // so simulate a JSON parsing error - // @ts-ignore - global.fetch = jest.fn(() => { - return Promise.resolve({ - json: () => Promise.reject(new SyntaxError("Unable to parse JSON")), - status: 200, - ok: true, - }) - }) as jest.Mock; + updateGlobalFetchMockJsonToThrowSyntaxError(); await assertAsyncCallbackThrowsApiResponseError(async () => { await loader.fetchAndUpdateRouteDataForSystemId("263"); @@ -160,14 +164,7 @@ describe("ApiBasedRepositoryLoader", () => { }); it("throws the correct error if the API response contains no data", async () => { - // @ts-ignore - global.fetch = jest.fn(() => { - return Promise.resolve({ - json: () => Promise.reject(new SyntaxError("Unable to parse JSON")), - status: 200, - ok: true, - }) - }) as jest.Mock; + updateGlobalFetchMockJsonToThrowSyntaxError(); await assertAsyncCallbackThrowsApiResponseError(async () => { await loader.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId("263"); From 95f2181b1cd4e0292d6eca80f4657282f3d38632 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:03:29 -0800 Subject: [PATCH 20/31] add test for fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository --- src/loaders/ApiBasedRepositoryLoader.ts | 6 ++-- src/loaders/TimedApiBasedRepositoryLoader.ts | 2 +- .../ApiBasedRepositoryLoaderTests.test.ts | 30 ++++++++++++------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index f9f740d..fce25df 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -98,9 +98,7 @@ export class ApiBasedRepositoryLoader { } } - public async fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems() { - // Fetch from the API - // Pass JSON output into two different methods to update repository + public async fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository() { const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system: ISystem) => { await this.fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(system.id); @@ -108,6 +106,8 @@ export class ApiBasedRepositoryLoader { } public async fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId(systemId: string) { + // Fetch from the API + // Pass JSON output into two different methods to update repository const params = { getStops: "2", }; diff --git a/src/loaders/TimedApiBasedRepositoryLoader.ts b/src/loaders/TimedApiBasedRepositoryLoader.ts index be806d7..7588316 100644 --- a/src/loaders/TimedApiBasedRepositoryLoader.ts +++ b/src/loaders/TimedApiBasedRepositoryLoader.ts @@ -52,7 +52,7 @@ export class TimedApiBasedRepositoryLoader extends ApiBasedRepositoryLoader { await this.repository.clearRouteData(); await this.fetchAndUpdateRouteDataForExistingSystemsInRepository(); await this.repository.clearStopData(); - await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystems(); + await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository(); await this.repository.clearShuttleData(); await this.fetchAndUpdateShuttleDataForExistingSystems(); await this.repository.clearEtaData(); diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index 6a3d615..07a53aa 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -8,6 +8,7 @@ import { ISystem } from "../../src/entities/entities"; import { fetchStopAndPolylineDataSuccessfulResponse } from "../jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse"; +import { generateMockSystems } from "../generators"; /** * Function to update behavior of the global `fetch` function. @@ -97,16 +98,7 @@ describe("ApiBasedRepositoryLoader", () => { test("calls fetchAndUpdateRouteDataForSystemId for all systems in repository", async () => { const spy = jest.spyOn(loader, "fetchAndUpdateRouteDataForSystemId"); - const systems: ISystem[] = [ - { - name: "Chapman University", - id: "1", - }, - { - name: "City of Monterey Park", - id: "2", - } - ]; + const systems = generateMockSystems(); await Promise.all(systems.map(async (system) => { await loader.repository.addOrUpdateSystem(system); @@ -114,7 +106,7 @@ describe("ApiBasedRepositoryLoader", () => { await loader.fetchAndUpdateRouteDataForExistingSystemsInRepository(); - expect(spy.mock.calls.length).toBe(2); + expect(spy.mock.calls.length).toBe(systems.length); }); }); @@ -141,6 +133,22 @@ describe("ApiBasedRepositoryLoader", () => { }); }); + describe("fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository", () => { + it("calls fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId for every system", async () => { + const spy = jest.spyOn(loader, "fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId"); + + const systems = generateMockSystems(); + + await Promise.all(systems.map(async (system) => { + await loader.repository.addOrUpdateSystem(system); + })); + + await loader.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository(); + + expect(spy.mock.calls.length).toBe(systems.length); + }); + }) + describe("fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId", () => { it("updates stop and polyline data if there are systems and response received", async () => { updateGlobalFetchMockJson(fetchStopAndPolylineDataSuccessfulResponse); From bc3526df88e11a9ac7a8325a5c76eb8f55b51423 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:16:28 -0800 Subject: [PATCH 21/31] refactor remaining methods into separate methods for improved testing --- src/loaders/ApiBasedRepositoryLoader.ts | 155 ++++++++++--------- src/loaders/TimedApiBasedRepositoryLoader.ts | 4 +- 2 files changed, 87 insertions(+), 72 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index fce25df..17cbbb8 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -137,85 +137,100 @@ export class ApiBasedRepositoryLoader { } } - public async fetchAndUpdateShuttleDataForExistingSystems() { + public async fetchAndUpdateShuttleDataForExistingSystemsInRepository() { const systems = await this.repository.getSystems(); await Promise.all(systems.map(async (system: ISystem) => { - const params = { - getBuses: "2" - }; - - const formDataJsonObject = { - "s0": system.id, - "sA": "1" - }; - - const formData = new FormData(); - formData.set("json", JSON.stringify(formDataJsonObject)); - - const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "POST", - body: formData, - }); - const json = await response.json(); - - if (json.buses && json.buses["-1"] === undefined) { - const jsonBuses = Object.values(json.buses).map((busesArr: any) => { - return busesArr[0]; - }); - - await Promise.all(jsonBuses.map(async (jsonBus: any) => { - const constructedShuttle: IShuttle = { - name: jsonBus.bus, - coordinates: { - latitude: parseFloat(jsonBus.latitude), - longitude: parseFloat(jsonBus.longitude), - }, - routeId: jsonBus.routeId, - systemId: system.id, - id: `${jsonBus.busId}` - } - - await this.repository.addOrUpdateShuttle(constructedShuttle); - })) - } + const systemId = system.id; + await this.fetchAndUpdateShuttleDataForSystemId(systemId); })); } - public async fetchAndUpdateEtaDataForExistingOrderedStops() { + public async fetchAndUpdateShuttleDataForSystemId(systemId: string) { + const params = { + getBuses: "2" + }; + + const formDataJsonObject = { + "s0": systemId, + "sA": "1" + }; + + const formData = new FormData(); + formData.set("json", JSON.stringify(formDataJsonObject)); + + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "POST", + body: formData, + }); + const json = await response.json(); + + if (json.buses && json.buses["-1"] === undefined) { + const jsonBuses = Object.values(json.buses).map((busesArr: any) => { + return busesArr[0]; + }); + + await Promise.all(jsonBuses.map(async (jsonBus: any) => { + const constructedShuttle: IShuttle = { + name: jsonBus.bus, + coordinates: { + latitude: parseFloat(jsonBus.latitude), + longitude: parseFloat(jsonBus.longitude), + }, + routeId: jsonBus.routeId, + systemId: systemId, + id: `${jsonBus.busId}` + } + + await this.repository.addOrUpdateShuttle(constructedShuttle); + })) + } + } + + public async fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository() { const systems = await this.repository.getSystems() await Promise.all(systems.map(async (system: ISystem) => { - const stops = await this.repository.getStopsBySystemId(system.id); - await Promise.all(stops.map(async (stop) => { - const params = { - eta: "3", - stopIds: stop.id, + const systemId = system.id; + await this.fetchAndUpdateEtaDataForExistingStopsForSystemId(systemId); + })) + } + + public async fetchAndUpdateEtaDataForExistingStopsForSystemId(systemId: string) { + const stops = await this.repository.getStopsBySystemId(systemId); + await Promise.all(stops.map(async (stop) => { + let stopId = stop.id; + await this.fetchAndUpdateEtaDataForStopId(stopId); + })); + } + + public async fetchAndUpdateEtaDataForStopId(stopId: string) { + const params = { + eta: "3", + stopIds: stopId, + }; + + const query = new URLSearchParams(params).toString(); + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "GET", + }); + const json = await response.json(); + + if (json.ETAs && json.ETAs[stopId]) { + // Continue with the parsing + json.ETAs[stopId].forEach((jsonEta: any) => { + // Update cache + const shuttleId: string = jsonEta.busId; + + const eta: IEta = { + secondsRemaining: jsonEta.secondsSpent, + shuttleId: `${shuttleId}`, + stopId: stopId, + millisecondsSinceEpoch: Date.now(), }; - const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "GET", - }); - const json = await response.json(); - - if (json.ETAs && json.ETAs[stop.id]) { - // Continue with the parsing - json.ETAs[stop.id].forEach((jsonEta: any) => { - // Update cache - const shuttleId: string = jsonEta.busId; - - const eta: IEta = { - secondsRemaining: jsonEta.secondsSpent, - shuttleId: `${shuttleId}`, - stopId: stop.id, - millisecondsSinceEpoch: Date.now(), - }; - - this.repository.addOrUpdateEta(eta); - }); - } - })); - })) + this.repository.addOrUpdateEta(eta); + }); + } } protected async updateStopDataForSystemAndApiResponse(systemId: string, json: any) { diff --git a/src/loaders/TimedApiBasedRepositoryLoader.ts b/src/loaders/TimedApiBasedRepositoryLoader.ts index 7588316..763c9fa 100644 --- a/src/loaders/TimedApiBasedRepositoryLoader.ts +++ b/src/loaders/TimedApiBasedRepositoryLoader.ts @@ -54,9 +54,9 @@ export class TimedApiBasedRepositoryLoader extends ApiBasedRepositoryLoader { await this.repository.clearStopData(); await this.fetchAndUpdateStopAndPolylineDataForRoutesInExistingSystemsInRepository(); await this.repository.clearShuttleData(); - await this.fetchAndUpdateShuttleDataForExistingSystems(); + await this.fetchAndUpdateShuttleDataForExistingSystemsInRepository(); await this.repository.clearEtaData(); - await this.fetchAndUpdateEtaDataForExistingOrderedStops(); + await this.fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository(); } catch (e) { console.error(e); } From ad6a9191f3d5fe70df3b6e86b6447a2f1cd31ace Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:38:27 -0800 Subject: [PATCH 22/31] add remaining test cases --- .../ApiBasedRepositoryLoaderTests.test.ts | 71 ++++++++++++++++--- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index 07a53aa..a8704aa 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -4,11 +4,11 @@ import { UnoptimizedInMemoryRepository } from "../../src/repositories/Unoptimize import { fetchSystemDataSuccessfulResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataSuccessfulResponse"; import { fetchSystemDataFailedResponse } from "../jsonSnapshots/fetchSystemData/fetchSystemDataFailedResponse"; import { fetchRouteDataSuccessfulResponse } from "../jsonSnapshots/fetchRouteData/fetchRouteDataSuccessfulResponse"; -import { ISystem } from "../../src/entities/entities"; import { fetchStopAndPolylineDataSuccessfulResponse } from "../jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse"; -import { generateMockSystems } from "../generators"; +import { generateMockStops, generateMockSystems } from "../generators"; +import { IStop } from "../../src/entities/entities"; /** * Function to update behavior of the global `fetch` function. @@ -111,7 +111,7 @@ describe("ApiBasedRepositoryLoader", () => { }); describe("fetchAndUpdateRouteDataForSystemId", () => { - it("updates route data in repository if there are systems and response received", async () => { + it("updates route data in repository if response received", async () => { updateGlobalFetchMockJson(fetchRouteDataSuccessfulResponse); await loader.fetchAndUpdateRouteDataForSystemId("263"); @@ -150,7 +150,7 @@ describe("ApiBasedRepositoryLoader", () => { }) describe("fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId", () => { - it("updates stop and polyline data if there are systems and response received", async () => { + it("updates stop and polyline data if response received", async () => { updateGlobalFetchMockJson(fetchStopAndPolylineDataSuccessfulResponse); const stopsArray = Object.values(fetchStopAndPolylineDataSuccessfulResponse.stops); @@ -180,23 +180,78 @@ describe("ApiBasedRepositoryLoader", () => { }) }); - describe("fetchAndUpdateShuttleDataForExistingSystems", () => { - it("updates shuttle data in repository if there are systems and response received", async () => { + describe("fetchAndUpdateShuttleDataForExistingSystemsInRepository", () => { + it("calls fetchAndUpdateShuttleDataForSystemId for every system", async () => { + const spy = jest.spyOn(loader, "fetchAndUpdateShuttleDataForSystemId"); + + const systems = generateMockSystems(); + await Promise.all(systems.map(async (system) => { + await loader.repository.addOrUpdateSystem(system); + })) + + await loader.fetchAndUpdateShuttleDataForExistingSystemsInRepository(); + + expect(spy.mock.calls.length).toBe(systems.length); + }); + }); + + describe("fetchAndUpdateShuttleDataForSystemId", () => { + it("updates shuttle data in repository if response received", async () => { }); it("throws the correct error if the API response contains no data", async () => { + updateGlobalFetchMockJsonToThrowSyntaxError(); + + await assertAsyncCallbackThrowsApiResponseError(async () => { + await loader.fetchAndUpdateShuttleDataForSystemId("263"); + }); + }); + }); + + describe("fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository", () => { + it("calls fetchAndUpdateEtaDataFoExistingStopsForSystemId for every system in repository", async () => { }); }); - describe("fetchAndUpdateEtaDataForExistingSystems", () => { - it("updates shuttle data in repository if there are systems and response received", async () => { + describe("fetchAndUpdateEtaDataForExistingStopsForSystemId", () => { + it("calls fetchAndUpdateEtaDataForStopId for every stop in repository", async () => { + // const systems = generateMockSystems(); + // await Promise.all(systems.map(async (system) => { + // await loader.repository.addOrUpdateSystem(system); + // })); + // + // const stop: IStop = { + // coordinates: { + // latitude: 1, + // longitude: 1, + // }, + // id: "1", + // name: "Chapman Court", + // systemId: "263", + // }; + // await loader.repository.addOrUpdateStop(stop); + const stops = generateMockStops(); + await Promise.all(stops.map(async (stop) => { + await loader.repository.addOrUpdateStop(stop); + })) + + + }); + }); + + describe("fetchAndUpdateEtaDataForStopId", () => { + it("updates ETA data for stop id if response received", async () => { }); it("throws the correct error if the API response contains no data", async () => { + updateGlobalFetchMockJsonToThrowSyntaxError(); + await assertAsyncCallbackThrowsApiResponseError(async () => { + await loader.fetchAndUpdateEtaDataForStopId("263"); + }); }); }); }); From 1027927bd69bb1a88fcd9f83ab7568230773a6bb Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:41:28 -0800 Subject: [PATCH 23/31] add test implementations for methods involving loops --- .../ApiBasedRepositoryLoaderTests.test.ts | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index a8704aa..90cb41f 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -211,33 +211,35 @@ describe("ApiBasedRepositoryLoader", () => { describe("fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository", () => { it("calls fetchAndUpdateEtaDataFoExistingStopsForSystemId for every system in repository", async () => { + const spy = jest.spyOn(loader, "fetchAndUpdateEtaDataForExistingStopsForSystemId"); + const systems = generateMockSystems(); + await Promise.all(systems.map(async (system) => { + await loader.repository.addOrUpdateSystem(system); + })); + + await loader.fetchAndUpdateEtaDataForExistingStopsForSystemsInRepository(); + + expect(spy.mock.calls.length).toBe(systems.length); }); }); describe("fetchAndUpdateEtaDataForExistingStopsForSystemId", () => { it("calls fetchAndUpdateEtaDataForStopId for every stop in repository", async () => { - // const systems = generateMockSystems(); - // await Promise.all(systems.map(async (system) => { - // await loader.repository.addOrUpdateSystem(system); - // })); - // - // const stop: IStop = { - // coordinates: { - // latitude: 1, - // longitude: 1, - // }, - // id: "1", - // name: "Chapman Court", - // systemId: "263", - // }; - // await loader.repository.addOrUpdateStop(stop); + const spy = jest.spyOn(loader, "fetchAndUpdateEtaDataForStopId"); + const stops = generateMockStops(); + stops.forEach((stop) => { + stop.systemId = "1"; + }); + await Promise.all(stops.map(async (stop) => { await loader.repository.addOrUpdateStop(stop); - })) + })); + await loader.fetchAndUpdateEtaDataForExistingStopsForSystemId("1"); + expect(spy.mock.calls.length).toEqual(stops.length); }); }); From 871f3b91797f11e76e12261be7a82daba01985a9 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:43:21 -0800 Subject: [PATCH 24/31] rename shuttle data fetch snapshot --- .../fetchShuttleDataSuccessfulResponse.ts} | 2 +- test/loaders/temp.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename test/jsonSnapshots/{genericShuttleDataBySystemId.ts => fetchShuttleData/fetchShuttleDataSuccessfulResponse.ts} (98%) diff --git a/test/jsonSnapshots/genericShuttleDataBySystemId.ts b/test/jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse.ts similarity index 98% rename from test/jsonSnapshots/genericShuttleDataBySystemId.ts rename to test/jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse.ts index 04edca6..877ab2d 100644 --- a/test/jsonSnapshots/genericShuttleDataBySystemId.ts +++ b/test/jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse.ts @@ -1,5 +1,5 @@ // Snapshot taken from the Passio GO! API -export const genericShuttleDataBySystemId = { +export const fetchShuttleDataSuccessfulResponse = { "alertCRC": "23c1b91c", "buses": { "402840": [ diff --git a/test/loaders/temp.ts b/test/loaders/temp.ts index 3248494..160b490 100644 --- a/test/loaders/temp.ts +++ b/test/loaders/temp.ts @@ -6,7 +6,7 @@ import { } from "../../src/repositories/ApiBasedRepository"; import { IEta, IShuttle, IStop } from "../../src/entities/entities"; import { genericEtaDataByStopId } from "../jsonSnapshots/genericEtaDataBySystemId"; -import { genericShuttleDataBySystemId } from "../jsonSnapshots/genericShuttleDataBySystemId"; +import { fetchShuttleDataSuccessfulResponse } from "../jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse"; /** * Update the global fetch function to return a specific object. @@ -290,7 +290,7 @@ describe("updateEtasForSystemIfTTL", () => { describe("getShuttleById", () => { test("getShuttleById returns null if unseeded cache", async () => { - updateGlobalFetchMockJson(genericShuttleDataBySystemId); + updateGlobalFetchMockJson(fetchShuttleDataSuccessfulResponse); const initialCache: ApiBasedRepositoryCache = {}; const repository = new ApiBasedRepository(initialCache); @@ -300,7 +300,7 @@ describe("getShuttleById", () => { }); test("getShuttleById returns data if present", async () => { - updateGlobalFetchMockJson(genericShuttleDataBySystemId); + updateGlobalFetchMockJson(fetchShuttleDataSuccessfulResponse); const initialCacheShuttle = { coordinates: { From eb5d872a1e70b1c09265e0cefac1a44070b55128 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:43:34 -0800 Subject: [PATCH 25/31] delete temp tests --- test/loaders/temp.ts | 422 ------------------------------------------- 1 file changed, 422 deletions(-) delete mode 100644 test/loaders/temp.ts diff --git a/test/loaders/temp.ts b/test/loaders/temp.ts deleted file mode 100644 index 160b490..0000000 --- a/test/loaders/temp.ts +++ /dev/null @@ -1,422 +0,0 @@ -import { beforeEach, describe, expect, jest, test } from "@jest/globals"; -import { - ApiBasedRepository, - ApiBasedRepositoryCache, - ApiBasedRepositoryMillisecondTTLs -} from "../../src/repositories/ApiBasedRepository"; -import { IEta, IShuttle, IStop } from "../../src/entities/entities"; -import { genericEtaDataByStopId } from "../jsonSnapshots/genericEtaDataBySystemId"; -import { fetchShuttleDataSuccessfulResponse } from "../jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse"; - -/** - * Update the global fetch function to return a specific object. - * @param obj - */ -function updateGlobalFetchMockJson(obj: any) { - // @ts-ignore - global.fetch = jest.fn(() => { - return Promise.resolve({ - json: () => Promise.resolve(obj) - }) - }) as jest.Mock; -} - -/** - * Reset the global fetch function mock's JSON to return an empty object. - * @param obj - */ -function resetGlobalFetchMockJson() { - updateGlobalFetchMockJson({}) -} - -beforeEach(() => { - resetGlobalFetchMockJson(); -}) - - -describe("getEtaForShuttleAndStopId", () => { - test("getEtaForShuttleAndStopId returns correct ETA data", async () => { - updateGlobalFetchMockJson(genericEtaDataByStopId); - - const initialCache: ApiBasedRepositoryCache = { - etasForStopId: { - "177666": [ - { - secondsRemaining: 587, - shuttleId: "5577", - stopId: "177666", - millisecondsSinceEpoch: Date.now(), - }, - { - secondsRemaining: 226, - shuttleId: "9909", - stopId: "177666", - millisecondsSinceEpoch: Date.now(), - } - ], - }, - } - - const repository = new ApiBasedRepository(initialCache); - - repository.getShuttleById = jest.fn(async () => { - const shuttle: IShuttle = { - id: "5577", - name: "08", - coordinates: { - latitude: 33.7933406, - longitude: -117.8539321, - }, - routeId: "53966", - systemId: "1", - }; - return shuttle; - }); - - repository.updateEtasForSystemIfTTL = jest.fn(async () => { - }); - - const result = await repository.getEtaForShuttleAndStopId("5577", "177666"); - - expect(result?.secondsRemaining).toEqual(587); - expect(result?.millisecondsSinceEpoch).toBeDefined(); - expect(result?.shuttleId).toEqual("5577"); - expect(result?.stopId).toEqual("177666"); - }); - - test("getEtaForShuttleAndStopId returns null if API call is invalid and cache is empty", async () => { - const repository = new ApiBasedRepository(); - const result = await repository.getEtaForShuttleAndStopId("5577", "177666"); - - expect(result).toEqual(null); - }); -}); - -describe("getEtasForShuttleId", () => { - test("getEtasForShuttleId returns correct ETA data", async () => { - updateGlobalFetchMockJson(genericEtaDataByStopId); - - const initialCache: ApiBasedRepositoryCache = { - etasForStopId: {}, - etasForShuttleId: { - "5577": [ - { - secondsRemaining: 587, - shuttleId: "5577", - stopId: "177666", - millisecondsSinceEpoch: Date.now(), - } - ] - }, - }; - - const ttls: ApiBasedRepositoryMillisecondTTLs = { - etasForShuttleId: 100000, - etasForStopId: 100000, - }; - - const repository = new ApiBasedRepository(initialCache, ttls); - repository.updateEtasForSystemIfTTL = jest.fn(async () => { - }); - repository.getShuttleById = jest.fn(async () => { - const shuttle: IShuttle = { - id: "5577", - name: "08", - coordinates: { - latitude: 33.7933406, - longitude: -117.8539321, - }, - routeId: "53966", - systemId: "1", - }; - return shuttle; - }); - const result = await repository.getEtasForShuttleId("5577"); - - // @ts-ignore - expect(result).toEqual(initialCache.etasForShuttleId["5577"]); - }); - - test("getEtasForShuttleId returns empty array if no data available", async () => { - const repository = new ApiBasedRepository(); - repository.updateEtasForSystemIfTTL = jest.fn(async () => { - }); - const result = await repository.getEtasForShuttleId("5577"); - - expect(result).toEqual([]); - }); -}); - -describe("getEtasForStopId", () => { - test("getEtasForStopId returns correct ETA data", async () => { - // Because I'm testing updateEtasForSystemIfTTL separately, - // stub it out here - - updateGlobalFetchMockJson(genericEtaDataByStopId); - - const initialCache: ApiBasedRepositoryCache = { - etasForStopId: { - "177666": [ - { - secondsRemaining: 587, - shuttleId: "5577", - stopId: "177666", - millisecondsSinceEpoch: Date.now(), - } - ] - }, - etasForShuttleId: {} - }; - - const ttls: ApiBasedRepositoryMillisecondTTLs = { - etasForShuttleId: 100000, - etasForStopId: 100000, - }; - - const repository = new ApiBasedRepository(initialCache, ttls); - repository.getStopById = jest.fn(async () => { - const stop: IStop = { - name: "Chapman Court", - systemId: "1", - id: "177666", - coordinates: { - latitude: 33.796796, - longitude: -117.889293 - }, - }; - return stop; - }); - repository.updateEtasForSystemIfTTL = jest.fn(async () => { - }); - const result = await repository.getEtasForStopId("177666"); - - expect(result).toEqual(initialCache.etasForStopId!["177666"]); - }); - - test("getEtasForStopId returns empty array if no data available", async () => { - const repository = new ApiBasedRepository(); - repository.updateEtasForSystemIfTTL = jest.fn(async () => { - }); - const result = await repository.getEtasForShuttleId("5577"); - - expect(result).toEqual([]); - }); -}); - -describe("updateEtasForSystemIfTTL", () => { - // test("updateEtasForSystemIfTTL does nothing if data is not TTL", async () => { - // updateGlobalFetchMockJson(genericEtaDataByStopId); - // - // // If ETA data is not TTL, then don't do anything - // const expectedEta: IEta = { - // secondsRemaining: 587, - // shuttleId: "5577", - // stopId: "177666", - // millisecondsSinceEpoch: Date.now() - 1000, - // }; - // - // const initialCache: ApiBasedRepositoryCache = { - // etasForShuttleId: { - // "5577": [ - // expectedEta, - // ], - // }, - // etasForStopId: { - // "177666": [ - // expectedEta, - // ], - // }, - // stopsBySystemId: { - // "1": [ - // { - // systemId: "1", - // millisecondsSinceEpoch: Date.now() - 1000, - // name: "Chapman Court", - // id: "177666", - // coordinates: { - // latitude: 33.796796, - // longitude: -117.889293 - // }, - // } - // ], - // }, - // }; - // - // const ttls: ApiBasedRepositoryMillisecondTTLs = { - // etasForShuttleId: 100000, - // etasForStopId: 100000, - // }; - // - // const repository = new ApiBasedRepository(initialCache, ttls); - // await repository.updateEtasForSystemIfTTL("1"); - // - // const updatedResult = await repository.getEtaForShuttleAndStopId( - // "5577", - // "177666", - // ); - // expect(updatedResult?.millisecondsSinceEpoch).toEqual(expectedEta.millisecondsSinceEpoch); - // }); - - test("updateEtasForSystemIfTTL updates all ETA data if data is TTL", async () => { - updateGlobalFetchMockJson(genericEtaDataByStopId); - - const sampleStop: IStop = { - name: "Chapman Court", - systemId: "1", - id: "177666", - coordinates: { - latitude: 33.796796, - longitude: -117.889293 - }, - } - - const repository = new ApiBasedRepository(); - repository.getStopsBySystemId = jest.fn(async () => { - return [ - sampleStop - ]; - }); - - repository.getStopById = jest.fn(async () => { - return sampleStop; - }); - - await repository.updateEtasForSystemIfTTL("1"); - - const updatedResult = await repository.getEtasForStopId("177666"); - expect(updatedResult.length).toEqual(2); - }); -}); - -describe("getShuttleById", () => { - test("getShuttleById returns null if unseeded cache", async () => { - updateGlobalFetchMockJson(fetchShuttleDataSuccessfulResponse); - - const initialCache: ApiBasedRepositoryCache = {}; - const repository = new ApiBasedRepository(initialCache); - - const shuttle = await repository.getShuttleById("5577"); - expect(shuttle).toBeNull(); - }); - - test("getShuttleById returns data if present", async () => { - updateGlobalFetchMockJson(fetchShuttleDataSuccessfulResponse); - - const initialCacheShuttle = { - coordinates: { - latitude: 33.7917818, - longitude: -117.8589646, - }, - name: "08", - routeId: "53966", - systemId: "1", - id: "5577", - } - - const initialCache: ApiBasedRepositoryCache = { - shuttleByShuttleId: { - "5577": initialCacheShuttle - } - }; - - const ttls: ApiBasedRepositoryMillisecondTTLs = { - shuttleByShuttleId: 1000, - }; - - const repository = new ApiBasedRepository(initialCache, ttls); - repository.updateStopsForSystemIdIfTTL = jest.fn(async () => { - }) - - const shuttle = await repository.getShuttleById("5577"); - expect(shuttle).toEqual(initialCacheShuttle); - }); -}); - -// TODO: enable when implemented -// describe("getShuttlesBySystemId", () => { -// test("getShuttlesBySystemId returns old data if not expired", async () => { -// updateGlobalFetchMockJson(genericShuttleDataBySystemId); -// -// const initialCacheShuttle = { -// coordinates: { -// latitude: 33.791781, -// longitude: -117.8589646, -// }, -// name: "08", -// routeId: "53966", -// systemId: "1", -// id: "5577", -// millisecondsSinceEpoch: Date.now() - 1000, -// }; -// -// const initialCache: ApiBasedRepositoryCache = { -// shuttlesBySystemId: { -// "1": [ -// initialCacheShuttle, -// ] -// }, -// shuttleByShuttleId: { -// "5577": initialCacheShuttle, -// } -// }; -// -// const ttls: ApiBasedRepositoryMillisecondTTLs = { -// shuttleByShuttleId: 100000, -// shuttlesBySystemId: 100000, -// }; -// -// const repository = new ApiBasedRepository(initialCache, ttls); -// const shuttles = await repository.getShuttlesBySystemId("1"); -// expect(shuttles.length).toEqual(1); -// expect(shuttles[0].id).toEqual(initialCacheShuttle.id); -// }); -// -// test("getShuttlesBySystemId returns fresh data if expired", async () => { -// updateGlobalFetchMockJson(genericShuttleDataBySystemId); -// -// // TODO: move construction of shuttle into method -// const initialCacheShuttle = { -// coordinates: { -// latitude: 33.791781, -// longitude: -117.8589646, -// }, -// name: "08", -// routeId: "53966", -// systemId: "1", -// id: "5577", -// millisecondsSinceEpoch: Date.now() - 100000, -// }; -// -// const initialCache: ApiBasedRepositoryCache = { -// shuttlesBySystemId: { -// "1": [ -// initialCacheShuttle, -// ] -// }, -// shuttleByShuttleId: { -// "5577": initialCacheShuttle, -// } -// }; -// -// const ttls: ApiBasedRepositoryMillisecondTTLs = { -// shuttleByShuttleId: 1000, -// shuttlesBySystemId: 1000, -// }; -// -// const repository = new ApiBasedRepository(initialCache, ttls); -// const shuttles = await repository.getShuttlesBySystemId("1"); -// -// expect(shuttles.length).toEqual(1); -// expect(shuttles[0].id).toEqual("5577"); -// expect(shuttles[0].millisecondsSinceEpoch).not.toEqual(initialCacheShuttle.millisecondsSinceEpoch); -// }); -// -// test("getShuttlesBySystemId returns fresh data if no seeded data", async () => { -// updateGlobalFetchMockJson(genericShuttleDataBySystemId); -// -// const repository = new ApiBasedRepository(); -// const shuttles = await repository.getShuttlesBySystemId("1"); -// -// expect(shuttles.length).toEqual(1); -// }); -// }); From 40231adfec265137363278593c4cc80df471f690 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:45:23 -0800 Subject: [PATCH 26/31] add test case for successful shuttle data fetch --- test/loaders/ApiBasedRepositoryLoaderTests.test.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index 90cb41f..ea34042 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -9,6 +9,9 @@ import { } from "../jsonSnapshots/fetchStopAndPolylineData/fetchStopAndPolylineDataSuccessfulResponse"; import { generateMockStops, generateMockSystems } from "../generators"; import { IStop } from "../../src/entities/entities"; +import { + fetchShuttleDataSuccessfulResponse +} from "../jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse"; /** * Function to update behavior of the global `fetch` function. @@ -197,7 +200,14 @@ describe("ApiBasedRepositoryLoader", () => { describe("fetchAndUpdateShuttleDataForSystemId", () => { it("updates shuttle data in repository if response received", async () => { + updateGlobalFetchMockJson(fetchShuttleDataSuccessfulResponse); + const busesInResponse = Object.values(fetchShuttleDataSuccessfulResponse.buses); + await loader.fetchAndUpdateShuttleDataForSystemId("263"); + + const shuttles = await loader.repository.getShuttlesBySystemId("263"); + + expect(shuttles.length).toEqual(busesInResponse.length); }); it("throws the correct error if the API response contains no data", async () => { From 7955f27e77b77aab3f561b976f16acf197367da6 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:46:27 -0800 Subject: [PATCH 27/31] rename eta data response for consistency --- .../{ => fetchEtaData}/genericEtaDataBySystemId.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test/jsonSnapshots/{ => fetchEtaData}/genericEtaDataBySystemId.ts (98%) diff --git a/test/jsonSnapshots/genericEtaDataBySystemId.ts b/test/jsonSnapshots/fetchEtaData/genericEtaDataBySystemId.ts similarity index 98% rename from test/jsonSnapshots/genericEtaDataBySystemId.ts rename to test/jsonSnapshots/fetchEtaData/genericEtaDataBySystemId.ts index 3b603c7..4ba29d9 100644 --- a/test/jsonSnapshots/genericEtaDataBySystemId.ts +++ b/test/jsonSnapshots/fetchEtaData/genericEtaDataBySystemId.ts @@ -1,5 +1,5 @@ // Snapshot taken from the Passio GO! API -export const genericEtaDataByStopId = { +export const fetchEtaDataSuccessfulResponse = { "ETAs": { "177666": [ { From 05c03aa61fa05aa101f9618b030cc9e2b7295d62 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:47:37 -0800 Subject: [PATCH 28/31] rename the snapshot file --- ...ericEtaDataBySystemId.ts => fetchEtaDataSuccessfulResponse.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/jsonSnapshots/fetchEtaData/{genericEtaDataBySystemId.ts => fetchEtaDataSuccessfulResponse.ts} (100%) diff --git a/test/jsonSnapshots/fetchEtaData/genericEtaDataBySystemId.ts b/test/jsonSnapshots/fetchEtaData/fetchEtaDataSuccessfulResponse.ts similarity index 100% rename from test/jsonSnapshots/fetchEtaData/genericEtaDataBySystemId.ts rename to test/jsonSnapshots/fetchEtaData/fetchEtaDataSuccessfulResponse.ts From 8e944892cc7567c78a3e3a2d2ca1fdbaa73cbe34 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:49:47 -0800 Subject: [PATCH 29/31] add test case for successful eta data response --- test/loaders/ApiBasedRepositoryLoaderTests.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts index ea34042..ed4b92d 100644 --- a/test/loaders/ApiBasedRepositoryLoaderTests.test.ts +++ b/test/loaders/ApiBasedRepositoryLoaderTests.test.ts @@ -12,6 +12,7 @@ import { IStop } from "../../src/entities/entities"; import { fetchShuttleDataSuccessfulResponse } from "../jsonSnapshots/fetchShuttleData/fetchShuttleDataSuccessfulResponse"; +import { fetchEtaDataSuccessfulResponse } from "../jsonSnapshots/fetchEtaData/fetchEtaDataSuccessfulResponse"; /** * Function to update behavior of the global `fetch` function. @@ -255,7 +256,15 @@ describe("ApiBasedRepositoryLoader", () => { describe("fetchAndUpdateEtaDataForStopId", () => { it("updates ETA data for stop id if response received", async () => { + updateGlobalFetchMockJson(fetchEtaDataSuccessfulResponse); + const stopId = "177666"; + // @ts-ignore + const etasFromResponse = fetchEtaDataSuccessfulResponse.ETAs[stopId] + await loader.fetchAndUpdateEtaDataForStopId(stopId); + + const etas = await loader.repository.getEtasForStopId(stopId); + expect(etas.length).toEqual(etasFromResponse.length); }); it("throws the correct error if the API response contains no data", async () => { From d1f8d940b3b7bcbbca0b2024c831bc81cea40026 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:51:00 -0800 Subject: [PATCH 30/31] remove console.error calls to leave responsibility to caller --- src/loaders/ApiBasedRepositoryLoader.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index 17cbbb8..a7717a4 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -46,7 +46,6 @@ export class ApiBasedRepositoryLoader { throw new Error("Received JSON object does not contain `all` field") } } catch(e: any) { - console.error("fetchAndUpdateSystemData call failed: ", e); throw new ApiResponseError(e.message); } } @@ -93,7 +92,6 @@ export class ApiBasedRepositoryLoader { })) } } catch(e: any) { - console.error(`fetchAndUpdateRouteDataForSystemId failed for system ID ${systemId}: ${e}`); throw new ApiResponseError(e.message); } } @@ -132,7 +130,6 @@ export class ApiBasedRepositoryLoader { await this.updateOrderedStopDataForExistingStops(json); await this.updatePolylineDataForExistingRoutesAndApiResponse(json); } catch(e: any) { - console.error(`fetchAndUpdateStopAndPolylineDataForRoutesWithSystemId failed for system ID ${systemId}:`, e); throw new ApiResponseError(e.message); } } From c902472457a45e7cd134a24de70d14ab626e0b08 Mon Sep 17 00:00:00 2001 From: Brendan Chen Date: Wed, 22 Jan 2025 15:52:29 -0800 Subject: [PATCH 31/31] add try/catch to remaining methods --- src/loaders/ApiBasedRepositoryLoader.ts | 88 ++++++++++++++----------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/src/loaders/ApiBasedRepositoryLoader.ts b/src/loaders/ApiBasedRepositoryLoader.ts index a7717a4..de48179 100644 --- a/src/loaders/ApiBasedRepositoryLoader.ts +++ b/src/loaders/ApiBasedRepositoryLoader.ts @@ -156,31 +156,36 @@ export class ApiBasedRepositoryLoader { formData.set("json", JSON.stringify(formDataJsonObject)); const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "POST", - body: formData, - }); - const json = await response.json(); - if (json.buses && json.buses["-1"] === undefined) { - const jsonBuses = Object.values(json.buses).map((busesArr: any) => { - return busesArr[0]; + try { + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "POST", + body: formData, }); + const json = await response.json(); - await Promise.all(jsonBuses.map(async (jsonBus: any) => { - const constructedShuttle: IShuttle = { - name: jsonBus.bus, - coordinates: { - latitude: parseFloat(jsonBus.latitude), - longitude: parseFloat(jsonBus.longitude), - }, - routeId: jsonBus.routeId, - systemId: systemId, - id: `${jsonBus.busId}` - } + if (json.buses && json.buses["-1"] === undefined) { + const jsonBuses = Object.values(json.buses).map((busesArr: any) => { + return busesArr[0]; + }); - await this.repository.addOrUpdateShuttle(constructedShuttle); - })) + await Promise.all(jsonBuses.map(async (jsonBus: any) => { + const constructedShuttle: IShuttle = { + name: jsonBus.bus, + coordinates: { + latitude: parseFloat(jsonBus.latitude), + longitude: parseFloat(jsonBus.longitude), + }, + routeId: jsonBus.routeId, + systemId: systemId, + id: `${jsonBus.busId}` + } + + await this.repository.addOrUpdateShuttle(constructedShuttle); + })); + } + } catch(e: any) { + throw new ApiResponseError(e.message); } } @@ -207,26 +212,31 @@ export class ApiBasedRepositoryLoader { }; const query = new URLSearchParams(params).toString(); - const response = await fetch(`${this.baseUrl}?${query}`, { - method: "GET", - }); - const json = await response.json(); - if (json.ETAs && json.ETAs[stopId]) { - // Continue with the parsing - json.ETAs[stopId].forEach((jsonEta: any) => { - // Update cache - const shuttleId: string = jsonEta.busId; - - const eta: IEta = { - secondsRemaining: jsonEta.secondsSpent, - shuttleId: `${shuttleId}`, - stopId: stopId, - millisecondsSinceEpoch: Date.now(), - }; - - this.repository.addOrUpdateEta(eta); + try { + const response = await fetch(`${this.baseUrl}?${query}`, { + method: "GET", }); + const json = await response.json(); + + if (json.ETAs && json.ETAs[stopId]) { + // Continue with the parsing + json.ETAs[stopId].forEach((jsonEta: any) => { + // Update cache + const shuttleId: string = jsonEta.busId; + + const eta: IEta = { + secondsRemaining: jsonEta.secondsSpent, + shuttleId: `${shuttleId}`, + stopId: stopId, + millisecondsSinceEpoch: Date.now(), + }; + + this.repository.addOrUpdateEta(eta); + }); + } + } catch(e: any) { + throw new ApiResponseError(e.message); } }