Michelg29 commited on
Commit
0c7547b
·
verified ·
1 Parent(s): 0a278c1

Upload 3 files

Browse files
Files changed (3) hide show
  1. app.py +165 -12
  2. mon_modele.joblib +2 -2
  3. mon_modele_rf1.joblib +3 -0
app.py CHANGED
@@ -1,15 +1,23 @@
1
- API_KEY2 = "AIzaSyAWfT7LegzDMdwebnghQu3vjqYBZfJUdo0"
2
- API_METEO = "bd715056584f453cc48cb17af2e5e0bd"
3
  import joblib
4
  import numpy as np
5
  import streamlit as st
6
  import requests
 
 
 
 
 
 
7
 
8
  # -------------------------------------------------------------------------
9
  # PARAMÈTRES ET CHARGEMENT DU MODÈLE
10
  # -------------------------------------------------------------------------
11
- API_KEY = API_KEY2
12
- modele = joblib.load("mon_modele.joblib")
 
 
13
 
14
  # Tarif fixe (0.70 $/km) pour le modèle
15
  TARIF_PAR_KM = 0.70
@@ -89,6 +97,24 @@ def get_distance_and_duration(lat1, lng1, lat2, lng2, api_key):
89
  return dist_km, dur_min
90
  return None, None
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  def get_weather(lat, lng, api_key):
93
  """
94
  Récupère la météo actuelle à partir des coordonnées GPS.
@@ -100,19 +126,104 @@ def get_weather(lat, lng, api_key):
100
  f"&lon={lng}"
101
  f"&appid={api_key}"
102
  f"&units=metric"
103
- f"&lang=fr"
104
  )
105
  response = requests.get(url)
106
  if response.status_code == 200:
107
  data = response.json()
108
  temp = data["main"]["temp"]
109
  description = data["weather"][0]["description"]
110
- return temp, description
 
111
  else:
112
  return None, None
113
 
114
 
115
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  # -------------------------------------------------------------------------
117
  # INTERFACE UTILISATEUR : ADRESSES
118
  # -------------------------------------------------------------------------
@@ -127,7 +238,8 @@ if pickup_input:
127
  pickup_suggestions = get_address_suggestions(pickup_input, API_KEY)
128
 
129
  pickup_options = [s["description"] for s in pickup_suggestions]
130
- selected_pickup = st.selectbox("Suggestions pour l'adresse de départ :", pickup_options)
 
131
 
132
  st.header("Adresse d'arrivée")
133
  destination_input = st.text_input(
@@ -145,6 +257,11 @@ selected_destination = st.selectbox("Suggestions pour l'adresse d'arrivée :", d
145
  # -------------------------------------------------------------------------
146
  # BOUTON POUR TOUT CALCULER
147
  # -------------------------------------------------------------------------
 
 
 
 
 
148
  if st.button("Prédire le prix"):
149
  # Vérifier que l'utilisateur a sélectionné une suggestion
150
  if not selected_pickup or not selected_destination:
@@ -178,6 +295,15 @@ if st.button("Prédire le prix"):
178
  API_KEY
179
  )
180
  print(pickup_coords)
 
 
 
 
 
 
 
 
 
181
  if dist_km is not None and dur_min is not None:
182
  # Affichage
183
  if dur_min > 60:
@@ -186,26 +312,53 @@ if st.button("Prédire le prix"):
186
  #print(heures, minutes)
187
  st.write(f"**Durée estimée** : {int(heures)} heures {int(minutes)} minutes")
188
  else:
189
- st.write(f"**Distance estimée** : {dist_km} km")
 
 
 
 
 
 
 
 
190
 
191
  # Appel du modèle ML :
192
  # => Le modèle attend [distance, durée, prix_km=0.70]
193
  # => On lui passe donc ces 3 features
194
 
195
- donnee_entree = np.array([[dist_km, dur_min, TARIF_PAR_KM]])
196
- prediction_modele = modele.predict(donnee_entree)
197
 
198
- st.write(f"**Prédiction du modèle** : {prediction_modele[0]:.2f} $")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
  else:
200
  st.error("Impossible de calculer la distance ou la durée.")
201
  else:
202
  st.error("Impossible de récupérer les coordonnées GPS.")
203
 
 
 
 
 
 
 
204
  # Affichage de la meteo
205
  meteo = get_weather(pickup_coords[0], pickup_coords[1], API_METEO)
206
  if meteo:
207
  temperature, descrip = meteo
208
- st.write(f"Temperature : {round(temperature)} degré celsius, principalement : {descrip} en ce moment")
209
 
210
 
211
  else:
 
1
+ from os import write
2
+
3
  import joblib
4
  import numpy as np
5
  import streamlit as st
6
  import requests
7
+ import pandas as pd
8
+
9
+ from dotenv import load_dotenv
10
+ import os
11
+ load_dotenv(".api_env")
12
+
13
 
14
  # -------------------------------------------------------------------------
15
  # PARAMÈTRES ET CHARGEMENT DU MODÈLE
16
  # -------------------------------------------------------------------------
17
+ API_KEY = os.getenv("API_KEY")
18
+ API_METEO = os.getenv("API_METEO")
19
+ modele_linear = joblib.load("mon_modele.joblib")
20
+ modele_rf = joblib.load("mon_modele_rf1.joblib")
21
 
22
  # Tarif fixe (0.70 $/km) pour le modèle
23
  TARIF_PAR_KM = 0.70
 
97
  return dist_km, dur_min
98
  return None, None
99
 
100
+ def interpret_weather(description):
101
+ """
102
+
103
+ :param description: recupere la description qui est de base une chaine de caractere qui
104
+ nous est retournée par la fonction get_weather.
105
+ :return: nous retourne un des mots clés (rain, snow, clear)
106
+ """
107
+ if description is not None:
108
+ # convertissons toute la description en minuscule
109
+ description_lower = description.lower()
110
+ if "rain" in description_lower :
111
+ return "rain"
112
+ elif "snow" in description_lower :
113
+ return "snow"
114
+ else:
115
+ return "clear"
116
+
117
+
118
  def get_weather(lat, lng, api_key):
119
  """
120
  Récupère la météo actuelle à partir des coordonnées GPS.
 
126
  f"&lon={lng}"
127
  f"&appid={api_key}"
128
  f"&units=metric"
129
+ f"&lang=en"
130
  )
131
  response = requests.get(url)
132
  if response.status_code == 200:
133
  data = response.json()
134
  temp = data["main"]["temp"]
135
  description = data["weather"][0]["description"]
136
+ desc = interpret_weather(description)
137
+ return temp, desc
138
  else:
139
  return None, None
140
 
141
 
142
 
143
+ def encoding_weather(description):
144
+ """
145
+
146
+ :param description: recupere la description du retour de la fonction get_weather.
147
+ :return: nous retourne 0 ou 1 (pour que le modele comprenne)
148
+ """
149
+ if description is not None:
150
+ description_lower = description.lower()
151
+ if description_lower == "rain":
152
+ return 1,0
153
+ elif description_lower == "snow":
154
+ return 0,1
155
+ else:
156
+ return 0,0
157
+ else:
158
+ print("Description non recuperée")
159
+ return
160
+
161
+
162
+
163
+ def interpret_traffic_level(elem):
164
+ """
165
+ Compare duration_in_traffic vs. duration
166
+ pour en déduire un label (Low, Medium, High).
167
+ """
168
+ dur_no_traffic = elem["duration"]["value"] # en secondes
169
+ dur_with_traffic = elem["duration_in_traffic"]["value"]
170
+
171
+ ratio = dur_with_traffic / dur_no_traffic
172
+
173
+ # Ex. si la durée augmente de moins de 10% => Low
174
+ # entre 10% et 30% => Medium
175
+ # plus de 30% => High
176
+ if ratio < 1.10:
177
+ return "Low"
178
+ elif ratio < 1.30:
179
+ return "Medium"
180
+ else:
181
+ return "High"
182
+
183
+ def get_traffic_conditions(lat1, lng1, lat2, lng2, api_key):
184
+ """
185
+ Récupère les conditions de trafic entre deux points via l'API Distance Matrix.
186
+ Retourne le niveau de trafic (Low, Medium, High).
187
+ """
188
+ origin = f"{lat1},{lng1}"
189
+ destination = f"{lat2},{lng2}"
190
+ url = (
191
+ "https://maps.googleapis.com/maps/api/distancematrix/json"
192
+ f"?origins={origin}"
193
+ f"&destinations={destination}"
194
+ f"&key={api_key}"
195
+ "&mode=driving"
196
+ "&departure_time=now"
197
+ "&traffic_model=best_guess"
198
+ )
199
+ resp = requests.get(url).json()
200
+ if resp["status"] == "OK":
201
+ elem = resp["rows"][0]["elements"][0]
202
+ if elem["status"] == "OK":
203
+ # Extraire duration & duration_in_traffic et créer un label
204
+ return interpret_traffic_level(elem)
205
+ return "Unknown"
206
+
207
+
208
+ def encodage_traffic_conditions(level):
209
+ """
210
+ :param level: c'est le niveau du trafic qui sera (Low,Medium ou High)
211
+ :return: retourner un tuple avec deux valeurs 0 ou 1 pour pouvoir etre considerer par notre modele
212
+ """
213
+ if level is not None:
214
+ if level == "Low":
215
+ return 1,0
216
+ elif level == "Medium":
217
+ return 0,1
218
+ elif level == "High":
219
+ return 0,0
220
+ else:
221
+ print("Le niveau du traffic est introuvable")
222
+ return
223
+
224
+
225
+
226
+
227
  # -------------------------------------------------------------------------
228
  # INTERFACE UTILISATEUR : ADRESSES
229
  # -------------------------------------------------------------------------
 
238
  pickup_suggestions = get_address_suggestions(pickup_input, API_KEY)
239
 
240
  pickup_options = [s["description"] for s in pickup_suggestions]
241
+ selected_pickup = st.selectbox("Suggestions pour l'adresse de départ :", pickup_options,
242
+ placeholder= "Pas d'options proposés")
243
 
244
  st.header("Adresse d'arrivée")
245
  destination_input = st.text_input(
 
257
  # -------------------------------------------------------------------------
258
  # BOUTON POUR TOUT CALCULER
259
  # -------------------------------------------------------------------------
260
+
261
+ """
262
+ Donnees attendus par le modele : ['distance', 'minutes', 'prix_kilometre', 'Traffic_Conditions_Low',
263
+ 'Traffic_Conditions_Medium', 'Weather_Rain', 'Weather_Snow']
264
+ """
265
  if st.button("Prédire le prix"):
266
  # Vérifier que l'utilisateur a sélectionné une suggestion
267
  if not selected_pickup or not selected_destination:
 
295
  API_KEY
296
  )
297
  print(pickup_coords)
298
+ #
299
+ traffic_level = get_traffic_conditions(pickup_coords[0],pickup_coords[1],
300
+ dest_coords[0],dest_coords[1],API_KEY)
301
+
302
+ temp, desc = get_weather(pickup_coords[0],pickup_coords[1],API_METEO)
303
+
304
+
305
+
306
+
307
  if dist_km is not None and dur_min is not None:
308
  # Affichage
309
  if dur_min > 60:
 
312
  #print(heures, minutes)
313
  st.write(f"**Durée estimée** : {int(heures)} heures {int(minutes)} minutes")
314
  else:
315
+ st.write(f"**Durée estimée** : {int(dur_min)} minutes")
316
+
317
+ st.write(f"**Distance estimée** : {dist_km} km")
318
+
319
+ #
320
+ traffic_low, traffic_medium = encodage_traffic_conditions(traffic_level)
321
+ #
322
+ weather_rain, weather_snow = encoding_weather(desc)
323
+
324
 
325
  # Appel du modèle ML :
326
  # => Le modèle attend [distance, durée, prix_km=0.70]
327
  # => On lui passe donc ces 3 features
328
 
 
 
329
 
330
+
331
+ colonnes = ['distance', 'minutes', 'prix_kilometre',
332
+ 'Traffic_Conditions_Low', 'Traffic_Conditions_Medium',
333
+ 'Weather_Rain', 'Weather_Snow']
334
+
335
+ donnee_entree = pd.DataFrame([[dist_km, dur_min, TARIF_PAR_KM,
336
+ traffic_low, traffic_medium,
337
+ weather_rain, weather_snow]], columns=colonnes)
338
+ if dist_km > 50:
339
+ prediction_modele1 = modele_linear.predict(donnee_entree)
340
+ print("prediction_modele1")
341
+ st.write(f"**Prédiction du modèle** : {prediction_modele1[0]:.2f} $")
342
+ else:
343
+ prediction_modele2 = modele_rf.predict(donnee_entree)
344
+ print("prediction_modele2")
345
+ st.write(f"**Prédiction du modèle** : {prediction_modele2[0]:.2f} $")
346
  else:
347
  st.error("Impossible de calculer la distance ou la durée.")
348
  else:
349
  st.error("Impossible de récupérer les coordonnées GPS.")
350
 
351
+ # Affichage des conditions du traffic
352
+ if traffic_level:
353
+ st.write(f"**Conditions de trafic** : {traffic_level}")
354
+ else:
355
+ st.write('**Conditions de traffic** : Inconnues')
356
+
357
  # Affichage de la meteo
358
  meteo = get_weather(pickup_coords[0], pickup_coords[1], API_METEO)
359
  if meteo:
360
  temperature, descrip = meteo
361
+ st.write(f"**Temperature** : {round(temperature)} degré celsius, principalement : {descrip} en ce moment")
362
 
363
 
364
  else:
mon_modele.joblib CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:838f58ea1ada449dbbee73fe000806607e0f29092eaad01ace8fb7d14631c42e
3
- size 928
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8ea5add9f4812c6ef5bc877a5e7bfa5756a1c809788134c7f661baa40f27fa77
3
+ size 1088
mon_modele_rf1.joblib ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:bd00d42d2822c53100c18b8b7aaf2aec045998a5922f0bf5e61b2e0d25c0336e
3
+ size 67948401