mirror of
https://forge.chapril.org/tykayn/wololo
synced 2025-10-09 17:02:46 +02:00
réinit
This commit is contained in:
commit
996524bc6d
107 changed files with 1295536 additions and 0 deletions
82
wip/chargemap/chargemap.ts
Normal file
82
wip/chargemap/chargemap.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
import fs from "fs";
|
||||
|
||||
|
||||
let sourceFilePath: string = './chargemap_data/hurepoix.json'
|
||||
|
||||
/**
|
||||
makes a geojson from chargemap layer data
|
||||
*/
|
||||
function convertChargemapFile(sourceFilePath: string) {
|
||||
fs.readFile(sourceFilePath, 'utf8', function (err, data) {
|
||||
let data_transformed: any = JSON.parse(data)
|
||||
let base_dataset: any = {type: 'FeatureCollection', features: []}
|
||||
let base_point: any = {
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Point',
|
||||
coordinates: []
|
||||
},
|
||||
properties: {
|
||||
amenity: "charging_station"
|
||||
}
|
||||
}
|
||||
console.log('data_transformed.items.length', data_transformed.items.length)
|
||||
data_transformed.items.forEach((item: any) => {
|
||||
|
||||
let new_point: any = {...base_point}
|
||||
|
||||
if (item.type == 'point') {
|
||||
|
||||
new_point.geometry.coordinates = [
|
||||
item.properties?.lat,
|
||||
item.properties?.lng,
|
||||
]
|
||||
|
||||
} else if (item.type == 'pool') {
|
||||
new_point.geometry.coordinates = [
|
||||
item.pool.gps_coordinates.lon,
|
||||
item.pool.gps_coordinates.lat,
|
||||
]
|
||||
console.log('new_point.geometry.coordinates', new_point.geometry.coordinates)
|
||||
|
||||
}
|
||||
|
||||
base_dataset.features.push(new_point)
|
||||
})
|
||||
|
||||
|
||||
console.log('base_dataset.features.length', base_dataset.features.length)
|
||||
if (base_dataset) {
|
||||
|
||||
writeFile('hurepoix_geojson.json', JSON.stringify(base_dataset, null, 2))
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* crée un fichier dans le dossier par défaut, output
|
||||
* @param fileName
|
||||
* @param fileContent
|
||||
*/
|
||||
function writeFile(fileName: string, fileContent: any) {
|
||||
|
||||
|
||||
let output_folder = 'output';
|
||||
return fs.writeFile(
|
||||
`./${output_folder}/${fileName}`,
|
||||
fileContent,
|
||||
'utf8',
|
||||
(err) => {
|
||||
if (err) {
|
||||
console.log(`Error writing file: ${err}`)
|
||||
} else {
|
||||
console.log(`File ${fileName} is written successfully!`)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
convertChargemapFile(sourceFilePath)
|
||||
|
9594
wip/chargemap/hurepoix.json
Normal file
9594
wip/chargemap/hurepoix.json
Normal file
File diff suppressed because it is too large
Load diff
384
wip/chargemap/normandie.json
Normal file
384
wip/chargemap/normandie.json
Normal file
|
@ -0,0 +1,384 @@
|
|||
{
|
||||
"count": 18,
|
||||
"items": [
|
||||
{
|
||||
"lat": 50.0743484,
|
||||
"lng": 1.537268,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 33
|
||||
},
|
||||
{
|
||||
"lat": 49.6465569,
|
||||
"lng": 0.595749,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 31
|
||||
},
|
||||
{
|
||||
"lat": 49.9614983,
|
||||
"lng": 1.1935092,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 26
|
||||
},
|
||||
{
|
||||
"lat": 50.1074982,
|
||||
"lng": 1.8426746,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 24
|
||||
},
|
||||
{
|
||||
"lat": 50.2155533,
|
||||
"lng": 1.628114,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 22
|
||||
},
|
||||
{
|
||||
"lat": 49.6115227,
|
||||
"lng": 0.7733023,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 21
|
||||
},
|
||||
{
|
||||
"lat": 49.9128304,
|
||||
"lng": 1.0857821,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 20
|
||||
},
|
||||
{
|
||||
"lat": 49.8144035,
|
||||
"lng": 0.657026,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 16
|
||||
},
|
||||
{
|
||||
"lat": 49.8280449,
|
||||
"lng": 0.911511,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 15
|
||||
},
|
||||
{
|
||||
"lat": 49.5984917,
|
||||
"lng": 1.1111569,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 14
|
||||
},
|
||||
{
|
||||
"lat": 49.6525497,
|
||||
"lng": 1.6158921,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 11
|
||||
},
|
||||
{
|
||||
"lat": 49.7663574,
|
||||
"lng": 1.7457,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 9
|
||||
},
|
||||
{
|
||||
"lat": 49.9557304,
|
||||
"lng": 1.767372,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 7
|
||||
},
|
||||
{
|
||||
"lat": 49.8437424,
|
||||
"lng": 1.7790869,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 3
|
||||
},
|
||||
{
|
||||
"lat": 49.6544685,
|
||||
"lng": 1.832823,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"lat": 49.5701447,
|
||||
"lng": 0.4898517,
|
||||
"icon": "cluster.png",
|
||||
"type": "cluster",
|
||||
"count": 2
|
||||
},
|
||||
{
|
||||
"lat": 49.5702896,
|
||||
"lng": 1.609848,
|
||||
"icon": "icon-accelerated_on.png",
|
||||
"type": "pool",
|
||||
"pool": {
|
||||
"amenities": [],
|
||||
"city": "Saumont-la-Poterie",
|
||||
"real_time_available": true,
|
||||
"rating": null,
|
||||
"i18n_country_id": 67,
|
||||
"emsps": [],
|
||||
"gps_coordinates": {
|
||||
"lon": 1.609848,
|
||||
"lat": 49.5702896
|
||||
},
|
||||
"street_name": "358 Route de Paris ",
|
||||
"speed": {
|
||||
"icon": "accelerated.svg",
|
||||
"self": "charging_speeds/3.json",
|
||||
"id": 3,
|
||||
"map_icon": "accelerated.png"
|
||||
},
|
||||
"should_check_prices": true,
|
||||
"number": null,
|
||||
"schedules": [],
|
||||
"object_state_id": 2,
|
||||
"is_indoor": false,
|
||||
"id": 285402,
|
||||
"slug": "eco-pi-saumont-la-poterie-358-route-de-paris",
|
||||
"can_remote_start_charge": false,
|
||||
"statistic": {
|
||||
"global_note_average": null,
|
||||
"price_note_average": null,
|
||||
"location_note_average": null,
|
||||
"security_note_average": null,
|
||||
"comments_count": 0,
|
||||
"reports_count": 0,
|
||||
"checkins_count": 0,
|
||||
"material_note_average": null,
|
||||
"creation_date": "2023-07-29T02:04:10+00:00",
|
||||
"ratings_count": 1
|
||||
},
|
||||
"can_update_charging_pool": false,
|
||||
"is_always_open": true,
|
||||
"can_charge_with_chargemap": true,
|
||||
"location_type_id": 21,
|
||||
"network_id": 2340,
|
||||
"evse_emi3_ids": [
|
||||
"FR*EPI*E11734505*1"
|
||||
],
|
||||
"charging_connectors": [
|
||||
{
|
||||
"count": 5,
|
||||
"available_count": 3,
|
||||
"evse_ids": [
|
||||
701375,
|
||||
701376,
|
||||
701379,
|
||||
701377,
|
||||
701378
|
||||
],
|
||||
"type": "MENNEKES_TYPE_2",
|
||||
"connector_type": {
|
||||
"id": 14,
|
||||
"icon": "type2"
|
||||
},
|
||||
"power_max": 22
|
||||
}
|
||||
],
|
||||
"is_free": false,
|
||||
"name": "Eco-PI - Saumont-la-Poterie - 358 Route de Paris ",
|
||||
"location_type_slug": "unknown",
|
||||
"charging_speed_id": 3,
|
||||
"postal_code": "76440",
|
||||
"country_code": "FR",
|
||||
"is_tesla": false,
|
||||
"evses": [
|
||||
{
|
||||
"id": 701375,
|
||||
"is_available": true,
|
||||
"realtime_state": "AVAILABLE"
|
||||
},
|
||||
{
|
||||
"id": 701376,
|
||||
"is_available": true,
|
||||
"realtime_state": "AVAILABLE"
|
||||
},
|
||||
{
|
||||
"id": 701379,
|
||||
"is_available": true,
|
||||
"realtime_state": "AVAILABLE"
|
||||
},
|
||||
{
|
||||
"id": 701377,
|
||||
"is_available": false,
|
||||
"realtime_state": "OUT_OF_ORDER"
|
||||
},
|
||||
{
|
||||
"id": 701378,
|
||||
"is_available": false,
|
||||
"realtime_state": "OUT_OF_ORDER"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"lat": 49.5693893,
|
||||
"lng": 0.953997,
|
||||
"icon": "icon-accelerated_on.png",
|
||||
"type": "pool",
|
||||
"pool": {
|
||||
"amenities": [
|
||||
"drinks",
|
||||
"restoration",
|
||||
"shop",
|
||||
"restroom"
|
||||
],
|
||||
"city": "Pavilly",
|
||||
"real_time_available": true,
|
||||
"rating": 4,
|
||||
"i18n_country_id": 67,
|
||||
"emsps": [
|
||||
10,
|
||||
75,
|
||||
77,
|
||||
107,
|
||||
108,
|
||||
112
|
||||
],
|
||||
"gps_coordinates": {
|
||||
"lon": 0.953997,
|
||||
"lat": 49.5693893
|
||||
},
|
||||
"street_name": "Place du Président d'Esneval",
|
||||
"speed": {
|
||||
"icon": "accelerated.svg",
|
||||
"self": "charging_speeds/3.json",
|
||||
"id": 3,
|
||||
"map_icon": "accelerated.png"
|
||||
},
|
||||
"should_check_prices": true,
|
||||
"number": "4",
|
||||
"schedules": [],
|
||||
"object_state_id": 2,
|
||||
"is_indoor": false,
|
||||
"id": 105727,
|
||||
"slug": "sde76-place-du-president-desneval-4-pavilly",
|
||||
"can_remote_start_charge": false,
|
||||
"statistic": {
|
||||
"global_note_average": 4,
|
||||
"price_note_average": 5,
|
||||
"location_note_average": 2,
|
||||
"security_note_average": 5,
|
||||
"comments_count": 0,
|
||||
"reports_count": 0,
|
||||
"checkins_count": 25,
|
||||
"material_note_average": 2,
|
||||
"creation_date": "2023-07-29T02:01:25+00:00",
|
||||
"ratings_count": 1
|
||||
},
|
||||
"can_update_charging_pool": false,
|
||||
"is_always_open": true,
|
||||
"can_charge_with_chargemap": true,
|
||||
"location_type_id": 4,
|
||||
"network_id": 404,
|
||||
"evse_emi3_ids": [
|
||||
"FR*S76*E100*1*1"
|
||||
],
|
||||
"charging_connectors": [
|
||||
{
|
||||
"count": 4,
|
||||
"available_count": 2,
|
||||
"evse_ids": [
|
||||
25003,
|
||||
25004,
|
||||
390745,
|
||||
390747
|
||||
],
|
||||
"type": "DOMESTIC_TYPE_F",
|
||||
"connector_type": {
|
||||
"id": 6,
|
||||
"icon": "schuko"
|
||||
},
|
||||
"power_max": 3
|
||||
},
|
||||
{
|
||||
"count": 7,
|
||||
"available_count": 4,
|
||||
"evse_ids": [
|
||||
25003,
|
||||
25004,
|
||||
390745,
|
||||
390747,
|
||||
390662,
|
||||
390663,
|
||||
390664
|
||||
],
|
||||
"type": "MENNEKES_TYPE_2",
|
||||
"connector_type": {
|
||||
"id": 14,
|
||||
"icon": "type2"
|
||||
},
|
||||
"power_max": 22
|
||||
},
|
||||
{
|
||||
"count": 3,
|
||||
"available_count": 2,
|
||||
"evse_ids": [
|
||||
390662,
|
||||
390663,
|
||||
390664
|
||||
],
|
||||
"type": "DOMESTIC_TYPE_F",
|
||||
"connector_type": {
|
||||
"id": 6,
|
||||
"icon": "schuko"
|
||||
},
|
||||
"power_max": 2
|
||||
}
|
||||
],
|
||||
"is_free": false,
|
||||
"name": "SDE76 - Place du Président d'Esneval, 4 - Pavilly",
|
||||
"location_type_slug": "parking",
|
||||
"charging_speed_id": 3,
|
||||
"postal_code": "76570",
|
||||
"country_code": "FR",
|
||||
"is_tesla": false,
|
||||
"evses": [
|
||||
{
|
||||
"id": 25003,
|
||||
"is_available": true,
|
||||
"realtime_state": "AVAILABLE"
|
||||
},
|
||||
{
|
||||
"id": 25004,
|
||||
"is_available": true,
|
||||
"realtime_state": "AVAILABLE"
|
||||
},
|
||||
{
|
||||
"id": 390745,
|
||||
"is_available": false,
|
||||
"realtime_state": "OUT_OF_ORDER"
|
||||
},
|
||||
{
|
||||
"id": 390747,
|
||||
"is_available": false,
|
||||
"realtime_state": "OUT_OF_ORDER"
|
||||
},
|
||||
{
|
||||
"id": 390662,
|
||||
"is_available": false,
|
||||
"realtime_state": "OUT_OF_ORDER"
|
||||
},
|
||||
{
|
||||
"id": 390663,
|
||||
"is_available": true,
|
||||
"realtime_state": "AVAILABLE"
|
||||
},
|
||||
{
|
||||
"id": 390664,
|
||||
"is_available": true,
|
||||
"realtime_state": "AVAILABLE"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
184
wip/group_irve_stats.py
Normal file
184
wip/group_irve_stats.py
Normal file
|
@ -0,0 +1,184 @@
|
|||
import pandas as pd
|
||||
|
||||
import folium
|
||||
import plotly.graph_objects as go
|
||||
import io
|
||||
|
||||
# Chargement du fichier JSON
|
||||
with open('/home/poule/encrypted/stockage-syncable/www/development/html/mapping-geojson-osm/etalab_data/irve_bornes_recharge/latest.csv', 'r') as file:
|
||||
data = pd.read_csv(file)
|
||||
|
||||
|
||||
def format_puissance_nominale(value):
|
||||
"""Formate la valeur de la puissance nominale"""
|
||||
if value >= 1000:
|
||||
return "{:,.1f} kW".format(value / 1000)
|
||||
else:
|
||||
return "{:,.0f} W".format(value)
|
||||
|
||||
|
||||
|
||||
|
||||
# Création du DataFrame pandas
|
||||
dataframe_irve = pd.DataFrame(data)
|
||||
print("Nombre total de lignes avant suppression de duplicatas: ", len(dataframe_irve))
|
||||
|
||||
|
||||
# enlever les duplicatas selon l'id du point de charge
|
||||
dataframe_irve = dataframe_irve.drop_duplicates(subset=["id_pdc_itinerance"])
|
||||
# enlever les duplicatas de placement
|
||||
dataframe_irve = dataframe_irve.drop_duplicates(subset=["coordonneesXY"])
|
||||
# enlever les lignes où on ne connait pas l'opérateur
|
||||
dataframe_irve = dataframe_irve[(dataframe_irve["nom_operateur"].notnull()) & (dataframe_irve["nom_amenageur"].notnull())]
|
||||
dataframe_irve = dataframe_irve[(dataframe_irve["coordonneesXY"].notnull())]
|
||||
|
||||
# Regroupement par opérateur
|
||||
groups = dataframe_irve.groupby("nom_operateur")
|
||||
|
||||
dataframe_irve_sorted = dataframe_irve.sort_values(by="nom_operateur")
|
||||
|
||||
# Affichage du résultat
|
||||
# print(dataframe_irve_sorted)
|
||||
|
||||
|
||||
# Filtres pour identifier les lignes incorrectes
|
||||
filtre_non_numerique = dataframe_irve["puissance_nominale"] % 1 > 0
|
||||
filtre_incorrect = filtre_non_numerique
|
||||
|
||||
# Lignes incorrectes
|
||||
erreurs_puissance_nominale = dataframe_irve[filtre_incorrect][[ "puissance_nominale", "id_station_itinerance"]]
|
||||
|
||||
groups_erreur = erreurs_puissance_nominale
|
||||
print('groups en erreur: \n',)
|
||||
groups_erreur.head()
|
||||
|
||||
# Minimum de puissance_nominale
|
||||
puissance_nominale_min = dataframe_irve["puissance_nominale"].min()
|
||||
|
||||
# Maximum de puissance_nominale
|
||||
puissance_nominale_max = dataframe_irve["puissance_nominale"].max()
|
||||
|
||||
print("\nMinimum de puissance_nominale : {}".format(puissance_nominale_min))
|
||||
print("Maximum de puissance_nominale : {}\n".format(puissance_nominale_max))
|
||||
|
||||
# Impression du nombre de stations restantes
|
||||
print("Nombre total de lignes : ", len(dataframe_irve))
|
||||
|
||||
|
||||
# Application de la fonction de formatage à la colonne "puissance_nominale"
|
||||
dataframe_irve["puissance_nominale_formatted"] = dataframe_irve["puissance_nominale"].apply(format_puissance_nominale)
|
||||
|
||||
# Remplacement de la colonne originale par celle nouvellement formatée
|
||||
dataframe_irve["puissance_nominale"] = dataframe_irve["puissance_nominale_formatted"]
|
||||
del dataframe_irve["puissance_nominale_formatted"]
|
||||
|
||||
|
||||
|
||||
# Compte le nombre d'anomalies pour chaque opérateur
|
||||
def count_errors_for_each_operator():
|
||||
# Initialisation du dictionnaire vide servant au stockage temporaire
|
||||
temp_dict = dict()
|
||||
|
||||
for _, row in dataframe_irve.iterrows():
|
||||
operator = str(row["nom_operateur"])
|
||||
|
||||
# Test uniquement les entrées textuelles présentes dans la colonne "puissance_nominale"
|
||||
power_entry = str(row["puissance_nominale"]).replace('W', '').replace(' ', '')
|
||||
if 'k' in power_entry or power_entry[-2:] == ". " or int(power_entry) > 6000 or int(power_entry) < 0:
|
||||
if operator not in temp_dict:
|
||||
temp_dict[operator] = {"error_count": 1}
|
||||
else:
|
||||
current_error_count = temp_dict[operator]["error_count"] + 1
|
||||
temp_dict[operator] = {"error_count": current_error_count}
|
||||
|
||||
# Transformation du dictionnaire local en liste de tuples
|
||||
return sorted([(key, val["error_count"]) for key, val in temp_dict.items()], key=lambda x: -x[1])
|
||||
|
||||
# Passage du DataFrame à la fonction
|
||||
countland = count_errors_for_each_operator()
|
||||
|
||||
print("\nListe des opérateurs classés par nombre d'anomalies :'" , countland)
|
||||
|
||||
# Affichage des résultats
|
||||
# print("\nListe des opérateurs classés par nombre d'anomalies : ")
|
||||
for i, item in enumerate(countland):
|
||||
print("{} - Opérateur : {}, Anomalies : {}".format(i+1, item[0], item[1]))
|
||||
|
||||
# ============== graphique ============================
|
||||
import plotly.express as px
|
||||
import plotly.io as pio
|
||||
pio.renderers.default = "svg"
|
||||
# Spécification du nom et du path du fichier de sortie
|
||||
output_filename = "puissances_repartition.svg"
|
||||
|
||||
# Génération du graphe
|
||||
# fig = px.histogram(
|
||||
# dataframe_irve,
|
||||
# x="puissance_nominale",
|
||||
# title="Répartition des Puissances",
|
||||
# labels={'puissance_nominale': 'Puissance'},
|
||||
# color_discrete_sequence=px.colors.sequential.Plasma_r,
|
||||
# opacity=0.7,
|
||||
# hover_name="nom_operateur",
|
||||
# category_orders={'puissance_nominale': ['<1 kW', '1 kW', '2 kW', '3 kW', '5 kW', '6 kW', '8 kW', '11 kW', '12 kW', '15 kW', '22 kW', '30 kW', '43 kW', '50 kW', '150 kW']},
|
||||
# )
|
||||
|
||||
# Visualisation du graphe
|
||||
# fig.show()
|
||||
|
||||
|
||||
# Sauvegarde du graphe Plotly sous forme de fichier SVG
|
||||
# fig.write_image(output_filename, engine='kaleido', scale=1.0)
|
||||
#
|
||||
# # Display the generated filename
|
||||
# print("\nGraph saved to:", output_filename)
|
||||
|
||||
dataframe_irve.to_csv("output/cleaned_irve_from_cipherbliss.csv", index=False)
|
||||
|
||||
|
||||
# ============ carte svg
|
||||
|
||||
|
||||
# Colonne "coordonneesXY" est un string, transformation en tuple
|
||||
dataframe_irve[['latitude','longitude']] = dataframe_irve['coordonneesXY'].str.findall(r'(-?[\d]+(\.[0-9]*)?)').apply(pd.Series)
|
||||
|
||||
dataframe_irve['latitude'].head()
|
||||
|
||||
# Centrer la map sur la france
|
||||
france_center = [47.5, 2.5]
|
||||
# map_folium = folium.Map(location=france_center, zoom_start=5)
|
||||
#
|
||||
# # Itération sur chaque point géographique pour l'ajouter à la map Folium
|
||||
# for index, row in dataframe_irve.iterrows():
|
||||
# location = [row['latitude'], row['longitude']]
|
||||
# icon = folium.Icon(color='blue', icon='info-sign')
|
||||
# tooltip = "<strong>{}</strong>{}".format(row['id_station_itinerance'], row['adresse_station'])
|
||||
# popup = '<div style="width:10rem;">{}</div>'.format(row['nom_station'])
|
||||
# marker = folium.Marker(location, popup=popup, tooltip=tooltip, icon=icon)
|
||||
# marker.add_to(map_folium)
|
||||
#
|
||||
# # Objet graphique Plotly contenant la carte Folium encodée
|
||||
# plotly_chart = go.Figure(go.Scattergeo(
|
||||
# lon=[row['longitude'] for index, row in dataframe_irve.iterrows()],
|
||||
# lat=[row['latitude'] for index, row in dataframe_irve.iterrows()]
|
||||
# ))
|
||||
#
|
||||
# # Configuration de l'apparence visuelle
|
||||
# plotly_chart.update_geos(fitbounds="locations", visible=True)
|
||||
# plotly_chart.update_layout(
|
||||
# geo_scope="world",
|
||||
# margin={"r":0,"t":0,"l":0,"b":0},
|
||||
# paper_bgcolor="#FFFFFF",
|
||||
# plot_bgcolor="#FFFFFF",
|
||||
# showlegend=False
|
||||
# )
|
||||
|
||||
|
||||
|
||||
# Encapsulation de la carte Plotly dans un objet BytesIO
|
||||
# buffer = io.BytesIO()
|
||||
# plotly_chart.write_html(buffer, auto_open=False)
|
||||
# buffer.seek(0)
|
||||
|
||||
# Affichage de la carte Plotly
|
||||
# plotly.io.write_image(plotly_chart, "carte_stations.svg", format="svg", engine="kaleido")
|
35
wip/irve_split_by_operators_from_json.ts
Normal file
35
wip/irve_split_by_operators_from_json.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
const stations = [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Tesla Supercharger',
|
||||
address: '123 Main St',
|
||||
lat: 37.7749,
|
||||
lon: -122.4194,
|
||||
network_operator: 'Tesla'
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Electrify America',
|
||||
address: '456 Maple Ave',
|
||||
lat: 40.7128,
|
||||
lon: -74.0060,
|
||||
network_operator: 'Electrify America'
|
||||
},
|
||||
{id: 3, name: 'ChargePoint', address: '789 Oak St', lat: 34.0522, lon: -118.2437, network_operator: 'ChargePoint'},
|
||||
];
|
||||
|
||||
interface Station {
|
||||
[key: string]: string
|
||||
|
||||
}
|
||||
|
||||
function groupStationsByNetworkOperator(stations: Station[]) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
function groupStationsByNetworkOperatorAndWriteToFiles(stations: any[], outputDir: string) {
|
||||
|
||||
}
|
||||
|
||||
groupStationsByNetworkOperatorAndWriteToFiles(stations, "output")
|
Loading…
Add table
Add a link
Reference in a new issue