-
Notifications
You must be signed in to change notification settings - Fork 3
/
bartDown.js
94 lines (79 loc) · 2.87 KB
/
bartDown.js
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
const urlParams = window.location.search
.substring(1)
.split('&')
.reduce((params, urlParam) => {
let param = urlParam.split('=');
params[param[0]] = param[1];
return params;
}, {});
// number of trains to display in either direction
const MAX_TRAINS_PER_DIRECTION = parseInt(urlParams.limit) || 3;
// station of origin abbreviation - https://api.bart.gov/docs/overview/abbrev.aspx
const STATION_CODE = urlParams.station || '19th';
// departure times below the cutoff will not be displayed
const MINUTE_CUTOFF = parseInt(urlParams.minute_cutoff) || 3;
// How often to poll for updates
const UPDATE_MS = 10000;
// See https://api.bart.gov/docs/etd/etd.aspx
const BASE_URL = 'https://api.bart.gov/api/etd.aspx';
// Scale content
const fontWidth = 100 / (MAX_TRAINS_PER_DIRECTION * 1.4);
document.body.style.fontSize = `${fontWidth}vw`;
// TODO:
// Allow user to pick station from a dropdown form
async function bartDown() {
const response = await fetch(
`${BASE_URL}?key=${BART_API_KEY}&cmd=etd&orig=${STATION_CODE}&json=y`,
);
const data = await response.json();
// Get an array of estimated departures from the response data
const estimatesForStation = data.root.station[0].etd.reduce((acc, etd) => {
return acc.concat(etd.estimate);
}, []);
const estimates = estimatesForStation
// Filter estimates that don't match criteria
.filter((estimate) => estimate.minutes >= MINUTE_CUTOFF)
// Transform 'Leaving' to 00 and ensure all times are double digits
// Note that we're mutating here :P
.map((estimate) => {
estimate.minutes = estimate.minutes === 'Leaving' ? '00' : estimate.minutes;
estimate.minutes = estimate.minutes.length < 2 ? '0' + estimate.minutes : estimate.minutes;
return estimate;
})
// Sort departures from soonest to latest
.sort((a, b) => a.minutes - b.minutes);
// Hide the error state
document.getElementById('disconnected').style.display = 'none';
// Remove existing estimates from DOM
Array.from(document.getElementsByClassName('estimate')).forEach((line) => {
line.remove();
});
let directionCount = {
north: 0,
south: 0,
};
// Add the new estimates to the DOM
estimates.forEach((estimate) => {
const direction = estimate.direction.toLowerCase();
if (directionCount[direction] < MAX_TRAINS_PER_DIRECTION) {
document
.getElementById(direction)
.insertAdjacentHTML(
'beforeEnd',
`<div class="estimate ${estimate.color.toLowerCase()}">${estimate.minutes}</div>`,
);
directionCount[direction]++;
}
});
}
// Display an icon on error
function displayErrorState(error) {
console.log(error);
document.getElementById('disconnected').style.display = 'flex';
}
// Kick it off!
bartDown().catch(displayErrorState);
// Set up recurring call
setInterval(() => {
bartDown().catch(displayErrorState);
}, UPDATE_MS);