const request = require('request'); const csv = require('csv-parse'); const network = require('./network'); const TAM_REALTIME = 'http://data.montpellier3m.fr/node/10732/download'; const sortByFirstKey = (a, b) => a[0] - b[0]; const fetchRealtime = () => new Promise((res, rej) => { const parser = csv({ delimiter: ';', }); const stream = request(TAM_REALTIME).pipe(parser); const courses = {}; stream.on('readable', () => { let row; while (row = stream.read()) { if (row.length === 0 || row[0] === 'course') { // Ignore les lignes invalides et l’en-tête continue; } const course = row[0]; const stopRef = row[2]; const lineRef = row[4]; const eta = row[9]; const destinationRef = row[10]; if (!(course in courses)) { courses[course] = { lineRef, destinationRef, stops: [], }; } courses[course].stops.push([parseInt(eta, 10), stopRef]); courses[course].stops.sort(sortByFirstKey); } }); stream.on('end', () => res(courses)); stream.on('error', err => rej(err)); }); const updateVehicles = async (lines, vehicles) => { const courses = await fetchRealtime(); const currentTime = Math.floor(Date.now() / 1000); for (let [courseRef, course] of Object.entries(courses)) { if (course.lineRef in lines) { if (!(courseRef in vehicles)) { // New vehicle: identify which route it pertains to const line = lines[course.lineRef]; let routeIndex = null; for (let [index, route] of Object.entries(line.routes)) { const destRef = route.stops[route.stops.length - 1].ref; if (destRef === course.destinationRef) { routeIndex = index; } } if (routeIndex !== null) { const route = line.routes[routeIndex]; // Convert ETAs to absolute times const nextStops = course.stops.map(([eta, ref]) => [ eta + currentTime, ref ]); // Convert stop refs to indices const stopIndices = course.stops.map(([eta, ref]) => [ eta, ]); // Find the preceding stop from which the vehicle is coming const arrivingStop = stopIndices[0][1]; const arrivingStopIndex = route.stops.findIndex(stop => stop.ref === arrivingStop); const [eta, nextStop] = stopIndices[0]; if (nextStop === 0) { // Vehicle at starting point vehicles[courseRef] = { lineRef: course.lineRef, stopRef stopIndex: 0, nextStops: stopIndices, distance: 0, speed: 0, }; } else { // Vehicle in transit between two stops vehicles[courseRef] = { lineRef: course.lineRef, routeIndex, stopIndex: nextStop - 1, nextStops: stopIndices, distance: 0, speed: route.distances[nextStop - 1] / eta, }; } } } else { // Existing vehicle: update information const vehicle = vehicles[courseRef]; const line = lines[vehicle.lineRef]; const route = line.routes[vehicle.routeIndex]; // Convert stop refs to indices const stopIndices = course.stops.map(([eta, ref]) => [ eta, route.stops.findIndex(stop => stop.ref === ref), ]); console.log(stopIndices); console.log(vehicle); console.log(course); console.log('---'); } } } }; const sleep = time => new Promise(res => setTimeout(res, time)); const updateLoop = async (lines, vehicles = {}) => { await updateVehicles(lines, vehicles); await sleep(30000); return updateLoop(lines, vehicles); }; (async () => { const lines = {'1': await network.fetchLineData('1')}; updateLoop(lines); // console.log(require('util').inspect(vehicles, true, 10)); })();