blob: 5951682eed49349b7ec7fc6a0812ec7b5e0fa2f7 [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 },
52 prettyTime: function(seconds, detailed = true) {
53 if (detailed) return (Math.floor(seconds/60)).toString().padStart(2, '0')+":"+(seconds % 60).toString().padStart(2, '0');
54 return Math.floor(seconds/60)+"min";
55 },
56 addCurrentTime: function(data) {
57 var trains = document.getElementById("trains");
58
59 var train = document.createElement("div");
60 train.setAttribute("class", "train");
61
62 var logo = document.createElement("div");
63 logo.setAttribute("class", "logo");
64 logo.style.backgroundColor = "#"+data.color;
65 logo.style.color = "#"+data.textColor;
66 logo.style.fontSize = ("calc("+((scheduleController.isOldView() ? 20 : 18)/data.route.length)+"*var(--unit-size))");
67 logo.textContent = data.route;
68 train.appendChild(logo);
69
70 var destination = document.createElement("div");
71 destination.setAttribute("class", "destination");
72 destination.textContent = data.destination;
73 train.appendChild(destination);
74
75 var time = document.createElement("div");
76 time.setAttribute("class", "time");
77 train.appendChild(time);
78
79 trains.appendChild(train);
80
81 data._element = time;
82 data._markedToRemove = false;
83 scheduleController._times.push(data);
84 },
85 addTime: function(data) {
86 if (data.departureTime > scheduleController._lastTime) {
87 scheduleController._lastTime = data.departureTime;
88 scheduleController._lastDestinations = [data.destination];
89 } else if (data.departureTime == scheduleController.lastTime) {
90 var flag = false;
91 scheduleController._lastDestinations.forEach(dest => {
92 if (data.destination == dest) flag = true;
93 });
94
95 if (flag) {
96 return;
97 }
98
99 scheduleController._lastDestinations.push(dest);
100 } else return;
101
102 if (scheduleController._times.length < scheduleController.numSchedules()) {
103 scheduleController.addCurrentTime(data);
104 } else {
105 scheduleController._queueTimes.push(data);
106 }
107 },
108 fetchTimes: function() {
109 fetch("ajax/api.php?action=getTimes&stop="+scheduleController._stop).then(res => {
110 return res.json();
111 }).then(json => {
112 if (json.status != "ok") throw Error("Not ok");
113
114 scheduleController._numRoutes = json.data.numRoutes;
115
116 json.data.schedules.forEach(data => {
117 scheduleController.addTime(data);
118 });
119 });
120
121 setTimeout(scheduleController.fetchTimes, scheduleController.fetchInterval);
122 },
123 timer: function() {
124 var timeSinceMidnight = scheduleController.timeSinceMidnight();
125
126 var removed = 0;
127 for (var i = 0;; ++i) {
128 if (scheduleController._times[i - removed] === undefined) break;
129
130 if (scheduleController._times[i - removed]._markedToRemove) {
131 scheduleController.removeElement(scheduleController._times[i - removed]._element.parentNode);
132 scheduleController._times.shift();
133 ++removed;
134 }
135
136 if (scheduleController._times[i - removed].departureTime - timeSinceMidnight == 0) {
137 scheduleController._times[i - removed]._markedToRemove = true;
138 }
139 }
140
141 for (var i = 0; i < removed; ++i) {
142 if (scheduleController._queueTimes.length > 0) {
143 scheduleController.addCurrentTime(scheduleController._queueTimes.shift());
144 }
145 }
146
147 var i = 0;
148 scheduleController._times.forEach(time => {
149 var diff = (time.departureTime - timeSinceMidnight).mod(24*60*60);
150
151 time._element.textContent = scheduleController.prettyTime(diff, scheduleController.isDetailed(i));
152
153 ++i;
154 });
155
156 setTimeout(scheduleController.timer, (1000 - (new Date().getTime()) % 1000));
157 }
158};
159
160window.addEventListener("load", _ => {
161 scheduleController.init();
162});