From a5aa58d2ee78b92d45d3b57b6b19fb3fc09ad19a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matt=C3=A9o=20Delabre?= Date: Fri, 17 Jul 2020 19:17:06 +0200 Subject: [PATCH] Split map logic in front --- front/data.js | 32 +++++++++++ front/index.js | 133 +-------------------------------------------- front/map.js | 145 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 180 insertions(+), 130 deletions(-) create mode 100644 front/data.js create mode 100644 front/map.js diff --git a/front/data.js b/front/data.js new file mode 100644 index 0000000..fe61b39 --- /dev/null +++ b/front/data.js @@ -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(); diff --git a/front/index.js b/front/index.js index 4334e1b..4691e3e 100644 --- a/front/index.js +++ b/front/index.js @@ -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'); diff --git a/front/map.js b/front/map.js new file mode 100644 index 0000000..c6fa1a6 --- /dev/null +++ b/front/map.js @@ -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;