173 lines
5.0 KiB
JavaScript
173 lines
5.0 KiB
JavaScript
|
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));
|
|||
|
})();
|