| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  | const tam = require('./sources/tam'); | 
					
						
							|  |  |  | const util = require('../util'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Comparison function between two stop passings. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @param passing1 First stop passing. | 
					
						
							|  |  |  |  * @param passing2 Second stop passing. | 
					
						
							|  |  |  |  * @return Negative value if passing1 is sooner than passing2, positive | 
					
						
							|  |  |  |  * otherwise, zero if they occur at the same time. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | const passingCompare = ({arrivalTime: time1}, {arrivalTime: time2}) => ( | 
					
						
							|  |  |  |     time1 - time2 | 
					
						
							|  |  |  | ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Time at which the course data needs to be updated next
 | 
					
						
							| 
									
										
										
										
											2020-07-18 17:00:46 +00:00
										 |  |  | let nextUpdate = null; | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Current information about courses
 | 
					
						
							| 
									
										
										
										
											2020-07-18 17:00:46 +00:00
										 |  |  | let currentCourses = null; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2020-07-18 17:00:46 +00:00
										 |  |  |  * Fetch real-time information about active courses in the TaM network. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * New data will only be fetched from the TaM server once every minute, | 
					
						
							|  |  |  |  * otherwise pulling from the in-memory cache. | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-07-18 17:00:46 +00:00
										 |  |  |  * The following information is provided for each active course: | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2020-07-18 17:00:46 +00:00
										 |  |  |  * - `id`: Unique identifier for the course. | 
					
						
							|  |  |  |  * - `line`: Line number. | 
					
						
							|  |  |  |  * - `finalStop`: The final stop to which the course is headed. | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  |  * - `nextPassings`: Next passings of the vehicle, sorted by increasing | 
					
						
							|  |  |  |  *   arrival time, containing both the stop identifier (`stopId`) and the | 
					
						
							|  |  |  |  *   expected arrival timestamp (`arrivalTime`). | 
					
						
							| 
									
										
										
										
											2020-07-18 17:00:46 +00:00
										 |  |  |  * | 
					
						
							|  |  |  |  * @return Mapping from active course IDs to information about each course. | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | const getCourses = () => new Promise((res, rej) => | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |     if (nextUpdate !== null && Date.now() < nextUpdate) | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         res(currentCourses); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |     const courses = {}; | 
					
						
							|  |  |  |     let lastUpdate = null; | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |     tam.fetchRealtime((err, entry) => | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         if (err) | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |             rej(err); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         if (!util.isObject(entry)) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  |             // End of courses information stream. Sort next stops by increasing
 | 
					
						
							|  |  |  |             // arrival time in each course then save result in memory cache
 | 
					
						
							|  |  |  |             for (let course of Object.values(courses)) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 course.nextPassings.sort(passingCompare); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |             currentCourses = courses; | 
					
						
							|  |  |  |             res(currentCourses); | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         if ('lastUpdate' in entry) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  |             // Metadata header
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |             lastUpdate = entry.lastUpdate; | 
					
						
							|  |  |  |             nextUpdate = entry.nextUpdate; | 
					
						
							|  |  |  |             return; | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         const { | 
					
						
							|  |  |  |             course: id, | 
					
						
							|  |  |  |             routeShortName: line, | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  |             stopId, | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |             destArCode: finalStop, | 
					
						
							|  |  |  |         } = entry; | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         const arrivalTime = lastUpdate + parseInt(entry.delaySec, 10) * 1000; | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         if (!(id in courses)) | 
					
						
							|  |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  |             courses[id] = { | 
					
						
							|  |  |  |                 id, line, finalStop, | 
					
						
							|  |  |  |                 nextPassings: [{stopId, arrivalTime}], | 
					
						
							|  |  |  |             }; | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  |         else | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         { | 
					
						
							| 
									
										
										
										
											2020-07-18 22:10:08 +00:00
										 |  |  |             courses[id].nextPassings.push({stopId, arrivalTime}); | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  |         } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2020-01-14 13:08:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-17 14:40:09 +00:00
										 |  |  | exports.getCourses = getCourses; |