tracktracker/back/data/realtime.js

178 lines
5.3 KiB
JavaScript
Raw Normal View History

2020-07-16 22:16:54 +00:00
const axios = require('axios');
const csv = require('csv-parse');
const network = require('./network');
const {TAM_REALTIME} = require('./endpoints');
const sortByFirstKey = (a, b) => a[0] - b[0];
const fetchRealtime = () => new Promise((res, rej) =>
{
2020-07-16 22:16:54 +00:00
const stream = axios.get(TAM_REALTIME, {
responseType: 'stream'
}).then(stream =>
{
2020-07-16 22:16:54 +00:00
const parser = csv({
delimiter: ';',
});
const courses = {};
stream.pipe(parser);
2020-07-16 22:16:54 +00:00
stream.on('readable', () =>
{
2020-07-16 22:16:54 +00:00
let row;
while (row = stream.read())
{
2020-07-16 22:16:54 +00:00
if (row.length === 0 || row[0] === 'course')
{
// Ignore les lignes invalides et len-tête
continue;
}
2020-07-16 22:16:54 +00:00
const course = row[0];
const stopRef = row[2];
const lineRef = row[4];
const eta = row[9];
const destinationRef = row[10];
2020-07-16 22:16:54 +00:00
if (!(course in courses))
{
courses[course] = {
lineRef,
destinationRef,
stops: [],
};
}
courses[course].stops.push([parseInt(eta, 10), stopRef]);
courses[course].stops.sort(sortByFirstKey);
}
2020-07-16 22:16:54 +00:00
});
2020-07-16 22:16:54 +00:00
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 leavingStop = arrivingStopIndex === 0
? route.stops[0]
: route.stops[arrivingStopIndex - 1];
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));
})();