Mattéo Delabre
4 years ago
3 changed files with 180 additions and 130 deletions
@ -0,0 +1,32 @@ |
|||
const updateFromTam = async (courses) => |
|||
{ |
|||
const currentCourses = await getCurrentCourses(); |
|||
|
|||
for (let [id, course] of Object.entries(currentCourses)) |
|||
{ |
|||
if (!(id in courses)) |
|||
{ |
|||
course.arrivalTime = now() + course.eta; |
|||
console.log(`${displayNow(now())} - New course ${id} @ ${course.line} departing from stop ${course.stop} at ${displayNow(course.arrivalTime)}`); |
|||
courses[id] = course; |
|||
} |
|||
else |
|||
{ |
|||
course.arrivalTime = now() + course.eta; |
|||
console.log(`${displayNow(now())} - Course ${id} @ ${course.line} will arrive to stop ${course.stop} at ${displayNow(course.arrivalTime)} (previously to stop ${courses[id].stop} at ${displayNow(courses[id].arrivalTime)})`); |
|||
courses[id] = course; |
|||
} |
|||
} |
|||
}; |
|||
|
|||
const sleep = time => new Promise(res => setTimeout(res, time)); |
|||
const courses = {}; |
|||
|
|||
const loop = async (courses = {}) => |
|||
{ |
|||
await updateFromTam(courses); |
|||
await sleep(30000); |
|||
return loop(courses); |
|||
}; |
|||
|
|||
loop(); |
@ -1,131 +1,4 @@ |
|||
require('ol/ol.css'); |
|||
require('regenerator-runtime/runtime'); |
|||
|
|||
const {Map, View} = require('ol'); |
|||
|
|||
const TileLayer = require('ol/layer/Tile').default; |
|||
const XYZSource = require('ol/source/XYZ').default; |
|||
|
|||
const VectorLayer = require('ol/layer/Vector').default; |
|||
const VectorSource = require('ol/source/Vector').default; |
|||
|
|||
const Feature = require('ol/Feature').default; |
|||
const Point = require('ol/geom/Point').default; |
|||
const LineString = require('ol/geom/LineString').default; |
|||
|
|||
const proj = require('ol/proj'); |
|||
|
|||
const {Style, Fill, Stroke, Circle} = require('ol/style'); |
|||
const color = require('color'); |
|||
|
|||
// Map background
|
|||
const mapboxToken = 'pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJjazUxaWNsdXcwdWhjM2\ |
|||
9tc2xndXJoNGtxIn0.xELwMerqJLFimIqU6RxnZw'; |
|||
|
|||
const backgroundSource = new XYZSource({ |
|||
url: 'https://api.mapbox.com/' + [ |
|||
'styles', 'v1', 'mapbox', 'streets-v11', |
|||
'tiles', '512', '{z}', '{x}', '{y}', |
|||
].join('/') + `?access_token=${mapboxToken}`, |
|||
tileSize: [512, 512], |
|||
}); |
|||
|
|||
const backgroundLayer = new TileLayer({ |
|||
source: backgroundSource, |
|||
}); |
|||
|
|||
// Data overlay
|
|||
const dataSource = new VectorSource(); |
|||
|
|||
const SERVER = window.origin; |
|||
|
|||
fetch(SERVER + '/network').then(res => res.json()).then(network => |
|||
{ |
|||
const stopPoints = Object.entries(network.stops) |
|||
.map(([stopId, stop]) => |
|||
new Feature({ |
|||
type: 'stop', |
|||
color: network.lines[stop.lines[0]].color, |
|||
geometry: new Point(proj.fromLonLat([stop.lon, stop.lat])), |
|||
}) |
|||
); |
|||
|
|||
const segmentLines = Object.values(network.lines) |
|||
.flatMap(({color, routes}) => |
|||
routes.map(({segments}) => |
|||
new Feature({ |
|||
type: 'segment', |
|||
color, |
|||
geometry: new LineString(segments.flat().map( |
|||
({lat, lon}) => proj.fromLonLat([lon, lat]) |
|||
)), |
|||
}) |
|||
) |
|||
); |
|||
|
|||
dataSource.addFeatures( |
|||
stopPoints.concat(segmentLines) |
|||
); |
|||
}); |
|||
|
|||
const makeBorderColor = mainColor => |
|||
{ |
|||
const hsl = color(mainColor).hsl(); |
|||
hsl.color = Math.max(0, hsl.color[2] -= 20); |
|||
return hsl.hex(); |
|||
}; |
|||
|
|||
const dataLayer = new VectorLayer({ |
|||
source: dataSource, |
|||
style: feature => |
|||
{ |
|||
if (feature.get('type') === 'stop') |
|||
{ |
|||
return new Style({ |
|||
image: new Circle({ |
|||
fill: new Fill({ |
|||
color: feature.get('color'), |
|||
}), |
|||
stroke: new Stroke({ |
|||
color: makeBorderColor(feature.get('color')), |
|||
width: 2, |
|||
}), |
|||
radius: 6, |
|||
}), |
|||
}); |
|||
} |
|||
else if (feature.get('type') === 'segment') |
|||
{ |
|||
return [ |
|||
new Style({ |
|||
stroke: new Stroke({ |
|||
color: makeBorderColor(feature.get('color')), |
|||
width: 8, |
|||
}), |
|||
}), |
|||
new Style({ |
|||
stroke: new Stroke({ |
|||
color: feature.get('color'), |
|||
width: 6, |
|||
}), |
|||
}), |
|||
]; |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
// Setup map
|
|||
const map = new Map({ |
|||
target: 'map', |
|||
layers: [ |
|||
backgroundLayer, |
|||
dataLayer, |
|||
], |
|||
view: new View({ |
|||
center: proj.fromLonLat([3.88, 43.605]), |
|||
zoom: 13, |
|||
maxZoom: 22, |
|||
constrainResolution: true, |
|||
}), |
|||
}); |
|||
|
|||
module.exports = map; |
|||
const {createMap} = require('./map'); |
|||
createMap(/* map = */ 'map'); |
|||
|
@ -0,0 +1,145 @@ |
|||
require('ol/ol.css'); |
|||
|
|||
const {Map, View} = require('ol'); |
|||
|
|||
const TileLayer = require('ol/layer/Tile').default; |
|||
const XYZSource = require('ol/source/XYZ').default; |
|||
|
|||
const VectorLayer = require('ol/layer/Vector').default; |
|||
const VectorSource = require('ol/source/Vector').default; |
|||
|
|||
const Feature = require('ol/Feature').default; |
|||
const Point = require('ol/geom/Point').default; |
|||
const LineString = require('ol/geom/LineString').default; |
|||
|
|||
const proj = require('ol/proj'); |
|||
|
|||
const {Style, Fill, Stroke, Circle} = require('ol/style'); |
|||
const color = require('color'); |
|||
|
|||
const mapboxToken = 'pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJjazUxaWNsdXcwdWhjM2\ |
|||
9tc2xndXJoNGtxIn0.xELwMerqJLFimIqU6RxnZw'; |
|||
|
|||
const server = window.origin; |
|||
|
|||
const fetchDataSources = async () => |
|||
{ |
|||
const dataSource = new VectorSource(); |
|||
|
|||
const res = await fetch(`${server}/network`); |
|||
const network = await res.json(); |
|||
|
|||
const stopPoints = Object.entries(network.stops) |
|||
.map(([stopId, stop]) => |
|||
new Feature({ |
|||
type: 'stop', |
|||
color: network.lines[stop.lines[0]].color, |
|||
geometry: new Point(proj.fromLonLat([stop.lon, stop.lat])), |
|||
}) |
|||
); |
|||
|
|||
dataSource.addFeatures(stopPoints); |
|||
|
|||
const segmentLines = Object.values(network.lines) |
|||
.flatMap(({color, routes}) => |
|||
routes.map(({segments}) => |
|||
new Feature({ |
|||
type: 'segment', |
|||
color, |
|||
geometry: new LineString(segments.flat().map( |
|||
({lat, lon}) => proj.fromLonLat([lon, lat]) |
|||
)), |
|||
}) |
|||
) |
|||
); |
|||
|
|||
dataSource.addFeatures(segmentLines); |
|||
|
|||
return dataSource; |
|||
}; |
|||
|
|||
const createMap = async (target) => |
|||
{ |
|||
// Map background
|
|||
const backgroundSource = new XYZSource({ |
|||
url: 'https://api.mapbox.com/' + [ |
|||
'styles', 'v1', 'mapbox', 'streets-v11', |
|||
'tiles', '512', '{z}', '{x}', '{y}', |
|||
].join('/') + `?access_token=${mapboxToken}`, |
|||
tileSize: [512, 512], |
|||
}); |
|||
|
|||
const backgroundLayer = new TileLayer({ |
|||
source: backgroundSource, |
|||
}); |
|||
|
|||
// Data overlay
|
|||
const dataSource = await fetchDataSources(); |
|||
|
|||
const makeBorderColor = mainColor => |
|||
{ |
|||
const hsl = color(mainColor).hsl(); |
|||
hsl.color = Math.max(0, hsl.color[2] -= 20); |
|||
return hsl.hex(); |
|||
}; |
|||
|
|||
const dataLayer = new VectorLayer({ |
|||
source: dataSource, |
|||
updateWhileInteracting: true, |
|||
updateWhileAnimating: true, |
|||
style: feature => |
|||
{ |
|||
if (feature.get('type') === 'stop') |
|||
{ |
|||
return new Style({ |
|||
image: new Circle({ |
|||
fill: new Fill({ |
|||
color: feature.get('color'), |
|||
}), |
|||
stroke: new Stroke({ |
|||
color: makeBorderColor(feature.get('color')), |
|||
width: 2, |
|||
}), |
|||
radius: 6, |
|||
}), |
|||
}); |
|||
} |
|||
else if (feature.get('type') === 'segment') |
|||
{ |
|||
return [ |
|||
new Style({ |
|||
stroke: new Stroke({ |
|||
color: makeBorderColor(feature.get('color')), |
|||
width: 8, |
|||
}), |
|||
}), |
|||
new Style({ |
|||
stroke: new Stroke({ |
|||
color: feature.get('color'), |
|||
width: 6, |
|||
}), |
|||
}), |
|||
]; |
|||
} |
|||
}, |
|||
}); |
|||
|
|||
// Setup map
|
|||
const map = new Map({ |
|||
target, |
|||
layers: [ |
|||
backgroundLayer, |
|||
dataLayer, |
|||
], |
|||
view: new View({ |
|||
center: proj.fromLonLat([3.88, 43.605]), |
|||
zoom: 13, |
|||
maxZoom: 22, |
|||
constrainResolution: true, |
|||
}), |
|||
}); |
|||
|
|||
return map; |
|||
}; |
|||
|
|||
exports.createMap = createMap; |
Loading…
Reference in new issue