blob: 1e0e7f42d59697bf52f127fcb1d9ca998ec7a2a0 [file] [log] [blame]
avm9996399bb77c2020-01-27 03:15:08 +01001Number.prototype.mod = function(n) {
2 return ((this % n) + n) % n;
3}
4
5var scheduleController = {
6 maxSchedules: 6,
7 recommendedSchedulesPerLine: 2,
8 fetchInterval: 8*60*1000,
9 _times: [],
10 _queueTimes: [],
11 _lastTime: -1,
12 _lastDestinations: [],
13 _numRoutes: -1,
14 _stop: -1,
15 init: function() {
16 scheduleController.setStop();
17 scheduleController.removeDummy();
18 scheduleController.fetchTimes();
19 scheduleController.timer();
20 },
21 setStop: function() {
22 var params = new URLSearchParams(window.location.search);
23 scheduleController._stop = params.get("station");
24 },
25 isOldView: function() {
26 return document.body.classList.contains("view-old");
27 },
28 numSchedules: function() {
29 return Math.min(scheduleController.maxSchedules, 2 * scheduleController.recommendedSchedulesPerLine * scheduleController._numRoutes);
30 },
31 numSchedulesDetailed: function() {
32 return Math.ceil(scheduleController.numSchedules() / 2);
33 },
34 isDetailed: function(i) {
35 return (i < scheduleController.numSchedulesDetailed());
36 },
37 removeElement: function(el) {
38 el.parentNode.removeChild(el);
39 },
40 removeDummy: function() {
41 document.getElementById("trains").innerHTML = "";
42 },
43 timeSinceMidnight: function() {
44 var now = new Date();
45 var then = new Date(
46 now.getFullYear(),
47 now.getMonth(),
48 now.getDate(),
49 0,0,0);
50 return Math.floor((now.getTime() - then.getTime())/1000);
51 },
avm999630c4c7d02020-01-29 00:25:12 +010052 getTime: function() {
53 return Math.floor((new Date()).getTime()/1000);
54 },
55 timeSinceMidnightInverse: function(sec) {
56 var now = new Date();
57 var today = new Date(
58 now.getFullYear(),
59 now.getMonth(),
60 now.getDate(),
61 0,0,0);
62
63 return Math.floor(today.getTime()/1000) + sec;
64 },
avm9996399bb77c2020-01-27 03:15:08 +010065 prettyTime: function(seconds, detailed = true) {
66 if (detailed) return (Math.floor(seconds/60)).toString().padStart(2, '0')+":"+(seconds % 60).toString().padStart(2, '0');
67 return Math.floor(seconds/60)+"min";
68 },
69 addCurrentTime: function(data) {
70 var trains = document.getElementById("trains");
71
72 var train = document.createElement("div");
73 train.setAttribute("class", "train");
74
75 var logo = document.createElement("div");
76 logo.setAttribute("class", "logo");
77 logo.style.backgroundColor = "#"+data.color;
78 logo.style.color = "#"+data.textColor;
79 logo.style.fontSize = ("calc("+((scheduleController.isOldView() ? 20 : 18)/data.route.length)+"*var(--unit-size))");
80 logo.textContent = data.route;
81 train.appendChild(logo);
82
83 var destination = document.createElement("div");
84 destination.setAttribute("class", "destination");
85 destination.textContent = data.destination;
86 train.appendChild(destination);
87
88 var time = document.createElement("div");
89 time.setAttribute("class", "time");
90 train.appendChild(time);
91
92 trains.appendChild(train);
93
94 data._element = time;
avm999630c4c7d02020-01-29 00:25:12 +010095 data._removeAtTime = scheduleController.timeSinceMidnightInverse(data.departureTime);
avm9996399bb77c2020-01-27 03:15:08 +010096 scheduleController._times.push(data);
97 },
98 addTime: function(data) {
99 if (data.departureTime > scheduleController._lastTime) {
100 scheduleController._lastTime = data.departureTime;
101 scheduleController._lastDestinations = [data.destination];
102 } else if (data.departureTime == scheduleController.lastTime) {
103 var flag = false;
104 scheduleController._lastDestinations.forEach(dest => {
105 if (data.destination == dest) flag = true;
106 });
107
108 if (flag) {
109 return;
110 }
111
112 scheduleController._lastDestinations.push(dest);
113 } else return;
114
115 if (scheduleController._times.length < scheduleController.numSchedules()) {
116 scheduleController.addCurrentTime(data);
117 } else {
118 scheduleController._queueTimes.push(data);
119 }
120 },
121 fetchTimes: function() {
122 fetch("ajax/api.php?action=getTimes&stop="+scheduleController._stop).then(res => {
123 return res.json();
124 }).then(json => {
125 if (json.status != "ok") throw Error("Not ok");
126
127 scheduleController._numRoutes = json.data.numRoutes;
128
129 json.data.schedules.forEach(data => {
130 scheduleController.addTime(data);
131 });
132 });
133
134 setTimeout(scheduleController.fetchTimes, scheduleController.fetchInterval);
135 },
136 timer: function() {
137 var timeSinceMidnight = scheduleController.timeSinceMidnight();
avm999630c4c7d02020-01-29 00:25:12 +0100138 var time = scheduleController.getTime();
avm9996399bb77c2020-01-27 03:15:08 +0100139
140 var removed = 0;
141 for (var i = 0;; ++i) {
142 if (scheduleController._times[i - removed] === undefined) break;
143
avm999630c4c7d02020-01-29 00:25:12 +0100144 if (scheduleController._times[i - removed]._removeAtTime < time) {
avm9996399bb77c2020-01-27 03:15:08 +0100145 scheduleController.removeElement(scheduleController._times[i - removed]._element.parentNode);
146 scheduleController._times.shift();
147 ++removed;
avm9996399bb77c2020-01-27 03:15:08 +0100148 }
149 }
150
151 for (var i = 0; i < removed; ++i) {
152 if (scheduleController._queueTimes.length > 0) {
153 scheduleController.addCurrentTime(scheduleController._queueTimes.shift());
154 }
155 }
156
157 var i = 0;
158 scheduleController._times.forEach(time => {
159 var diff = (time.departureTime - timeSinceMidnight).mod(24*60*60);
160
161 time._element.textContent = scheduleController.prettyTime(diff, scheduleController.isDetailed(i));
162
163 ++i;
164 });
165
166 setTimeout(scheduleController.timer, (1000 - (new Date().getTime()) % 1000));
167 }
168};
169
170window.addEventListener("load", _ => {
171 scheduleController.init();
172});