alihmaou commited on
Commit
a6d3d2b
·
verified ·
1 Parent(s): b13463d

Upload tools/vélib_disponibilites.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. tools/vélib_disponibilites.py +104 -0
tools/vélib_disponibilites.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import json
3
+ from PIL import Image
4
+ import numpy as np
5
+
6
+ # --- User Defined Logic ---
7
+ import requests
8
+ import difflib
9
+ from typing import Optional
10
+
11
+ def velib_disponibilites(query: str, token: str, commune: Optional[str] = None, max_results: int = 10) -> str:
12
+ """Search Vélib stations by approximate name and return real‑time availability.
13
+
14
+ Args:
15
+ query: Partial station name to search for.
16
+ token: API token for the PRIM marketplace.
17
+ commune: Optional city/commune name to filter stations.
18
+ max_results: Maximum number of stations to return.
19
+
20
+ Returns:
21
+ Human‑readable string describing each matching station and its current
22
+ bike/dock availability. Returns an error message if the data cannot be
23
+ retrieved or no stations match.
24
+ """
25
+ base_url = "https://prim.iledefrance-mobilites.fr/marketplace/velib"
26
+ headers = {"Authorization": f"Bearer {token}"} if token else {}
27
+
28
+ try:
29
+ info_resp = requests.get(f"{base_url}/station_information.json", headers=headers, timeout=10)
30
+ info_resp.raise_for_status()
31
+ stations_info = info_resp.json()
32
+
33
+ status_resp = requests.get(f"{base_url}/station_status.json", headers=headers, timeout=10)
34
+ status_resp.raise_for_status()
35
+ stations_status = status_resp.json()
36
+ except requests.RequestException as e:
37
+ return f"Erreur lors de la récupération des données Vélib : {e}"
38
+
39
+ stations_data = stations_info.get('data', {}).get('stations', [])
40
+ status_data = stations_status.get('data', {}).get('stations', [])
41
+
42
+ stations_dict = {s['station_id']: s for s in stations_data}
43
+
44
+ for status in status_data:
45
+ sid = status['station_id']
46
+ if sid in stations_dict:
47
+ stations_dict[sid].update({
48
+ 'num_bikes_available': status.get('num_bikes_available', 0),
49
+ 'num_bikes_available_mechanical': status.get('num_bikes_available_types', {}).get('mechanical', 0),
50
+ 'num_bikes_available_ebike': status.get('num_bikes_available_types', {}).get('ebike', 0),
51
+ 'num_docks_available': status.get('num_docks_available', 0),
52
+ 'last_reported': status.get('last_reported', '')
53
+ })
54
+
55
+ stations = list(stations_dict.values())
56
+
57
+ if commune:
58
+ commune_lower = commune.lower()
59
+ stations = [s for s in stations if commune_lower in s.get('address', '').lower()]
60
+ if not stations:
61
+ return f"Aucune station trouvée à '{commune}'."
62
+
63
+ station_names = [s.get('name', '') for s in stations if s.get('name')]
64
+ matches = difflib.get_close_matches(query, station_names, n=max_results, cutoff=0.3)
65
+
66
+ if not matches:
67
+ matches = [name for name in station_names if query.lower() in name.lower()][:max_results]
68
+
69
+ if not matches:
70
+ return f"Aucune station ne correspond à la recherche '{query}'."
71
+
72
+ lines = []
73
+ for name in matches:
74
+ station = next(s for s in stations if s.get('name') == name)
75
+ total = station.get('num_bikes_available', 0)
76
+ mech = station.get('num_bikes_available_mechanical', 0)
77
+ elec = station.get('num_bikes_available_ebike', 0)
78
+ docks = station.get('num_docks_available', 0)
79
+ address = station.get('address', '')
80
+ address_parts = [p.strip() for p in address.split(',')]
81
+ commune_name = address_parts[-1] if address_parts else 'Non spécifiée'
82
+
83
+ line = (
84
+ f"🚲 Station: {station.get('name', 'Inconnu')}\n"
85
+ f"📍 Adresse: {address} ({commune_name})\n"
86
+ f"🗺️ Coordonnées: {station.get('lat', 'N/A')}, {station.get('lon', 'N/A')}\n"
87
+ f"💺 Capacité totale: {station.get('capacity', 'N/A')}\n"
88
+ f"🚴 Vélos disponibles: {total} (dont {mech} mécaniques, {elec} électriques)\n"
89
+ f"🔌 Bornettes libres: {docks}\n"
90
+ f"⏰ Dernière mise à jour: {station.get('last_reported', 'Inconnue')}\n"
91
+ )
92
+ lines.append(line)
93
+
94
+ return "\n".join(lines)
95
+
96
+ # --- Interface Factory ---
97
+ def create_interface():
98
+ return gr.Interface(
99
+ fn=velib_disponibilites,
100
+ inputs=[gr.Textbox(label=k) for k in ['query', 'token']],
101
+ outputs=gr.Textbox(label="Formatted list of matching Vélib stations with real‑time availability"),
102
+ title="vélib_disponibilites",
103
+ description="Auto-generated tool: vélib_disponibilites"
104
+ )