-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrealtime.ts
207 lines (179 loc) · 7.73 KB
/
realtime.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
import fetch from "node-fetch";
import fs from "fs";
import { Alert, TripUpdate, VehiclePosition } from "./gtfs-realtime.js";
const API_DOMAIN = "http://127.0.0.1:5343/gtfs/seq/";
interface APIAlert {
id: string;
alert: Alert;
}
interface APITripUpdate {
id: string;
tripUpdate: TripUpdate;
}
interface APIVehiclePosition {
id: string;
vehicle: VehiclePosition;
}
/**
* Gets data from the API.
*
* @param {Array<string>} routeIds route IDs relevant to UQ Lakes station
*
* @returns {Promise<Array<Array<Alert>, Array<TripUpdate>, Array<VehiclePosition>>>} Promise that resolves to an array of three arrays: alerts, trip updates, and vehicle positions.
*/
async function getApiData(routeIds: Array<string>): Promise<any> {
/**
* Gets alerts relevant to UQ Lakes Station.
*
* @param {Array<string>} routeIds route IDs relevant to UQ Lakes station
*
* @returns {Promise<Array<Alert>>} alerts relevant to UQ Lakes Station
*/
async function getAlerts(routeIds: Array<string>): Promise<Array<Alert>> {
/**
* Extracts the alerts from the API objects.
*
* @param {Array<APIAlert>} alerts raw alerts with IDs from the API
*
* @returns {Array<Alert>} extracted alerts
*/
function extractAlerts(alerts: Array<APIAlert>): Array<Alert> {
return alerts.map(alert => alert.alert);
}
/**
* Filters alerts to those relevant to UQ Lakes Station.
*
* @param {Array<Alert>} alerts all alerts from the API
* @param {Array<string>} routeIds route IDs relevant to UQ Lakes station
*
* @returns {Array<Alert>} alerts relevant to UQ Lakes Station
*/
function filterAlerts(alerts: Array<Alert>, routeIds: Array<string>): Array<Alert> {
return alerts.filter(alert => {
let alertRouteIds = alert.informedEntity.map(entity => entity.routeId);
return routeIds.some(routeId => alertRouteIds.includes(routeId))
});
}
let response = await fetch(API_DOMAIN + "alerts.json");
let buffer = await response.arrayBuffer();
let decoded = new TextDecoder().decode(buffer);
let jsonified = JSON.parse(decoded);
let entity = jsonified.entity;
let alerts = extractAlerts(entity);
return filterAlerts(alerts, routeIds);
}
/**
* Gets trip updates relevant to UQ Lakes Station.
*
* @param {Array<string>} routeIds route IDs relevant to UQ Lakes station
*
* @returns {Promise<Array<TripUpdate>>} trip updates relevant to UQ Lakes Station
*/
async function getTripUpdates(routeIds: Array<string>): Promise<Array<TripUpdate>> {
/**
* Extracts the trip updates from the API objects.
*
* @param {Array<APITripUpdate>} tripUpdates raw trip updates with IDs from the API
*
* @returns {Array<TripUpdate>} extracted trip updates
*/
function extractTripUpdates(tripUpdates: Array<APITripUpdate>): Array<TripUpdate> {
return tripUpdates.map(tripUpdate => tripUpdate.tripUpdate);
}
/**
* Filters trip updates to those relevant to UQ Lakes Station.
*
* @param {Array<TripUpdate>} tripUpdates all trip updates from the API
* @param {Array<string>} routeIds route IDs relevant to UQ Lakes station
*
* @returns {Array<TripUpdate>} trip updates relevant to UQ Lakes Station
*/
function filterTripUpdates(tripUpdates: Array<TripUpdate>, routeIds: Array<string>): Array<TripUpdate> {
return tripUpdates.filter(tripUpdate => tripUpdate.trip.routeId && routeIds.includes(tripUpdate.trip.routeId));
}
let response = await fetch(API_DOMAIN + "trip_updates.json");
let buffer = await response.arrayBuffer();
let decoded = new TextDecoder().decode(buffer);
let jsonified = JSON.parse(decoded);
let entity = jsonified.entity;
let tripUpdates = extractTripUpdates(entity);
return filterTripUpdates(tripUpdates, routeIds);
}
/**
* Gets vehicle positions relevant to UQ Lakes Station.
*
* @param {Array<string>} routeIds route IDs relevant to UQ Lakes station
*
* @returns {Promise<Array<VehiclePosition>>} vehicle positions relevant to UQ Lakes Station
*/
async function getVehiclePositions(routeIds: Array<string>): Promise<Array<VehiclePosition>> {
/**
* Extracts the vehicle positions from the API objects.
*
* @param {Array<APIVehiclePosition>} vehiclePositions raw vehicle positions with IDs from the API
*
* @returns {Array<VehiclePosition>} extracted vehicle positions
*/
function extractVehiclePositions(vehiclePositions: Array<APIVehiclePosition>): Array<VehiclePosition> {
return vehiclePositions.map(vehiclePosition => vehiclePosition.vehicle);
}
/**
* Filters vehicle positions to those relevant to UQ Lakes Station.
*
* @param {Array<VehiclePosition>} vehiclePositions all vehicle positions from the API
* @param {Array<string>} routeIds route IDs relevant to UQ Lakes station
*
* @returns {Array<VehiclePosition>} vehicle positions relevant to UQ Lakes Station
*/
function filterVehiclePositions(vehiclePositions: Array<VehiclePosition>, routeIds: Array<string>): Array<VehiclePosition> {
return vehiclePositions.filter(vehiclePosition =>
vehiclePosition.trip?.routeId
&& routeIds.includes(vehiclePosition.trip?.routeId)
);
}
let response = await fetch(API_DOMAIN + "vehicle_positions.json");
let buffer = await response.arrayBuffer();
let decoded = new TextDecoder().decode(buffer);
let jsonified = JSON.parse(decoded);
let entity = jsonified.entity;
let vehiclePositions = extractVehiclePositions(entity);
return filterVehiclePositions(vehiclePositions, routeIds);
}
let alerts = await getAlerts(routeIds);
let tripUpdates = await getTripUpdates(routeIds);
let vehiclePositions = await getVehiclePositions(routeIds);
return [alerts, tripUpdates, vehiclePositions];
}
/**
* Writes API data to local cached files.
*
* @param {Array<Alert>} alerts alerts to write to the cache
* @param {Array<TripUpdate>} tripUpdates alerts to write to the cache
* @param {Array<VehiclePosition>} vehiclePositions alerts to write to the cache
*/
async function writeApiData(alerts: Array<Alert>, tripUpdates: Array<TripUpdate>, vehiclePositions: Array<VehiclePosition>) {
/** Callback function used to log errors. */
const logError = (error: any) => { if (error) console.log(error); };
type APIEntity = Alert | TripUpdate | VehiclePosition;
/**
* Writes the entity to the local cached file specified by filename.
*
* @param {string} filename name of the file to write to
* @param {Array<APIEntity>} entity entity to write to the file
*/
async function writeApiDataHelper(filename: string, entity: Array<APIEntity>) {
fs.writeFile(`cached-data/${filename}.json`,
JSON.stringify(entity, null, 4),
logError
);
}
await writeApiDataHelper("alerts", alerts);
await writeApiDataHelper("trip_updates", tripUpdates);
await writeApiDataHelper("vehicle_positions", vehiclePositions);
}
export async function main(routeIds: Array<string>) {
let data = await getApiData(routeIds);
let [alerts, tripUpdates, vehiclePositions] = data;
writeApiData(alerts, tripUpdates, vehiclePositions);
return [alerts, tripUpdates, vehiclePositions];
}