2020-07-16 22:16:54 +00:00
|
|
|
|
const axios = require('axios');
|
2020-01-14 13:08:08 +00:00
|
|
|
|
const csv = require('csv-parse');
|
|
|
|
|
|
|
|
|
|
const network = require('./network');
|
2020-01-14 23:19:26 +00:00
|
|
|
|
const {TAM_REALTIME} = require('./endpoints');
|
2020-01-14 13:08:08 +00:00
|
|
|
|
|
|
|
|
|
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-01-14 13:08:08 +00:00
|
|
|
|
{
|
2020-07-16 22:16:54 +00:00
|
|
|
|
const parser = csv({
|
|
|
|
|
delimiter: ';',
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const courses = {};
|
|
|
|
|
stream.pipe(parser);
|
2020-01-14 13:08:08 +00:00
|
|
|
|
|
2020-07-16 22:16:54 +00:00
|
|
|
|
stream.on('readable', () =>
|
2020-01-14 13:08:08 +00:00
|
|
|
|
{
|
2020-07-16 22:16:54 +00:00
|
|
|
|
let row;
|
|
|
|
|
|
|
|
|
|
while (row = stream.read())
|
2020-01-14 13:08:08 +00:00
|
|
|
|
{
|
2020-07-16 22:16:54 +00:00
|
|
|
|
if (row.length === 0 || row[0] === 'course')
|
|
|
|
|
{
|
|
|
|
|
// Ignore les lignes invalides et l’en-tête
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2020-01-14 13:08:08 +00:00
|
|
|
|
|
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-01-14 13:08:08 +00:00
|
|
|
|
|
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-01-14 13:08:08 +00:00
|
|
|
|
}
|
2020-07-16 22:16:54 +00:00
|
|
|
|
});
|
2020-01-14 13:08:08 +00:00
|
|
|
|
|
2020-07-16 22:16:54 +00:00
|
|
|
|
stream.on('end', () => res(courses));
|
|
|
|
|
stream.on('error', err => rej(err));
|
2020-01-14 13:08:08 +00:00
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
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];
|
2020-01-14 23:19:26 +00:00
|
|
|
|
const arrivingStopIndex = route.stops.findIndex(
|
|
|
|
|
stop => stop.ref === arrivingStop
|
|
|
|
|
);
|
2020-01-14 13:08:08 +00:00
|
|
|
|
|
2020-01-14 23:19:26 +00:00
|
|
|
|
const leavingStop = arrivingStopIndex === 0
|
|
|
|
|
? route.stops[0]
|
|
|
|
|
: route.stops[arrivingStopIndex - 1];
|
2020-01-14 13:08:08 +00:00
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
})();
|