const tam = require("./sources/tam"); const network = require("./network.json"); // Time at which the course data needs to be updated next let nextUpdate = null; // Current information about courses let currentCourses = null; /** * Information about the course of a vehicle. * @typedef {Object} Course * @property {string} id Unique identifier for this course. * @property {string} line Transport line number. * @property {string} finalStop Final stop to which the course is headed. * @property {Object.} nextPassings Next stations to which * the vehicle will stop, associated to the passing timestamp. */ /** * 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. * @returns {Object.} Mapping from active course IDs to * information about each course. */ const fetch = async() => { if (nextUpdate === null || Date.now() >= nextUpdate) { const courses = {}; const passings = tam.fetchRealtime(); const timing = (await passings.next()).value; nextUpdate = timing.nextUpdate; // Aggregate passings relative to the same course for await (const passing of passings) { const { course: id, routeShortName: line, stopId, destArCode: finalStop } = passing; const arrivalTime = ( timing.lastUpdate + parseInt(passing.delaySec, 10) * 1000 ); if (!(id in courses)) { courses[id] = { id, line, finalStop, nextPassings: { [stopId]: arrivalTime } }; } else { courses[id].nextPassings[stopId] = arrivalTime; } } // Filter courses to only keep those referring to known data for (const courseId of Object.keys(courses)) { const course = courses[courseId]; if (!(course.line in network.lines)) { delete courses[courseId]; } else { for (const stopId of Object.keys(course.nextPassings)) { if (!(stopId in network.stops)) { delete courses[courseId]; break; } } } } currentCourses = courses; } return currentCourses; }; exports.fetch = fetch;