Improved www.ttss.krakow.pl
Jacek Kowalski
2021-07-29 d80109132d362199e6d9e370d5f54bd0d6554126
commit | author | age
7e7221 1 'use strict';
f4a54f 2
4bfa36 3 var ttss_urls = {
JK 4     t: 'proxy_tram.php',
5     // t: 'http://www.ttss.krakow.pl/internetservice',
6     b: 'proxy_bus.php',
bb78f4 7     // b: 'http://ttss.mpk.krakow.pl/internetservice',
4bfa36 8 };
JK 9 var ttss_types = ['t', 'b'];
cbce8b 10
68aeb4 11 var special_directions = {
c57bed 12     'Zajezdnia Nowa Huta' : 'ZH',
JK 13     'Zajezdnia Podgórze' : 'ZP',
14     'Zjazd do zajezdni' : 'Z',
15     'Wyjazd na linię' : 'W',
16     'Przejazd techniczny' : 'PT',
68aeb4 17 };
JK 18
2b6454 19
JK 20 /********
21  * AJAX *
22  ********/
23
24 function Deferred(promise, request) {
e82356 25     this.promise = promise;
JK 26     this.request = request;
2b6454 27 }
e82356 28 Deferred.prototype = {
JK 29     promise: null,
30     request: null,
31     abort: function() {
32         this.request.abort.bind(this.request);
33         return new Deferred(this.promise, this.request);
34     },
35     done: function(func) {
2bc9da 36         return new Deferred(this.promise.then(func.bind(this)), this.request);
e82356 37     },
JK 38     fail: function(func) {
2bc9da 39         return new Deferred(this.promise.catch(func.bind(this)), this.request);
e82356 40     },
JK 41     always: function(func) {
2bc9da 42         return new Deferred(this.promise.finally(func.bind(this)), this.request);
e82356 43     },
JK 44 };
2b6454 45 Deferred.all = function(iterable) {
e82356 46     return new Deferred(
2b6454 47         Promise.all(
3c77d4 48             iterable.map(function(x) {
JK 49                 return x.promise;
50             })
2b6454 51         )
JK 52     );
53 };
54
55 var $ = {
56     timeout: 10000,
57     dataType: 'json',
2bc9da 58     get: function(url, headers) {
2b6454 59         var self = this;
JK 60         var request = new XMLHttpRequest();
61         var promise = new Promise(function(resolve, reject) {
58a4db 62             request.open('GET', url, true);
2bc9da 63             if(headers) {
JK 64                 Object.keys(headers).forEach(function (header) {
65                     request.setRequestHeader(header, headers[header]);
66                 });
67             }
2b6454 68             request.timeout = self.timeout;
JK 69             request.onreadystatechange = function() {
70                 if(this.readyState == 4) {
2bc9da 71                     if(this.status == 304) {
JK 72                         resolve();
73                     } else if(this.status == 200) {
74                         if(self.dataType === 'json') {
2b6454 75                             resolve(JSON.parse(this.responseText));
JK 76                         } else {
77                             resolve(this.responseText);
78                         }
79                     } else {
80                         reject(request);
81                     }
82                 }
83             };
84             request.send();
85         });
e82356 86         return new Deferred(promise, request);
2b6454 87     },
JK 88 };
89
90
91 /***********
92  * VERSION *
93  ***********/
94
572390 95 var script_version;
JK 96 var script_version_xhr;
97
98 function checkVersion() {
99     if(script_version_xhr) script_version_xhr.abort();
100     
101     script_version_xhr = $.get(
102         'version.php'
103     ).done(function(data) {
104         if(!script_version) {
105             script_version = data;
106             return;
107         }
108         
109         if(script_version != data) {
110             fail(lang.error_new_version);
111             location.reload(true);
112         }
113     });
114 }
115
116 function checkVersionInit() {
117     checkVersion();
118     setInterval(checkVersion, 3600000);
2bc9da 119 }
JK 120
121 /**********
122  * ARRAYS *
123  **********/
124
125 function deepMerge(a1, a2) {
126     if(typeof a1 !== 'object' || typeof a2 !== 'object') {
127         return a2;
128     }
129     Object.keys(a2).forEach(function (key) {
130         a1[key] = deepMerge(a1[key], a2[key]);
131         if(a1[key] === null) {
132             delete a1[key];
133         }
134     });
135     return a1;
7e7221 136 }
JK 137
138
139 /*******
140  * DOM *
141  *******/
142
143 function deleteChildren(element) {
144     while(element.lastChild) element.removeChild(element.lastChild);
145 }
146
147 function addElementWithText(parent, element, text) {
148     var elem = document.createElement(element);
149     elem.appendChild(document.createTextNode(text));
150     parent.appendChild(elem);
151     return elem;
152 }
153
154 function addCellWithText(parent, text) {
155     return addElementWithText(parent, 'td', text);
156 }
157
158 function addParaWithText(parent, text) {
159     return addElementWithText(parent, 'p', text);
160 }
161
162 function setText(element, text) {
163     deleteChildren(element);
164     element.appendChild(document.createTextNode(text));
572390 165 }
2bc9da 166
JK 167
168 /*****************
169  * VEHICLES INFO *
170  *****************/
171
172 function VehiclesInfo() {
173     this.data = {};
174     this.watchers = [];
175 }
176 VehiclesInfo.prototype = {
177     update: function () {
178         return $.get(
179             'https://mpk.jacekk.net/vehicles/'
180         ).done(function(data) {
181             this.data = data;
182             this.watchers.forEach(function(watcher) {
183                 watcher(this);
184             });
185         }.bind(this));
186     },
187     addWatcher: function(callback) {
188         this.watchers.push(callback);
189     },
190
191     get: function(vehicleId) {
192         if(!vehicleId) return false;
193         if(typeof this.data[vehicleId] === "undefined") {
194             return false;
195         }
196         return this.data[vehicleId];
197     },
198     getParsed: function (vehicleId) {
199         var vehicle = this.get(vehicleId);
200         if(!vehicle) return false;
201         return {
202             vehicleId: vehicleId,
203             prefix: vehicle['num'].substr(0, 2),
204             id: vehicle['num'].substr(2, 3),
205             num: vehicle['num'],
206             type: vehicle['type'],
207             low: vehicle['low']
208         };
209     },
210     depotIdToVehicleId: function(depotId, typeHelper) {
211         var prop;
212         depotId = depotId.toString();
213         if(typeHelper) {
214             for(prop in this.data) {
215                 if(prop.substr(0,1) === typeHelper && this.data[prop]['num'].substr(2) === depotId) {
216                     return prop;
217                 }
218             }
219         } else {
220             for(prop in this.data) {
221                 if(this.data[prop]['num'] === depotId) {
222                     return prop;
223                 }
224             }
225         }
226     },
227 };
228 var vehicles_info = new VehiclesInfo();
572390 229
2b6454 230
JK 231 /***********
232  * PARSING *
233  ***********/
234
ca42d3 235 function normalizeName(string) {
JK 236     return string.replace('.', '. ').replace('  ', ' ');
237 }
238
8b6250 239 function parseStatus(status) {
JK 240     switch(status.status) {
241         case 'STOPPING':
242         case 'PREDICTED':
243             if(status.actualRelativeTime <= 0)
244                 return lang.boarding_sign;
245             if(status.actualRelativeTime >= 60)
246                 return lang.time_minutes_prefix + Math.floor(status.actualRelativeTime / 60) + lang.time_minutes_suffix;
247             return lang.time_seconds_prefix + status.actualRelativeTime + lang.time_seconds_suffix;
248         case 'DEPARTED':
249             return lang.time_minutes_ago_prefix + Math.floor(-status.actualRelativeTime / 60) + lang.time_minutes_ago_suffix;
250         default:
251             return status.mixedTime;
252     }
253 }
254
255 function parseTime(date, time) {
38340e 256     var result = new Date(date.getTime());
8b6250 257     var time_split = time.split(':');
38340e 258     result.setHours(time_split[0], time_split[1], 0);
8b6250 259     
JK 260     if(result.getTime() - date.getTime() > 72000000) {
261         result.setTime(result.getTime() - 86400000);
262     }
263     
264     if(date.getTime() - result.getTime() > 72000000) {
265         result.setTime(result.getTime() + 86400000);
266     }
267     
268     return result;
269 }
270
271 function parseDelay(status) {
272     if(!status.actualTime) return lang.unknown_sign;
273     if(!status.plannedTime) return lang.unknown_sign;
274     
275     var now = new Date();
276     var actual = parseTime(now, status.actualTime);
277     var planned = parseTime(now, status.plannedTime);
278     
279     return lang.time_minutes_prefix + ((actual.getTime() - planned.getTime()) / 1000 / 60) + lang.time_minutes_suffix;
280 }
281
07c714 282 function displayVehicle(vehicleInfo) {
JK 283     if(!vehicleInfo) return document.createTextNode('');
284     
285     var span = document.createElement('span');
286     span.className = 'vehicleInfo';
287     
288     var floor_type = '';
2bc9da 289     if(vehicleInfo.low === 0) {
07c714 290         setText(span, lang.high_floor_sign);
JK 291         floor_type = lang.high_floor;
2bc9da 292     } else if(vehicleInfo.low === 1) {
07c714 293         setText(span, lang.partially_low_floor_sign);
JK 294         floor_type = lang.partially_low_floor;
2bc9da 295     } else if(vehicleInfo.low === 2) {
07c714 296         setText(span, lang.low_floor_sign);
JK 297         floor_type = lang.low_floor;
298     }
299     
300     span.title = lang.tram_type_pattern
301         .replace('$num', vehicleInfo.num)
302         .replace('$type', vehicleInfo.type)
303         .replace('$floor', floor_type);
304     
305     return span;
68aeb4 306 }