add test and split codebase
This commit is contained in:
parent
0614feaa03
commit
be0ea5263c
11
babel.config.cjs
Normal file
11
babel.config.cjs
Normal file
@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
targets:
|
||||
{ node: 'current' }
|
||||
}
|
||||
]
|
||||
],
|
||||
}
|
40
js/color-utils.js
Normal file
40
js/color-utils.js
Normal file
@ -0,0 +1,40 @@
|
||||
import utils from "./utils.js"
|
||||
|
||||
|
||||
let unknown_color = '#c0b1b1' // color for unknown power output of the station
|
||||
const colors = [
|
||||
'#36423d',
|
||||
'#4e8a8d',
|
||||
'#2999b3',
|
||||
'#1782dd',
|
||||
'#2900ff',
|
||||
'#8000ff',
|
||||
]
|
||||
|
||||
const error_color = '#ff1414'
|
||||
// 2024-12-16: au delà d'une valeur de 400kW on peut dire qu'il existe une erreur de saisie, nous n'avons pas de chargeur de 1800kW en production.
|
||||
const max_out_legit_power = 400
|
||||
|
||||
const colorUtils = {
|
||||
/**
|
||||
* trouver une couleur correspondant
|
||||
*/
|
||||
getColor : (feature) =>{
|
||||
|
||||
let outputPower = utils.guessOutputPowerFromFeature(feature)
|
||||
feature.properties.tags.has_output_of_irve_specified = outputPower
|
||||
if (outputPower) {
|
||||
|
||||
if(outputPower> max_out_legit_power){
|
||||
return error_color;
|
||||
}
|
||||
let index = Math.min(Math.floor(outputPower / 10), colors.length - 1)
|
||||
|
||||
return colors[index]
|
||||
}
|
||||
// autrement, sans puissance max trouvée, on met la couleur des indéfinis
|
||||
return unknown_color
|
||||
},
|
||||
}
|
||||
|
||||
export default colorUtils
|
7
js/config.js
Normal file
7
js/config.js
Normal file
@ -0,0 +1,7 @@
|
||||
const config = {
|
||||
osmMention:'© <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
|
||||
showHighPower : true,
|
||||
overrideQuery : true,
|
||||
initialZoom : 12
|
||||
}
|
||||
export default config
|
136
js/main.js
136
js/main.js
@ -4,12 +4,12 @@
|
||||
* lister les bornes trouvées dans la page
|
||||
* @type {boolean}
|
||||
*/
|
||||
import config from './config.js'
|
||||
import utils from './utils.js'
|
||||
import colorUtils from "./color-utils.js"
|
||||
|
||||
let showHighPower = true
|
||||
const overrideQuery = true
|
||||
const initialZoom = 12
|
||||
const osmMention = '© <a href="https://openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
let unknown_color = '#c0b1b1' // color for unknown power output of the station
|
||||
console.log('config', config)
|
||||
let geojsondata;
|
||||
|
||||
// serveurs de tuiles: https://wiki.openstreetmap.org/wiki/Tile_servers
|
||||
// https://stamen-tiles.a.ssl.fastly.net/toner/{z}/{x}/{y}.png
|
||||
@ -21,28 +21,7 @@ const tileServer_stamen = 'https://a.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png
|
||||
|
||||
// Créer la carte centrée sur Rouen
|
||||
// Liste des 20 villes les plus peuplées de France avec leurs coordonnées géographiques
|
||||
let cities = [
|
||||
{ name: 'Paris', coords: [48.8566, 2.3522] },
|
||||
{ name: 'Marseille', coords: [43.2965, 5.3698] },
|
||||
{ name: 'Lyon', coords: [45.7640, 4.8357] },
|
||||
{ name: 'Toulouse', coords: [43.6042, 1.4437] },
|
||||
{ name: 'Nice', coords: [43.7101, 7.2620] },
|
||||
{ name: 'Nantes', coords: [47.2184, -1.5536] },
|
||||
{ name: 'Strasbourg', coords: [48.5831, 7.7521] },
|
||||
{ name: 'Montpellier', coords: [43.6167, 3.8742] },
|
||||
{ name: 'Bordeaux', coords: [44.8378, -0.5792] },
|
||||
{ name: 'Lille', coords: [50.6293, 3.1466] },
|
||||
{ name: 'Rennes', coords: [48.1120, -1.6823] },
|
||||
{ name: 'Toulon', coords: [43.1230, 5.9291] },
|
||||
{ name: 'Le Havre', coords: [49.4943, 0.1079] },
|
||||
{ name: 'Saint-Etienne', coords: [45.4380, 4.3841] },
|
||||
{ name: 'Grenoble', coords: [45.1667, 5.7295] },
|
||||
{ name: 'Rouen', coords: [49.4431, 1.0820] },
|
||||
{ name: 'Dijon', coords: [47.3221, 5.0446] },
|
||||
{ name: 'Angers', coords: [47.4786, -0.5551] },
|
||||
{ name: 'Nîmes', coords: [43.8366, 4.3623] },
|
||||
{ name: 'Reims', coords: [49.2500, 4.0333] }
|
||||
]
|
||||
|
||||
|
||||
|
||||
// Initialisation de la carte avec la vue centrée sur la ville choisie
|
||||
@ -52,9 +31,9 @@ let map = L.map('map');
|
||||
function setRandomView(){
|
||||
console.log('set random view')
|
||||
// Choix au hasard d'une ville parmi la liste
|
||||
let randomCity = cities[Math.floor(Math.random() * cities.length)]
|
||||
let randomCity = utils.cities[Math.floor(Math.random() * utils.cities.length)]
|
||||
console.log('randomCity', randomCity)
|
||||
map = map.setView(randomCity.coords, initialZoom)
|
||||
map = map.setView(randomCity.coords, config.initialZoom)
|
||||
}
|
||||
function setCoordinatesOfLeafletMapFromQueryParameters() {
|
||||
// Récupère les paramètres de l'URL
|
||||
@ -85,32 +64,30 @@ function updateURLWithMapCoordinatesAndZoom() {
|
||||
|
||||
// Construit l'URL avec les paramètres de coordonnées et de zoom
|
||||
const url = `#coords=1&lat=${center.lat}&lng=${center.lng}&zoom=${zoom}`;
|
||||
console.log('updateURLWithMapCoordinatesAndZoom url', url)
|
||||
// console.log('updateURLWithMapCoordinatesAndZoom url', url)
|
||||
// Met à jour l'URL de la page
|
||||
history.replaceState(null, null, url);
|
||||
}
|
||||
|
||||
|
||||
|
||||
var osm = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: osmMention+'© <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors'
|
||||
attribution: config.osmMention+'© <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors'
|
||||
})
|
||||
|
||||
var cycle = L.tileLayer('https://{s}.tile.opencyclemap.org/{z}/{x}/{y}.png', {
|
||||
attribution: osmMention+'© <a href="https://www.opencyclemap.org/">OpenCycleMap</a> contributors'
|
||||
attribution: config.osmMention+'© <a href="https://www.opencyclemap.org/">OpenCycleMap</a> contributors'
|
||||
})
|
||||
|
||||
var transport = L.tileLayer('https://{s}.tile.thunderforest.com/transport/{z}/{x}/{y}.png', {
|
||||
attribution: osmMention
|
||||
attribution: config.osmMention
|
||||
})
|
||||
|
||||
let tileGrey =
|
||||
L.tileLayer(tileServer, {
|
||||
attribution: osmMention
|
||||
attribution: config.osmMention
|
||||
})
|
||||
let stamen =
|
||||
L.tileLayer(tileServer_stamen, {
|
||||
attribution: osmMention
|
||||
attribution: config.osmMention
|
||||
})
|
||||
var baseLayers = {
|
||||
'Grey': tileGrey,
|
||||
@ -132,7 +109,7 @@ function buildOverpassApiUrl (map, overpassQuery) {
|
||||
let bounds = map.getBounds().getSouth() + ',' + map.getBounds().getWest() + ',' + map.getBounds().getNorth() + ',' + map.getBounds().getEast()
|
||||
let resultUrl, query = ''
|
||||
|
||||
if (overrideQuery) {
|
||||
if (config.overrideQuery) {
|
||||
query = `?data=[out:json][timeout:15];(
|
||||
node[amenity=charging_station](${bounds});
|
||||
);out body geom;`
|
||||
@ -195,86 +172,11 @@ function supprimerMarqueurs (map) {
|
||||
})
|
||||
}
|
||||
|
||||
const colors = [
|
||||
'#36423d',
|
||||
'#4e8a8d',
|
||||
'#2999b3',
|
||||
'#1782dd',
|
||||
'#2900ff',
|
||||
'#8000ff',
|
||||
]
|
||||
|
||||
function guessOutputPowerFromFeature (feature) {
|
||||
let outputPower = 0
|
||||
let power = 0
|
||||
if (feature.properties && feature.properties.tags) {
|
||||
/**
|
||||
* fouiller dans les tags les valeurs explicites de puissance déclarée.
|
||||
* Deviner aussi les puissances non déclarées:
|
||||
* - type 2 présent, max 43kW
|
||||
* - type Chademo présent, max 63kW
|
||||
* https://forum.openstreetmap.fr/t/bornes-de-recharges-et-puissance-chargeurs-quel-est-votre-avis/27828
|
||||
*
|
||||
*/
|
||||
|
||||
let found_type_2 = false
|
||||
let found_type_chademo = false
|
||||
for (var tag in feature.properties.tags) {
|
||||
if (tag.indexOf('type2') !== -1) {
|
||||
// console.log('tag type2', tag)
|
||||
found_type_2 = true
|
||||
power = 43
|
||||
}
|
||||
if (tag.indexOf('chademo') !== -1) {
|
||||
found_type_chademo = true
|
||||
// console.log('tag chademo', tag)
|
||||
power = 63
|
||||
}
|
||||
let value = feature.properties.tags[tag]
|
||||
if (value && tag.toLowerCase().indexOf('output') !== -1) {
|
||||
// console.log('tag contient output', tag, value)
|
||||
value = '' + value
|
||||
if (value.replace) {
|
||||
value = value.replace(' ')
|
||||
value = value.replace('kW', '')
|
||||
}
|
||||
let power = parseInt(value)
|
||||
// deviner les types de prises présents
|
||||
|
||||
// if (power) {
|
||||
// console.log('power', power)
|
||||
// console.log('outputPower', outputPower)
|
||||
// }
|
||||
if (power > outputPower) {
|
||||
outputPower = power
|
||||
// console.log('power', power)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
feature.properties.outputPower = outputPower
|
||||
return outputPower
|
||||
}
|
||||
|
||||
// 2024-12-16: au delà d'une valeur de 400kW on peut dire qu'il existe une erreur de saisie, nous n'avons pas de chargeur de 1800kW en production.
|
||||
const max_out_legit_power = 400
|
||||
const error_color = 'red'
|
||||
function getColor (feature) {
|
||||
|
||||
let outputPower = guessOutputPowerFromFeature(feature)
|
||||
feature.properties.tags.has_output_of_irve_specified = outputPower
|
||||
if (outputPower) {
|
||||
|
||||
if(outputPower> max_out_legit_power){
|
||||
return error_color;
|
||||
}
|
||||
let index = Math.min(Math.floor(outputPower / 10), colors.length - 1)
|
||||
|
||||
return colors[index]
|
||||
}
|
||||
// autrement, sans puissance max trouvée, on met la couleur des indéfinis
|
||||
return unknown_color
|
||||
}
|
||||
|
||||
let coef_reduction_bars = 0.8
|
||||
|
||||
@ -320,7 +222,7 @@ function displayStatsFromGeoJson (resultAsGeojson) {
|
||||
found_type2 = true
|
||||
}
|
||||
})
|
||||
let outputPower = guessOutputPowerFromFeature(feature)
|
||||
let outputPower = utils.guessOutputPowerFromFeature(feature)
|
||||
if (found_type2_combo) {
|
||||
count_found_type2combo++
|
||||
}
|
||||
@ -383,7 +285,7 @@ ${count_estimated_type2combo} (${calculerPourcentage(count_estimated_type2combo,
|
||||
$('#bars_power').html(bar_powers)
|
||||
}
|
||||
|
||||
let geojsondata
|
||||
|
||||
|
||||
function bindEventsOnJosmRemote () {
|
||||
let josm_remote_buttons = $(`.josm`)
|
||||
@ -467,8 +369,8 @@ function displayPointsFromApi (points) {
|
||||
popupContent += '</div>'
|
||||
layer.bindPopup(popupContent)
|
||||
|
||||
let outPowerGuessed = guessOutputPowerFromFeature(feature)
|
||||
let color = getColor(feature)
|
||||
let outPowerGuessed = utils.guessOutputPowerFromFeature(feature)
|
||||
let color = colorUtils.getColor(feature)
|
||||
let displayOutPowerGuessed = '? kW'
|
||||
if (outPowerGuessed) {
|
||||
displayOutPowerGuessed = outPowerGuessed + ' kW max'
|
||||
|
85
js/utils.js
Normal file
85
js/utils.js
Normal file
@ -0,0 +1,85 @@
|
||||
|
||||
|
||||
|
||||
const utils = {
|
||||
/**
|
||||
* fouiller dans les tags les valeurs explicites de puissance déclarée.
|
||||
* Deviner aussi les puissances non déclarées:
|
||||
* - type 2 présent, max 43kW
|
||||
* - type Chademo présent, max 63kW
|
||||
* https://forum.openstreetmap.fr/t/bornes-de-recharges-et-puissance-chargeurs-quel-est-votre-avis/27828
|
||||
*
|
||||
* @param feature
|
||||
* @returns {number}
|
||||
*/
|
||||
guessOutputPowerFromFeature: (feature) => {
|
||||
let outputPower = 0
|
||||
let power = 0
|
||||
if (feature.properties && feature.properties.tags) {
|
||||
|
||||
let found_type_2 = false
|
||||
let found_type_chademo = false
|
||||
for (var tag in feature.properties.tags) {
|
||||
if (tag.indexOf('type2') !== -1) {
|
||||
// console.log('tag type2', tag)
|
||||
found_type_2 = true
|
||||
power = 43
|
||||
}
|
||||
if (tag.indexOf('chademo') !== -1) {
|
||||
found_type_chademo = true
|
||||
// console.log('tag chademo', tag)
|
||||
power = 63
|
||||
}
|
||||
let value = feature.properties.tags[tag]
|
||||
if (value && tag.toLowerCase().indexOf('output') !== -1) {
|
||||
// console.log('tag contient output', tag, value)
|
||||
value = '' + value
|
||||
if (value.replace) {
|
||||
value = value.replace(' ')
|
||||
value = value.replace('kW', '')
|
||||
}
|
||||
let power = parseInt(value)
|
||||
// deviner les types de prises présents
|
||||
|
||||
// if (power) {
|
||||
// console.log('power', power)
|
||||
// console.log('outputPower', outputPower)
|
||||
// }
|
||||
if (power > outputPower) {
|
||||
outputPower = power
|
||||
// console.log('power', power)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
feature.properties.outputPower = outputPower
|
||||
return outputPower
|
||||
},
|
||||
|
||||
/**
|
||||
* villes les plus peuplées de France
|
||||
*/
|
||||
cities: [
|
||||
{ name: 'Paris', coords: [48.8566, 2.3522] },
|
||||
{ name: 'Marseille', coords: [43.2965, 5.3698] },
|
||||
{ name: 'Lyon', coords: [45.7640, 4.8357] },
|
||||
{ name: 'Toulouse', coords: [43.6042, 1.4437] },
|
||||
{ name: 'Nice', coords: [43.7101, 7.2620] },
|
||||
{ name: 'Nantes', coords: [47.2184, -1.5536] },
|
||||
{ name: 'Strasbourg', coords: [48.5831, 7.7521] },
|
||||
{ name: 'Montpellier', coords: [43.6167, 3.8742] },
|
||||
{ name: 'Bordeaux', coords: [44.8378, -0.5792] },
|
||||
{ name: 'Lille', coords: [50.6293, 3.1466] },
|
||||
{ name: 'Rennes', coords: [48.1120, -1.6823] },
|
||||
{ name: 'Toulon', coords: [43.1230, 5.9291] },
|
||||
{ name: 'Le Havre', coords: [49.4943, 0.1079] },
|
||||
{ name: 'Saint-Etienne', coords: [45.4380, 4.3841] },
|
||||
{ name: 'Grenoble', coords: [45.1667, 5.7295] },
|
||||
{ name: 'Rouen', coords: [49.4431, 1.0820] },
|
||||
{ name: 'Dijon', coords: [47.3221, 5.0446] },
|
||||
{ name: 'Angers', coords: [47.4786, -0.5551] },
|
||||
{ name: 'Nîmes', coords: [43.8366, 4.3623] },
|
||||
{ name: 'Reims', coords: [49.2500, 4.0333] }
|
||||
]
|
||||
}
|
||||
export default utils
|
6687
package-lock.json
generated
Normal file
6687
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
34
package.json
Normal file
34
package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "libre-charge-map",
|
||||
"version": "0.5.0",
|
||||
"description": "Un visualisateur coloré de stations de recharge pour véhicules électriques selon les données OSM.",
|
||||
"main": "index.js",
|
||||
"devDependencies": {
|
||||
"@babel/preset-env": "^7.14.4",
|
||||
"@testing-library/dom": "^7.31.0",
|
||||
"@testing-library/jest-dom": "^5.12.0",
|
||||
"@testing-library/user-event": "^13.1.9",
|
||||
"babel-jest": "^27.0.2",
|
||||
"jest": "^27.0.3",
|
||||
"jest-html-reporter": "^3.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
"^.+\\.[t|j]sx?$": "babel-jest"
|
||||
},
|
||||
"rootDir": "tests",
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"mjs",
|
||||
"cjs",
|
||||
"jsx",
|
||||
"ts",
|
||||
"tsx",
|
||||
"json",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
45
tests/main.test.js
Normal file
45
tests/main.test.js
Normal file
@ -0,0 +1,45 @@
|
||||
import utils from '../js/utils'
|
||||
import colorUtils from '../js/color-utils'
|
||||
|
||||
describe('testing on features', () => {
|
||||
const featureWithOutput = {
|
||||
properties: {
|
||||
tags: {
|
||||
'socket:type2:output': '30 kW'
|
||||
}
|
||||
}
|
||||
}
|
||||
const featureWithBadOutput = {
|
||||
properties: {
|
||||
tags: {
|
||||
'socket:type2:output': '50000'
|
||||
}
|
||||
}
|
||||
}
|
||||
const featureWithoutOutput = {
|
||||
properties: {
|
||||
tags: {
|
||||
'socket:type2': '2'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
describe('testing outputPower', () => {
|
||||
it('finds max outputpower when existing', () => {
|
||||
let outputFound = utils.guessOutputPowerFromFeature(featureWithOutput)
|
||||
expect(outputFound).toEqual(30)
|
||||
})
|
||||
})
|
||||
describe('testing corresponding color', () => {
|
||||
|
||||
it('finds undefined color', () => {
|
||||
let color = colorUtils.getColor(featureWithoutOutput)
|
||||
expect(color).toEqual('#c0b1b1')
|
||||
})
|
||||
it('finds bad color', () => {
|
||||
let color = colorUtils.getColor(featureWithBadOutput)
|
||||
expect(color).toEqual('#ff1414')
|
||||
})
|
||||
})
|
||||
|
||||
})
|
Loading…
Reference in New Issue
Block a user