Migrate to ES6 modules and update dependencies
This commit is contained in:
parent
888845f9d7
commit
9d163f257d
File diff suppressed because it is too large
Load Diff
44
package.json
44
package.json
|
@ -1,38 +1,34 @@
|
||||||
{
|
{
|
||||||
"name": "tamview",
|
"name": "tamview",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "",
|
"type": "module",
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"back": "node src/back",
|
"back": "node src/back",
|
||||||
"front:dev": "parcel serve src/front/index.html",
|
"front:dev": "vite",
|
||||||
"front:prod": "npx parcel build src/front/index.html --no-source-maps --no-autoinstall",
|
"front:prod": "vite build",
|
||||||
"lint": "eslint ."
|
"lint": "eslint ."
|
||||||
},
|
},
|
||||||
"engines": {
|
|
||||||
"node": ">=10.0.0"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "Mattéo Delabre",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@turf/along": "^6.0.1",
|
"@turf/along": "^6.3.0",
|
||||||
"@turf/helpers": "^6.1.4",
|
"@turf/helpers": "^6.3.0",
|
||||||
"@turf/length": "^6.0.2",
|
"@turf/length": "^6.3.0",
|
||||||
"@turf/projection": "^6.0.1",
|
"@turf/projection": "^6.3.0",
|
||||||
"@turf/turf": "^5.1.6",
|
"@turf/turf": "^6.3.0",
|
||||||
"axios": "^0.19.2",
|
"axios": "^0.21.1",
|
||||||
"color": "^3.1.2",
|
"color": "^3.1.3",
|
||||||
"csv-parse": "^4.8.3",
|
"csv-parse": "^4.15.4",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"ol": "^6.1.1",
|
"ol": "^6.5.0",
|
||||||
"unzip-stream": "^0.3.0"
|
"unzip-stream": "^0.3.1",
|
||||||
|
"vue": "^3.0.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^6.8.0",
|
"@vitejs/plugin-vue": "^1.2.2",
|
||||||
"eslint-config-eslint": "^6.0.0",
|
"@vue/compiler-sfc": "^3.0.5",
|
||||||
"eslint-plugin-jsdoc": "^30.0.3",
|
"eslint": "^7.26.0",
|
||||||
|
"eslint-config-eslint": "^7.0.0",
|
||||||
|
"eslint-plugin-jsdoc": "^34.0.1",
|
||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"parcel-bundler": "^1.12.4"
|
"vite": "^2.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
const courses = require('../src/tam/courses');
|
import * as courses from '../src/tam/courses.js';
|
||||||
const network = require('../src/tam/network.json');
|
import {displayTime} from '../src/util.js';
|
||||||
const {displayTime} = require('../src/util');
|
import process from 'process';
|
||||||
const process = require('process');
|
import path from 'path';
|
||||||
const path = require('path');
|
import { readFile } from 'fs/promises';
|
||||||
|
|
||||||
|
const network = JSON.parse(await readFile(
|
||||||
|
new URL('../src/tam/network.json', import.meta.url)
|
||||||
|
));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert stop ID to human-readable stop name.
|
* Convert stop ID to human-readable stop name.
|
|
@ -1,29 +0,0 @@
|
||||||
#!/usr/bin/env node
|
|
||||||
|
|
||||||
const network = require('../src/tam/network');
|
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
(async () =>
|
|
||||||
{
|
|
||||||
const lines = ['1', '2', '3', '4'];
|
|
||||||
const data = await network.fetch(lines);
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(__dirname, '../src/tam/network.json'),
|
|
||||||
JSON.stringify(
|
|
||||||
data,
|
|
||||||
(_, value) =>
|
|
||||||
{
|
|
||||||
if (value instanceof Set)
|
|
||||||
{
|
|
||||||
// Convert sets to arrays for JSON representation
|
|
||||||
return Array.from(value.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
4
|
|
||||||
)
|
|
||||||
);
|
|
||||||
})();
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import * as network from '../src/tam/network.js';
|
||||||
|
import fs from 'fs/promises';
|
||||||
|
|
||||||
|
const lines = ['1', '2', '3', '4'];
|
||||||
|
const data = await network.fetch(lines);
|
||||||
|
|
||||||
|
await fs.writeFile(
|
||||||
|
new URL("../src/tam/network.json", import.meta.url),
|
||||||
|
JSON.stringify(
|
||||||
|
data,
|
||||||
|
(_, value) =>
|
||||||
|
{
|
||||||
|
if (value instanceof Set)
|
||||||
|
{
|
||||||
|
// Convert sets to arrays for JSON representation
|
||||||
|
return Array.from(value.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
},
|
||||||
|
4
|
||||||
|
)
|
||||||
|
);
|
|
@ -1,10 +1,10 @@
|
||||||
const express = require("express");
|
import express from "express";
|
||||||
const courses = require("../tam/courses");
|
import * as courses from "../tam/courses.js";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const port = 4321;
|
const port = 4321;
|
||||||
|
|
||||||
app.get("/courses", async(req, res) => {
|
app.get("/courses", async (_, res) => {
|
||||||
res.header("Access-Control-Allow-Origin", "*");
|
res.header("Access-Control-Allow-Origin", "*");
|
||||||
return res.json(await courses.fetch("realtime"));
|
return res.json(await courses.fetch("realtime"));
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<template>
|
||||||
|
<div>Hello {{ name }}!</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
name: "Vue",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
|
@ -18,8 +18,8 @@
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
|
|
||||||
#informations {
|
#panel {
|
||||||
flex: 0 0 600px;
|
flex: 0 0 400px;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
@ -31,8 +31,8 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="informations"></div>
|
<aside id="panel"></aside>
|
||||||
<div id="map"></div>
|
<div id="map"></div>
|
||||||
<script src="index.js"></script>
|
<script type="module" src="index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
// eslint-disable-next-line node/no-extraneous-require
|
import network from "../tam/network.json";
|
||||||
require("regenerator-runtime/runtime");
|
import * as simulation from "../tam/simulation";
|
||||||
|
import * as map from "./map/index";
|
||||||
const network = require("../tam/network.json");
|
|
||||||
const simulation = require("../tam/simulation");
|
|
||||||
const map = require("./map/index.js");
|
|
||||||
|
|
||||||
// Run courses simulation
|
// Run courses simulation
|
||||||
const coursesSimulation = simulation.start();
|
const coursesSimulation = simulation.start();
|
||||||
const informations = document.querySelector("#informations");
|
|
||||||
let courseId = null;
|
let courseId = null;
|
||||||
|
|
||||||
|
// Create display panel
|
||||||
|
const panel = document.querySelector("#panel");
|
||||||
|
|
||||||
const displayTime = date => [
|
const displayTime = date => [
|
||||||
date.getHours(),
|
date.getHours(),
|
||||||
date.getMinutes(),
|
date.getMinutes(),
|
||||||
|
@ -80,7 +79,7 @@ setInterval(() => {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
informations.innerHTML = html;
|
panel.innerHTML = html;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
// Create the network and courses map
|
// Create the network and courses map
|
||||||
|
|
|
@ -1,34 +1,24 @@
|
||||||
const colorModule = require("color");
|
import color from "color";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn the main color of a line into a color suitable for using as a border.
|
* Turn the main color of a line into a color suitable for using as a border.
|
||||||
* @param {string} mainColor Original color.
|
* @param {string} mainColor Original color.
|
||||||
* @returns {string} Hexadecimal representation of the border color.
|
* @returns {string} Hexadecimal representation of the border color.
|
||||||
*/
|
*/
|
||||||
const makeBorderColor = mainColor => {
|
export const makeBorderColor = mainColor => {
|
||||||
const hsl = colorModule(mainColor).hsl();
|
return color(mainColor).darken(0.2).hex();
|
||||||
|
|
||||||
hsl.color = Math.max(0, hsl.color[2] -= 20);
|
|
||||||
return hsl.hex();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.makeBorderColor = makeBorderColor;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Turn the main color of a line into a color suitable for using as a border.
|
* Turn the main color of a line into a color suitable for using as a border.
|
||||||
* @param {string} mainColor Original color.
|
* @param {string} mainColor Original color.
|
||||||
* @returns {string} Hexadecimal representation of the border color.
|
* @returns {string} Hexadecimal representation of the border color.
|
||||||
*/
|
*/
|
||||||
const makeCourseColor = mainColor => {
|
export const makeCourseColor = mainColor => {
|
||||||
const hsl = colorModule(mainColor).hsl();
|
return color(mainColor).lighten(0.2).hex();
|
||||||
|
|
||||||
hsl.color = Math.max(0, hsl.color[2] += 10);
|
|
||||||
return hsl.hex();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.makeCourseColor = makeCourseColor;
|
export const sizes = {
|
||||||
|
|
||||||
const sizes = {
|
|
||||||
segmentOuter: 8,
|
segmentOuter: 8,
|
||||||
segmentInner: 6,
|
segmentInner: 6,
|
||||||
stopRadius: 6,
|
stopRadius: 6,
|
||||||
|
@ -38,5 +28,3 @@ const sizes = {
|
||||||
courseBorder: 10,
|
courseBorder: 10,
|
||||||
courseInnerBorder: 7
|
courseInnerBorder: 7
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.sizes = sizes;
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
require("ol/ol.css");
|
import "ol/ol.css";
|
||||||
|
|
||||||
const { Map, View } = require("ol");
|
import { Map, View } from "ol";
|
||||||
const { getVectorContext } = require("ol/render");
|
import { getVectorContext } from "ol/render";
|
||||||
const Point = require("ol/geom/Point").default;
|
import Point from "ol/geom/Point";
|
||||||
const proj = require("ol/proj");
|
import * as proj from "ol/proj";
|
||||||
const { Style, Icon } = require("ol/style");
|
import { Style, Icon } from "ol/style";
|
||||||
const tilesLayers = require("./tiles");
|
import * as tilesLayers from "./tiles";
|
||||||
const networkLayers = require("./network");
|
import * as networkLayers from "./network";
|
||||||
const { sizes, makeBorderColor, makeCourseColor } = require("./common");
|
import { sizes, makeBorderColor, makeCourseColor } from "./common";
|
||||||
const network = require("../../tam/network.json");
|
import network from "../../tam/network.json";
|
||||||
|
|
||||||
const courseStyles = {};
|
const courseStyles = {};
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ const getCourseStyle = lineColor => {
|
||||||
return courseStyles[lineColor];
|
return courseStyles[lineColor];
|
||||||
};
|
};
|
||||||
|
|
||||||
const create = (target, coursesSimulation, onClick) => {
|
export const create = (target, coursesSimulation, onClick) => {
|
||||||
const view = new View({
|
const view = new View({
|
||||||
center: proj.fromLonLat([3.88, 43.605]),
|
center: proj.fromLonLat([3.88, 43.605]),
|
||||||
zoom: 14,
|
zoom: 14,
|
||||||
|
@ -138,5 +138,3 @@ const create = (target, coursesSimulation, onClick) => {
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.create = create;
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
const network = require("../../tam/network.json");
|
import network from "../../tam/network.json";
|
||||||
const { makeBorderColor, sizes } = require("./common");
|
import { makeBorderColor, sizes } from "./common";
|
||||||
|
|
||||||
const GeoJSON = require("ol/format/GeoJSON").default;
|
import GeoJSON from "ol/format/GeoJSON";
|
||||||
const VectorLayer = require("ol/layer/Vector").default;
|
import VectorLayer from "ol/layer/Vector";
|
||||||
const VectorSource = require("ol/source/Vector").default;
|
import VectorSource from "ol/source/Vector";
|
||||||
|
|
||||||
const { Style, Fill, Stroke, Circle } = require("ol/style");
|
import { Style, Fill, Stroke, Circle } from "ol/style";
|
||||||
|
|
||||||
const geojsonReader = new GeoJSON({ featureProjection: "EPSG:3857" });
|
const geojsonReader = new GeoJSON({ featureProjection: "EPSG:3857" });
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ const lineFeaturesOrder = (feature1, feature2) => {
|
||||||
* Create the list of layers for displaying the transit network.
|
* Create the list of layers for displaying the transit network.
|
||||||
* @returns {Array.<Layer>} List of map layers.
|
* @returns {Array.<Layer>} List of map layers.
|
||||||
*/
|
*/
|
||||||
const getLayers = () => {
|
export const getLayers = () => {
|
||||||
const segmentsSource = new VectorSource();
|
const segmentsSource = new VectorSource();
|
||||||
const stopsSource = new VectorSource();
|
const stopsSource = new VectorSource();
|
||||||
|
|
||||||
|
@ -128,5 +128,3 @@ const getLayers = () => {
|
||||||
|
|
||||||
return [segmentsBorderLayer, segmentsInnerLayer, stopsLayer];
|
return [segmentsBorderLayer, segmentsInnerLayer, stopsLayer];
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.getLayers = getLayers;
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const TileLayer = require("ol/layer/Tile").default;
|
import TileLayer from "ol/layer/Tile";
|
||||||
const XYZSource = require("ol/source/XYZ").default;
|
import XYZSource from "ol/source/XYZ";
|
||||||
|
|
||||||
const mapboxToken = "pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJja2NxaTUyMmUwcmFhMn\
|
const mapboxToken = "pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJja2NxaTUyMmUwcmFhMn\
|
||||||
h0NmFsdzQ3emxqIn0.cyxF0h36emIMTk3cc4VqUw";
|
h0NmFsdzQ3emxqIn0.cyxF0h36emIMTk3cc4VqUw";
|
||||||
|
@ -8,7 +8,7 @@ h0NmFsdzQ3emxqIn0.cyxF0h36emIMTk3cc4VqUw";
|
||||||
* Create the list of layers for displaying the background map.
|
* Create the list of layers for displaying the background map.
|
||||||
* @returns {Array.<Layer>} List of map layers.
|
* @returns {Array.<Layer>} List of map layers.
|
||||||
*/
|
*/
|
||||||
const getLayers = () => {
|
export const getLayers = () => {
|
||||||
const backgroundSource = new XYZSource({
|
const backgroundSource = new XYZSource({
|
||||||
url: `https://api.mapbox.com/${[
|
url: `https://api.mapbox.com/${[
|
||||||
"styles", "v1", "mapbox", "streets-v11",
|
"styles", "v1", "mapbox", "streets-v11",
|
||||||
|
@ -21,5 +21,3 @@ const getLayers = () => {
|
||||||
source: backgroundSource
|
source: backgroundSource
|
||||||
})];
|
})];
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.getLayers = getLayers;
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import path from 'path';
|
||||||
|
|
||||||
|
const root = path.join(
|
||||||
|
path.dirname(new URL(import.meta.url).pathname),
|
||||||
|
"..", ".."
|
||||||
|
);
|
||||||
|
|
||||||
|
export default {
|
||||||
|
server: {
|
||||||
|
fsServe: {
|
||||||
|
root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
|
@ -5,8 +5,12 @@
|
||||||
* from the official endpoints.
|
* from the official endpoints.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const tam = require("./sources/tam");
|
import * as tam from "./sources/tam.js";
|
||||||
const network = require("./network.json");
|
import { readFile } from 'fs/promises';
|
||||||
|
|
||||||
|
const network = JSON.parse(await readFile(
|
||||||
|
new URL('./network.json', import.meta.url)
|
||||||
|
));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Information about the course of a vehicle.
|
* Information about the course of a vehicle.
|
||||||
|
@ -40,12 +44,13 @@ const parseTime = (time, reference) =>
|
||||||
/**
|
/**
|
||||||
* Fetch information about courses in the TaM network.
|
* Fetch information about courses in the TaM network.
|
||||||
*
|
*
|
||||||
|
* @async
|
||||||
* @param {string} kind Pass 'realtime' to get real-time information,
|
* @param {string} kind Pass 'realtime' to get real-time information,
|
||||||
* or 'theoretical' to get planned courses for the day.
|
* or 'theoretical' to get planned courses for the day.
|
||||||
* @returns {Object.<string,Course>} Mapping from active course IDs to
|
* @returns {Object.<string,Course>} Mapping from active course IDs to
|
||||||
* information about each course.
|
* information about each course.
|
||||||
*/
|
*/
|
||||||
const fetch = async (kind = 'realtime') => {
|
export const fetch = async (kind = 'realtime') => {
|
||||||
const courses = {};
|
const courses = {};
|
||||||
const passings = (
|
const passings = (
|
||||||
kind === 'realtime'
|
kind === 'realtime'
|
||||||
|
@ -128,5 +133,3 @@ const fetch = async (kind = 'realtime') => {
|
||||||
|
|
||||||
return courses;
|
return courses;
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.fetch = fetch;
|
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
* the `script/update-network` script.
|
* the `script/update-network` script.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const turfHelpers = require("@turf/helpers");
|
import * as turfHelpers from "@turf/helpers";
|
||||||
const turfLength = require("@turf/length").default;
|
import turfLength from "@turf/length";
|
||||||
const util = require("../util");
|
import * as util from "../util.js";
|
||||||
const osm = require("./sources/osm");
|
import * as osm from "./sources/osm.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch stops and lines of the network.
|
* Fetch stops and lines of the network.
|
||||||
|
@ -22,7 +22,7 @@ const osm = require("./sources/osm");
|
||||||
* @returns {{stops: Object, lines: Object, segments: Object}} Set of stops,
|
* @returns {{stops: Object, lines: Object, segments: Object}} Set of stops,
|
||||||
* segments and lines.
|
* segments and lines.
|
||||||
*/
|
*/
|
||||||
const fetch = async lineRefs => {
|
export const fetch = async lineRefs => {
|
||||||
// Retrieve routes, ways and stops from OpenStreetMap
|
// Retrieve routes, ways and stops from OpenStreetMap
|
||||||
const rawData = await osm.runQuery(`[out:json];
|
const rawData = await osm.runQuery(`[out:json];
|
||||||
|
|
||||||
|
@ -250,5 +250,3 @@ different sequence of nodes in two or more lines.`);
|
||||||
|
|
||||||
return { stops, lines, segments };
|
return { stops, lines, segments };
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.fetch = fetch;
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const axios = require("axios");
|
import axios from "axios";
|
||||||
const turfAlong = require("@turf/along").default;
|
import turfAlong from "@turf/along";
|
||||||
const turfProjection = require("@turf/projection");
|
import * as turfProjection from "@turf/projection";
|
||||||
const network = require("./network.json");
|
import network from "./network.json";
|
||||||
|
|
||||||
const server = "http://localhost:4321";
|
const server = "http://localhost:4321";
|
||||||
|
|
||||||
|
@ -307,7 +307,7 @@ const tick = (courses, time) => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const start = () => {
|
export const start = () => {
|
||||||
const courses = {};
|
const courses = {};
|
||||||
let lastFrame = null;
|
let lastFrame = null;
|
||||||
let lastUpdate = null;
|
let lastUpdate = null;
|
||||||
|
@ -328,5 +328,3 @@ const start = () => {
|
||||||
|
|
||||||
return { courses, update };
|
return { courses, update };
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.start = start;
|
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* Interface with the OpenStreetMap collaborative mapping database.
|
* Interface with the OpenStreetMap collaborative mapping database.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const axios = require("axios");
|
import axios from "axios";
|
||||||
const { isObject } = require("../../util");
|
import { isObject } from "../../util.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Submit a query to an Overpass endpoint.
|
* Submit a query to an Overpass endpoint.
|
||||||
|
@ -19,7 +19,7 @@ const { isObject } = require("../../util");
|
||||||
* is requested in the query, the result will automatically be parsed into
|
* is requested in the query, the result will automatically be parsed into
|
||||||
* a JS object.
|
* a JS object.
|
||||||
*/
|
*/
|
||||||
const runQuery = (
|
export const runQuery = (
|
||||||
query,
|
query,
|
||||||
endpoint = "https://lz4.overpass-api.de/api/interpreter"
|
endpoint = "https://lz4.overpass-api.de/api/interpreter"
|
||||||
) => (
|
) => (
|
||||||
|
@ -27,16 +27,12 @@ const runQuery = (
|
||||||
.then(res => res.data)
|
.then(res => res.data)
|
||||||
);
|
);
|
||||||
|
|
||||||
exports.runQuery = runQuery;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a link to view a node.
|
* Create a link to view a node.
|
||||||
* @param {string|number} id Identifier for the node to view.
|
* @param {string|number} id Identifier for the node to view.
|
||||||
* @returns {string} Link to view this node on the OSM website.
|
* @returns {string} Link to view this node on the OSM website.
|
||||||
*/
|
*/
|
||||||
const viewNode = id => `https://www.osm.org/node/${id}`;
|
export const viewNode = id => `https://www.osm.org/node/${id}`;
|
||||||
|
|
||||||
exports.viewNode = viewNode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if an OSM way is one-way or not.
|
* Determine if an OSM way is one-way or not.
|
||||||
|
@ -45,15 +41,13 @@ exports.viewNode = viewNode;
|
||||||
* @param {Object} obj OSM way object.
|
* @param {Object} obj OSM way object.
|
||||||
* @returns {boolean} Whether the way is one-way.
|
* @returns {boolean} Whether the way is one-way.
|
||||||
*/
|
*/
|
||||||
const isOneWay = obj => (
|
export const isOneWay = obj => (
|
||||||
obj.type === "way" &&
|
obj.type === "way" &&
|
||||||
isObject(obj.tags) &&
|
isObject(obj.tags) &&
|
||||||
(obj.tags.oneway === "yes" || obj.tags.junction === "roundabout" ||
|
(obj.tags.oneway === "yes" || obj.tags.junction === "roundabout" ||
|
||||||
obj.tags.highway === "motorway")
|
obj.tags.highway === "motorway")
|
||||||
);
|
);
|
||||||
|
|
||||||
exports.isOneWay = isOneWay;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if an OSM object is a public transport line (route master).
|
* Determine if an OSM object is a public transport line (route master).
|
||||||
*
|
*
|
||||||
|
@ -62,10 +56,8 @@ exports.isOneWay = isOneWay;
|
||||||
* @param {Object} obj OSM relation object.
|
* @param {Object} obj OSM relation object.
|
||||||
* @returns {boolean} Whether the relation is a public transport line.
|
* @returns {boolean} Whether the relation is a public transport line.
|
||||||
*/
|
*/
|
||||||
const isTransportLine = obj => (
|
export const isTransportLine = obj => (
|
||||||
obj.type === "relation" &&
|
obj.type === "relation" &&
|
||||||
isObject(obj.tags) &&
|
isObject(obj.tags) &&
|
||||||
obj.tags.type === "route_master"
|
obj.tags.type === "route_master"
|
||||||
);
|
);
|
||||||
|
|
||||||
exports.isTransportLine = isTransportLine;
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
const csv = require("csv-parse");
|
import csv from "csv-parse";
|
||||||
const axios = require("axios");
|
import axios from "axios";
|
||||||
const path = require("path");
|
import path from "path";
|
||||||
const fs = require("fs").promises;
|
import fs from "fs/promises";
|
||||||
const { snakeToCamelCase, unzipFile } = require("../../util");
|
import { snakeToCamelCase, unzipFile } from "../../util.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data available for each passing of a vehicle at a station.
|
* Data available for each passing of a vehicle at a station.
|
||||||
|
@ -70,14 +70,14 @@ const makeCached = (func, cachePath) => {
|
||||||
yield passing;
|
yield passing;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFile(cachePath, JSON.stringify(newCache));
|
await fs.writeFile(cachePath, JSON.stringify(newCache));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const cacheDir = path.join(__dirname, "..", "..", "..", "cache");
|
const cacheDir = new URL("../../../cache/", import.meta.url);
|
||||||
|
|
||||||
const realtimeEndpoint = "http://data.montpellier3m.fr/node/10732/download";
|
const realtimeEndpoint = "http://data.montpellier3m.fr/node/10732/download";
|
||||||
const realtimeCachePath = path.join(cacheDir, "realtime.json");
|
const realtimeCachePath = new URL("./realtime.json", cacheDir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch real time passings of vehicles across the network.
|
* Fetch real time passings of vehicles across the network.
|
||||||
|
@ -86,7 +86,7 @@ const realtimeCachePath = path.join(cacheDir, "realtime.json");
|
||||||
* update of this information. Next values are informations about each vehicle
|
* update of this information. Next values are informations about each vehicle
|
||||||
* passing.
|
* passing.
|
||||||
*/
|
*/
|
||||||
const fetchRealtime = async function *() {
|
const fetchRealtimeRaw = async function *() {
|
||||||
const res = await axios.get(realtimeEndpoint, {
|
const res = await axios.get(realtimeEndpoint, {
|
||||||
responseType: "stream"
|
responseType: "stream"
|
||||||
});
|
});
|
||||||
|
@ -106,10 +106,10 @@ const fetchRealtime = async function *() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.fetchRealtime = makeCached(fetchRealtime, realtimeCachePath);
|
export const fetchRealtime = makeCached(fetchRealtimeRaw, realtimeCachePath);
|
||||||
|
|
||||||
const theoreticalEndpoint = "http://data.montpellier3m.fr/node/10731/download";
|
const theoreticalEndpoint = "http://data.montpellier3m.fr/node/10731/download";
|
||||||
const theoreticalCachePath = path.join(cacheDir, "theoretical.json");
|
const theoreticalCachePath = new URL("./theoretical.json", cacheDir);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch theoretical passings for the current day across the network.
|
* Fetch theoretical passings for the current day across the network.
|
||||||
|
@ -118,7 +118,7 @@ const theoreticalCachePath = path.join(cacheDir, "theoretical.json");
|
||||||
* update of this information. Next values are informations about each vehicle
|
* update of this information. Next values are informations about each vehicle
|
||||||
* passing.
|
* passing.
|
||||||
*/
|
*/
|
||||||
const fetchTheoretical = async function *() {
|
const fetchTheoreticalRaw = async function *() {
|
||||||
const res = await axios.get(theoreticalEndpoint, {
|
const res = await axios.get(theoreticalEndpoint, {
|
||||||
responseType: "stream"
|
responseType: "stream"
|
||||||
});
|
});
|
||||||
|
@ -154,4 +154,5 @@ const fetchTheoretical = async function *() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.fetchTheoretical = makeCached(fetchTheoretical, theoreticalCachePath);
|
export const fetchTheoretical = makeCached(
|
||||||
|
fetchTheoreticalRaw, theoreticalCachePath);
|
||||||
|
|
27
src/util.js
27
src/util.js
|
@ -1,23 +1,19 @@
|
||||||
const unzip = require("unzip-stream");
|
import unzip from "unzip-stream";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a snake-cased string to a camel-cased one.
|
* Convert a snake-cased string to a camel-cased one.
|
||||||
* @param {string} str Original string.
|
* @param {string} str Original string.
|
||||||
* @returns {string} Transformed string.
|
* @returns {string} Transformed string.
|
||||||
*/
|
*/
|
||||||
const snakeToCamelCase = str => str.replace(/([-_][a-z])/gu, group =>
|
export const snakeToCamelCase = str => str.replace(/([-_][a-z])/gu, group =>
|
||||||
group.toUpperCase().replace("-", "").replace("_", ""));
|
group.toUpperCase().replace("-", "").replace("_", ""));
|
||||||
|
|
||||||
exports.snakeToCamelCase = snakeToCamelCase;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a value is a JS object.
|
* Check if a value is a JS object.
|
||||||
* @param {*} value Value to check.
|
* @param {*} value Value to check.
|
||||||
* @returns {boolean} Whether `value` is a JS object.
|
* @returns {boolean} Whether `value` is a JS object.
|
||||||
*/
|
*/
|
||||||
const isObject = value => value !== null && typeof value === "object";
|
export const isObject = value => value !== null && typeof value === "object";
|
||||||
|
|
||||||
exports.isObject = isObject;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if two arrays are equal in a shallow manner.
|
* Check if two arrays are equal in a shallow manner.
|
||||||
|
@ -25,20 +21,18 @@ exports.isObject = isObject;
|
||||||
* @param {Array} array2 Second array.
|
* @param {Array} array2 Second array.
|
||||||
* @returns {boolean} Whether the two arrays are equal.
|
* @returns {boolean} Whether the two arrays are equal.
|
||||||
*/
|
*/
|
||||||
const arraysEqual = (array1, array2) => (
|
export const arraysEqual = (array1, array2) => (
|
||||||
array1.length === array2.length &&
|
array1.length === array2.length &&
|
||||||
array1.every((elt1, index) => elt1 === array2[index])
|
array1.every((elt1, index) => elt1 === array2[index])
|
||||||
);
|
);
|
||||||
|
|
||||||
exports.arraysEqual = arraysEqual;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a file in a zipped stream and unzip it.
|
* Find a file in a zipped stream and unzip it.
|
||||||
* @param {stream.Readable} data Input zipped stream.
|
* @param {stream.Readable} data Input zipped stream.
|
||||||
* @param {string} fileName Name of the file to find.
|
* @param {string} fileName Name of the file to find.
|
||||||
* @returns {Promise.<stream.Readable>} Stream of the unzipped file.
|
* @returns {Promise.<stream.Readable>} Stream of the unzipped file.
|
||||||
*/
|
*/
|
||||||
const unzipFile = (data, fileName) => new Promise((res, rej) => {
|
export const unzipFile = (data, fileName) => new Promise((res, rej) => {
|
||||||
// eslint-disable-next-line new-cap
|
// eslint-disable-next-line new-cap
|
||||||
const stream = data.pipe(unzip.Parse());
|
const stream = data.pipe(unzip.Parse());
|
||||||
let found = false;
|
let found = false;
|
||||||
|
@ -62,12 +56,13 @@ const unzipFile = (data, fileName) => new Promise((res, rej) => {
|
||||||
stream.on("error", err => rej(err));
|
stream.on("error", err => rej(err));
|
||||||
});
|
});
|
||||||
|
|
||||||
exports.unzipFile = unzipFile;
|
/**
|
||||||
|
* Display the time component of a date.
|
||||||
const displayTime = date => [
|
* @param {Date} date Date to display.
|
||||||
|
* @returns {string} Formatted date as 'HH:MM:SS'.
|
||||||
|
*/
|
||||||
|
export const displayTime = date => [
|
||||||
date.getHours(),
|
date.getHours(),
|
||||||
date.getMinutes(),
|
date.getMinutes(),
|
||||||
date.getSeconds()
|
date.getSeconds()
|
||||||
].map(number => number.toString().padStart(2, "0")).join(":");
|
].map(number => number.toString().padStart(2, "0")).join(":");
|
||||||
|
|
||||||
exports.displayTime = displayTime;
|
|
||||||
|
|
Loading…
Reference in New Issue