Spaces:
Sleeping
Sleeping
update new opt algorithm
Browse files- app.py +28 -12
- requirements.txt +1 -0
- utils.py +110 -76
app.py
CHANGED
@@ -34,7 +34,8 @@ with gr.Blocks() as demo:
|
|
34 |
with gr.Group() as main_group:
|
35 |
with gr.Tab("EV Charger Stations"):
|
36 |
plot_type = gr.Radio(['Provider', 'Charging Type'], value="Provider", label='Map type',
|
37 |
-
info="Map type plots separatly EV station by providers, charging type or both.",
|
|
|
38 |
gr_fmap = Folium(fmap_provider)
|
39 |
|
40 |
with gr.Tab("EV Charger along the Route"):
|
@@ -47,10 +48,12 @@ with gr.Blocks() as demo:
|
|
47 |
gr.DownloadButton(label="Setting Configuration", interactive=False)
|
48 |
with gr.Row():
|
49 |
search_type = gr.Radio(['Place Name', 'Coordinate'], value="Place Name", label='Search by',
|
50 |
-
info="Search address by place name or coordinate in format of (lat,long).",
|
|
|
51 |
plotcircle_radius = gr.Radio(['Without Circle', 'With Circle'], value="Without Circle", label='Plot Circle',
|
52 |
info="Plot a map with(or without) a circle for each point returned by the Google API.", interactive=True)
|
53 |
-
radius = gr.Slider(minimum=0.1, maximum=10, value=
|
|
|
54 |
with gr.Row():
|
55 |
submit_btn = gr.Button("Submit", variant='primary')
|
56 |
with gr.Row():
|
@@ -83,12 +86,25 @@ with gr.Blocks() as demo:
|
|
83 |
with gr.Row():
|
84 |
gr.DownloadButton(label="Input Battery Details", interactive=False)
|
85 |
with gr.Row():
|
86 |
-
opt_battery_capacity = gr.Number(value=
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
92 |
with gr.Row():
|
93 |
opt_submit_btn = gr.Button("Submit", variant='primary')
|
94 |
with gr.Row():
|
@@ -111,9 +127,9 @@ with gr.Blocks() as demo:
|
|
111 |
[origin_address, destination_address, search_type, radius, plotcircle_radius],
|
112 |
[fmap_route, total_distance, total_duration, route_df, stations_df, file1, file2])
|
113 |
|
114 |
-
opt_submit_btn.click(lambda originaddress, destinationaddress, batcapacity, batinit, batarival, ports,
|
115 |
-
plot_optimization(originaddress, destinationaddress, batcapacity, batinit, batarival, ports,
|
116 |
-
[opt_origin_address, opt_destination_address, opt_battery_capacity, opt_battery_initial, opt_battery_arrival, opt_charging_ports,
|
117 |
[opt_fmap, opt_distance, opt_driving_time, opt_charging_time, opt_total_time])
|
118 |
|
119 |
demo.launch(debug=False)
|
|
|
34 |
with gr.Group() as main_group:
|
35 |
with gr.Tab("EV Charger Stations"):
|
36 |
plot_type = gr.Radio(['Provider', 'Charging Type'], value="Provider", label='Map type',
|
37 |
+
info="Map type plots separatly EV station by providers, charging type or both.",
|
38 |
+
interactive=True)
|
39 |
gr_fmap = Folium(fmap_provider)
|
40 |
|
41 |
with gr.Tab("EV Charger along the Route"):
|
|
|
48 |
gr.DownloadButton(label="Setting Configuration", interactive=False)
|
49 |
with gr.Row():
|
50 |
search_type = gr.Radio(['Place Name', 'Coordinate'], value="Place Name", label='Search by',
|
51 |
+
info="Search address by place name or coordinate in format of (lat,long).",
|
52 |
+
interactive=True)
|
53 |
plotcircle_radius = gr.Radio(['Without Circle', 'With Circle'], value="Without Circle", label='Plot Circle',
|
54 |
info="Plot a map with(or without) a circle for each point returned by the Google API.", interactive=True)
|
55 |
+
radius = gr.Slider(minimum=0.1, maximum=10, value=3.5, step=0.1, label="Circle Radius (Km.)",
|
56 |
+
info='Adjust the radius of the circle.', interactive=True)
|
57 |
with gr.Row():
|
58 |
submit_btn = gr.Button("Submit", variant='primary')
|
59 |
with gr.Row():
|
|
|
86 |
with gr.Row():
|
87 |
gr.DownloadButton(label="Input Battery Details", interactive=False)
|
88 |
with gr.Row():
|
89 |
+
opt_battery_capacity = gr.Number(value=60, label='Battery capacity (kWh):',
|
90 |
+
info='Input battery capacity in kWh.')
|
91 |
+
opt_battery_initial = gr.Slider(minimum=0, maximum=100, value=50, step=0.1,
|
92 |
+
label="Current battery level (%)", info='Input your current battery level in %.',
|
93 |
+
interactive=True)
|
94 |
+
opt_battery_arrival = gr.Slider(minimum=0, maximum=100, value=50, step=0.1,
|
95 |
+
label="Desired battery level at destination (%)",
|
96 |
+
info='Input your desired battery level at destination in %.', interactive=True)
|
97 |
+
opt_reserve_battery = gr.Slider(minimum=0, maximum=100, value=10, step=0.1, label="Reserve battery level (%)",
|
98 |
+
info='Battery arrival of each station will be always grater than reserve battery.',
|
99 |
+
interactive=True)
|
100 |
+
with gr.Row():
|
101 |
+
opt_charging_ports = gr.CheckboxGroup(["Type2", "CCS2", "CHAdeMO"],
|
102 |
+
value=["Type2", "CCS2", "CHAdeMO"], label="Usable charging connectors",
|
103 |
+
info="Select your usable charging connectors.",interactive=True)
|
104 |
+
opt_provider_filter = gr.CheckboxGroup(['PTT', 'PEA', 'EleX', 'Altervim', 'EA'],
|
105 |
+
value=['PTT', 'PEA', 'EleX', 'Altervim', 'EA'],
|
106 |
+
label="Charging providers", info="Select your charging providers.",
|
107 |
+
interactive=True)
|
108 |
with gr.Row():
|
109 |
opt_submit_btn = gr.Button("Submit", variant='primary')
|
110 |
with gr.Row():
|
|
|
127 |
[origin_address, destination_address, search_type, radius, plotcircle_radius],
|
128 |
[fmap_route, total_distance, total_duration, route_df, stations_df, file1, file2])
|
129 |
|
130 |
+
opt_submit_btn.click(lambda originaddress, destinationaddress, batcapacity, batinit, batarival, batreserve, ports, provider :
|
131 |
+
plot_optimization(originaddress, destinationaddress, batcapacity, batinit, batarival, batreserve, ports, provider, gmaps=gmaps, data=data),
|
132 |
+
[opt_origin_address, opt_destination_address, opt_battery_capacity, opt_battery_initial, opt_battery_arrival, opt_reserve_battery, opt_charging_ports, opt_provider_filter],
|
133 |
[opt_fmap, opt_distance, opt_driving_time, opt_charging_time, opt_total_time])
|
134 |
|
135 |
demo.launch(debug=False)
|
requirements.txt
CHANGED
@@ -9,4 +9,5 @@ xlsxwriter
|
|
9 |
python-dotenv
|
10 |
requests
|
11 |
numpy
|
|
|
12 |
https://gradio-builds.s3.amazonaws.com/a57e34ef87d24f40f09380b7b71a052f120a19fe/gradio-4.19.2-py3-none-any.whl
|
|
|
9 |
python-dotenv
|
10 |
requests
|
11 |
numpy
|
12 |
+
geopy
|
13 |
https://gradio-builds.s3.amazonaws.com/a57e34ef87d24f40f09380b7b71a052f120a19fe/gradio-4.19.2-py3-none-any.whl
|
utils.py
CHANGED
@@ -14,6 +14,7 @@ import re
|
|
14 |
import os
|
15 |
import requests
|
16 |
import numpy as np
|
|
|
17 |
from typing import Any, Union
|
18 |
from dotenv import load_dotenv
|
19 |
|
@@ -145,20 +146,17 @@ def convert_string_to_tuple(input_string:str) -> tuple[float,float]:
|
|
145 |
except:
|
146 |
gr.Warning(f"'{input_string}' Worng Format. coordinate should be (lat, long). Please check your coordinate or try to use Place Name option instead.")
|
147 |
|
148 |
-
def geocode_place(place_name:str, gmaps:googlemaps.Client, warning_text:str
|
149 |
-
|
150 |
-
|
151 |
-
geocode_result = gmaps.geocode(place_name)
|
152 |
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
raise ValueError()
|
159 |
-
|
160 |
-
except:
|
161 |
gr.Warning(f"'{place_name}' {warning_text}")
|
|
|
162 |
|
163 |
def get_polyline(origin_address:tuple[float,float], destination_address:tuple[float,float], gmaps:googlemaps.Client) -> list[float]:
|
164 |
directions_result = gmaps.directions(origin_address, destination_address, mode='driving')
|
@@ -171,25 +169,65 @@ def get_polyline(origin_address:tuple[float,float], destination_address:tuple[fl
|
|
171 |
|
172 |
return all_polyline
|
173 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
174 |
# ********************** Optimization Function **********************
|
175 |
def plot_optimization(origin_address: str, destination_address: str, battery_capacity: float,
|
176 |
-
battery_initial: float,
|
177 |
-
|
|
|
178 |
|
179 |
-
def validate_inputs(origin_address, destination_address, battery_capacity, battery_initial,
|
|
|
180 |
errors = []
|
181 |
if origin_address == '':
|
182 |
errors.append("Origin address is required.")
|
183 |
if destination_address == '':
|
184 |
errors.append("Destination address is required.")
|
|
|
|
|
185 |
if battery_capacity <= 0:
|
186 |
errors.append("Battery capacity must be greater than 0.")
|
187 |
if battery_initial == 0:
|
188 |
errors.append("Battery initial state must be greater than 0.")
|
189 |
-
if
|
190 |
-
errors.append("Battery
|
191 |
-
if len(
|
192 |
errors.append("At least one charging port must be selected.")
|
|
|
|
|
193 |
|
194 |
if errors:
|
195 |
error_message = "Please correct the following errors:\n" + "\n".join(errors)
|
@@ -221,7 +259,8 @@ def plot_optimization(origin_address: str, destination_address: str, battery_cap
|
|
221 |
# Format the result as a string
|
222 |
return f"{total_hours} hours {remaining_minutes} minutes"
|
223 |
|
224 |
-
error = validate_inputs(origin_address, destination_address, battery_capacity, battery_initial,
|
|
|
225 |
if error is not None:
|
226 |
gr.Warning(error)
|
227 |
|
@@ -229,15 +268,23 @@ def plot_optimization(origin_address: str, destination_address: str, battery_cap
|
|
229 |
|
230 |
else:
|
231 |
|
232 |
-
|
233 |
-
for i in
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
|
242 |
try:
|
243 |
geocode_place(origin_address, gmaps, warning_text='Location Not Found. Please check your place name.')
|
@@ -245,9 +292,24 @@ def plot_optimization(origin_address: str, destination_address: str, battery_cap
|
|
245 |
except:
|
246 |
pass
|
247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
248 |
# get data
|
249 |
########################## data preprocessing ###########################
|
250 |
try:
|
|
|
251 |
solution_data = responce['solution data']
|
252 |
solution_detail = responce['solution detail']
|
253 |
solution_path = responce['solution path']
|
@@ -262,15 +324,18 @@ def plot_optimization(origin_address: str, destination_address: str, battery_cap
|
|
262 |
######################### plot map ###########################
|
263 |
icon_url = icons()
|
264 |
|
265 |
-
|
266 |
-
|
|
|
267 |
try:
|
268 |
directions_result = gmaps.directions(origin_address, destination_address, mode='driving')
|
269 |
except:
|
270 |
-
|
271 |
-
|
272 |
total_distance = directions_result[0]['legs'][0]['distance']['text']
|
273 |
total_duration = directions_result[0]['legs'][0]['duration']['text']
|
|
|
|
|
274 |
|
275 |
fmap = folium.Map(location=origin_address, tiles=None, zoom_start=13)
|
276 |
# add Openstreetmap layer
|
@@ -279,7 +344,7 @@ def plot_optimization(origin_address: str, destination_address: str, battery_cap
|
|
279 |
######################## plot start-stop location ###########################
|
280 |
addresses = [directions_result[0]['legs'][0]['start_address'], directions_result[0]['legs'][0]['end_address']]
|
281 |
locations = [origin_address, destination_address]
|
282 |
-
battery_state = [round(battery_initial, 1), round(
|
283 |
start_stop = ['start', 'stop']
|
284 |
icon_start_stop = ['house', 'flag']
|
285 |
|
@@ -337,8 +402,8 @@ def plot_optimization(origin_address: str, destination_address: str, battery_cap
|
|
337 |
|
338 |
html = f"""
|
339 |
<h3>{solution_detail[i]['Name']}</h3>
|
340 |
-
<p>Arival battery : {round(
|
341 |
-
<p>Target battery : {round(
|
342 |
<p>Charging time : {hours_to_hours_minutes(solution_data['charging time'][i])}</p>
|
343 |
<p>Address : {solution_detail[i]['Address']}</p>
|
344 |
<p>Coordinates : {solution_detail[i]['Coordinates']}</p>
|
@@ -364,61 +429,28 @@ def plot_optimization(origin_address: str, destination_address: str, battery_cap
|
|
364 |
|
365 |
if solution_path == ['START', 'STOP']:
|
366 |
gr.Warning('You can reach the destination with your current battery. There is no need to optimize.')
|
367 |
-
charging_time =
|
368 |
total_time = total_duration
|
369 |
elif solution_path != ['START', 'STOP'] and solution_data is not None:
|
370 |
charging_time = hours_to_hours_minutes(np.array(solution_data['charging time']).sum())
|
371 |
total_time = add_time_strings(charging_time, total_duration)
|
372 |
else:
|
373 |
-
charging_time =
|
374 |
total_time = total_duration
|
375 |
|
376 |
return fig, total_distance, total_duration, charging_time, total_time
|
377 |
-
|
378 |
-
# ********************** Utils Fucntion for Optimization **********************
|
379 |
-
def request_optimize(origin_address: str, destination_address: str, battery_capacity: float, battery_initial: float,
|
380 |
-
battery_arrival: float, charging_ports: str, method: str) -> dict:
|
381 |
-
|
382 |
-
optimizer_api_url = os.getenv('OPTIMIZER_API_URL')
|
383 |
-
headers = {
|
384 |
-
'Content-Type': 'application/json'
|
385 |
-
}
|
386 |
-
data = {
|
387 |
-
"origin_address": origin_address,
|
388 |
-
"destination_address": destination_address,
|
389 |
-
"battery_initial": battery_initial,
|
390 |
-
"battery_arrival": battery_arrival,
|
391 |
-
"battery_capacity": battery_capacity,
|
392 |
-
"charging_ports": charging_ports,
|
393 |
-
"reserve_batterry": 10,
|
394 |
-
"provider_filter": "PTT,PEA,EleX,Altervim,EA",
|
395 |
-
"method": method,
|
396 |
-
}
|
397 |
-
|
398 |
-
response = requests.post(optimizer_api_url, json=data, headers=headers)
|
399 |
-
|
400 |
-
if response.status_code == 200:
|
401 |
-
return response.json()
|
402 |
-
else:
|
403 |
-
return None
|
404 |
-
|
405 |
-
def hours_to_hours_minutes(time_in_hours):
|
406 |
-
# Extract whole hours
|
407 |
-
hours = int(time_in_hours)
|
408 |
-
# Compute remaining minutes
|
409 |
-
minutes = int((time_in_hours - hours) * 60)
|
410 |
-
return f"{hours} hours {minutes} minutes"
|
411 |
|
412 |
# ********************** Find all station near route **********************
|
413 |
def find_all_station_near_route(origin_address:str, destination_address:str, data:pd.DataFrame,
|
414 |
search_type:str, gmaps:googlemaps.Client, radius_km:int=1,
|
415 |
-
plotcircle_radius:str='Without Circle',
|
|
|
416 |
|
417 |
icon_url = icons()
|
418 |
|
419 |
if search_type == 'Place Name':
|
420 |
-
origin_address = geocode_place(origin_address, gmaps)
|
421 |
-
destination_address = geocode_place(destination_address, gmaps)
|
422 |
|
423 |
elif search_type == 'Coordinate':
|
424 |
origin_address = convert_string_to_tuple(origin_address)
|
@@ -567,7 +599,8 @@ def fetchdata(collection_name:str) -> pd.DataFrame:
|
|
567 |
data = clean_data(data)
|
568 |
return data
|
569 |
|
570 |
-
def plot_fmap_provider(data:pd.DataFrame, center:list[float,float], show_progress:bool=False,
|
|
|
571 |
#***************************** fmap1 for Provider Map *****************************
|
572 |
|
573 |
icon_url = icons()
|
@@ -625,7 +658,8 @@ def plot_fmap_provider(data:pd.DataFrame, center:list[float,float], show_progres
|
|
625 |
|
626 |
return fig1
|
627 |
|
628 |
-
def plot_fmap_chargetype(data:pd.DataFrame, center:list[float,float], show_progress:bool=False,
|
|
|
629 |
#***************************** fmap2 for Chage Type Map *****************************
|
630 |
icon_url = icons()
|
631 |
# create charge type feature groups
|
|
|
14 |
import os
|
15 |
import requests
|
16 |
import numpy as np
|
17 |
+
from geopy import distance
|
18 |
from typing import Any, Union
|
19 |
from dotenv import load_dotenv
|
20 |
|
|
|
146 |
except:
|
147 |
gr.Warning(f"'{input_string}' Worng Format. coordinate should be (lat, long). Please check your coordinate or try to use Place Name option instead.")
|
148 |
|
149 |
+
def geocode_place(place_name:str, gmaps:googlemaps.Client, warning_text:str) -> tuple[float,float]:
|
150 |
+
# Geocode the place name to get its latitude and longitude
|
151 |
+
geocode_result = gmaps.geocode(place_name)
|
|
|
152 |
|
153 |
+
if geocode_result:
|
154 |
+
location = geocode_result[0]['geometry']['location']
|
155 |
+
lat, lng = location['lat'], location['lng']
|
156 |
+
return tuple([lat, lng])
|
157 |
+
else:
|
|
|
|
|
|
|
158 |
gr.Warning(f"'{place_name}' {warning_text}")
|
159 |
+
return None
|
160 |
|
161 |
def get_polyline(origin_address:tuple[float,float], destination_address:tuple[float,float], gmaps:googlemaps.Client) -> list[float]:
|
162 |
directions_result = gmaps.directions(origin_address, destination_address, mode='driving')
|
|
|
169 |
|
170 |
return all_polyline
|
171 |
|
172 |
+
# ********************** Utils Fucntion for Optimization **********************
|
173 |
+
def request_optimize(origin_address: str, destination_address: str, battery_capacity: float, battery_initial: float,
|
174 |
+
battery_destination: float, reserve_battery: float, usable_battype: str, provider_filter:str) -> requests.Response:
|
175 |
+
|
176 |
+
optimizer_api_url = os.getenv('OPTIMIZER_API_URL')
|
177 |
+
headers = {
|
178 |
+
'Content-Type': 'application/json'
|
179 |
+
}
|
180 |
+
data = {
|
181 |
+
"origin_address": origin_address,
|
182 |
+
"destination_address": destination_address,
|
183 |
+
"usable_battype": usable_battype,
|
184 |
+
"provider_filter": provider_filter,
|
185 |
+
"battery_capacity": battery_capacity,
|
186 |
+
"battery_initial": battery_initial,
|
187 |
+
"battery_destination": battery_destination,
|
188 |
+
"reserve_battery": reserve_battery,
|
189 |
+
"epochs": 10,
|
190 |
+
"temperature": 10,
|
191 |
+
"top_k": 10,
|
192 |
+
"radius_km": 3.5
|
193 |
+
}
|
194 |
+
|
195 |
+
response = requests.post(optimizer_api_url, json=data, headers=headers)
|
196 |
+
|
197 |
+
return response
|
198 |
+
|
199 |
+
def hours_to_hours_minutes(time_in_hours):
|
200 |
+
# Extract whole hours
|
201 |
+
hours = int(time_in_hours)
|
202 |
+
# Compute remaining minutes
|
203 |
+
minutes = int((time_in_hours - hours) * 60)
|
204 |
+
return f"{hours} hours {minutes} minutes"
|
205 |
+
|
206 |
# ********************** Optimization Function **********************
|
207 |
def plot_optimization(origin_address: str, destination_address: str, battery_capacity: float,
|
208 |
+
battery_initial: float, battery_destination: float, reserve_battery: float,
|
209 |
+
usable_battype: list, provider_filter:list, gmaps:googlemaps.Client,
|
210 |
+
data:pd.DataFrame, progress:gr.Progress=gr.Progress()) -> tuple:
|
211 |
|
212 |
+
def validate_inputs(origin_address, destination_address, battery_capacity, battery_initial,
|
213 |
+
battery_destination, usable_battype, provider_filter):
|
214 |
errors = []
|
215 |
if origin_address == '':
|
216 |
errors.append("Origin address is required.")
|
217 |
if destination_address == '':
|
218 |
errors.append("Destination address is required.")
|
219 |
+
if origin_address == destination_address:
|
220 |
+
errors.append('Origin and destination address must be different.')
|
221 |
if battery_capacity <= 0:
|
222 |
errors.append("Battery capacity must be greater than 0.")
|
223 |
if battery_initial == 0:
|
224 |
errors.append("Battery initial state must be greater than 0.")
|
225 |
+
if battery_destination == 0:
|
226 |
+
errors.append("Battery destination state must be greater than 0.")
|
227 |
+
if len(usable_battype) == 0:
|
228 |
errors.append("At least one charging port must be selected.")
|
229 |
+
if len(provider_filter) == 0:
|
230 |
+
errors.append("At least one provider must be selected.")
|
231 |
|
232 |
if errors:
|
233 |
error_message = "Please correct the following errors:\n" + "\n".join(errors)
|
|
|
259 |
# Format the result as a string
|
260 |
return f"{total_hours} hours {remaining_minutes} minutes"
|
261 |
|
262 |
+
error = validate_inputs(origin_address, destination_address, battery_capacity, battery_initial,
|
263 |
+
battery_destination, usable_battype, provider_filter)
|
264 |
if error is not None:
|
265 |
gr.Warning(error)
|
266 |
|
|
|
268 |
|
269 |
else:
|
270 |
|
271 |
+
usable_battype_str = ''
|
272 |
+
for i in usable_battype:
|
273 |
+
usable_battype_str = usable_battype_str + i + ', '
|
274 |
+
usable_battype_str = usable_battype_str[:-2].replace(' ','')
|
275 |
+
|
276 |
+
provider_str = ''
|
277 |
+
for i in provider_filter:
|
278 |
+
provider_str = provider_str + i + ', '
|
279 |
+
provider_str = provider_str[:-2].replace(' ','')
|
280 |
+
|
281 |
+
responce = request_optimize(origin_address=origin_address, destination_address=destination_address,
|
282 |
+
battery_capacity=battery_capacity, battery_initial=battery_initial,
|
283 |
+
battery_destination=battery_destination, reserve_battery=reserve_battery,
|
284 |
+
usable_battype=usable_battype_str, provider_filter=provider_str)
|
285 |
+
|
286 |
+
if responce.status_code == 500:
|
287 |
+
gr.Warning('INTERNAL API SERVER ERROR. Please try again later or check your input.')
|
288 |
|
289 |
try:
|
290 |
geocode_place(origin_address, gmaps, warning_text='Location Not Found. Please check your place name.')
|
|
|
292 |
except:
|
293 |
pass
|
294 |
|
295 |
+
return None, None, None, None, None
|
296 |
+
|
297 |
+
if responce.status_code == 404:
|
298 |
+
origin_address_coordinate = geocode_place(origin_address, gmaps, warning_text='Location Not Found. Please check your place name.')
|
299 |
+
destination_address_coordinate = geocode_place(destination_address, gmaps, warning_text='Location Not Found. Please check your place name.')
|
300 |
+
distance_km = distance.distance(origin_address_coordinate, destination_address_coordinate).km
|
301 |
+
|
302 |
+
if battery_initial - (distance_km*0.2) >= battery_destination:
|
303 |
+
gr.Warning('Your battery initial state can reach your destination without charging.')
|
304 |
+
elif battery_initial - (distance_km*0.2) < battery_destination and origin_address_coordinate is not None and destination_address_coordinate is not None:
|
305 |
+
gr.Warning('Solution not found. Try to change your input with this suggestion. \n1.Try to increse battery initial state. \n2. Try to decrease battery destination state. \n3. Try to decrease reserve battery. \n4. Try to expand usable charging connectors. \n5. Try to expand provider filter.')
|
306 |
+
|
307 |
+
return None, None, None, None, None
|
308 |
+
|
309 |
# get data
|
310 |
########################## data preprocessing ###########################
|
311 |
try:
|
312 |
+
responce = responce.json()
|
313 |
solution_data = responce['solution data']
|
314 |
solution_detail = responce['solution detail']
|
315 |
solution_path = responce['solution path']
|
|
|
324 |
######################### plot map ###########################
|
325 |
icon_url = icons()
|
326 |
|
327 |
+
if solution_path is not None:
|
328 |
+
origin_address = geocode_place(origin_address, gmaps, 'Location Not Found. Please check your place name.')
|
329 |
+
destination_address = geocode_place(destination_address, gmaps, 'Location Not Found. Please check your place name.')
|
330 |
try:
|
331 |
directions_result = gmaps.directions(origin_address, destination_address, mode='driving')
|
332 |
except:
|
333 |
+
return None, None, None, None, None
|
334 |
+
|
335 |
total_distance = directions_result[0]['legs'][0]['distance']['text']
|
336 |
total_duration = directions_result[0]['legs'][0]['duration']['text']
|
337 |
+
if 'hours' not in total_duration:
|
338 |
+
total_duration = '0 hours ' + total_duration
|
339 |
|
340 |
fmap = folium.Map(location=origin_address, tiles=None, zoom_start=13)
|
341 |
# add Openstreetmap layer
|
|
|
344 |
######################## plot start-stop location ###########################
|
345 |
addresses = [directions_result[0]['legs'][0]['start_address'], directions_result[0]['legs'][0]['end_address']]
|
346 |
locations = [origin_address, destination_address]
|
347 |
+
battery_state = [round(battery_initial, 1), round(battery_destination, 1)]
|
348 |
start_stop = ['start', 'stop']
|
349 |
icon_start_stop = ['house', 'flag']
|
350 |
|
|
|
402 |
|
403 |
html = f"""
|
404 |
<h3>{solution_detail[i]['Name']}</h3>
|
405 |
+
<p>Arival battery : {round(solution_data['arrival battery'][i], 1)}</p>
|
406 |
+
<p>Target battery : {round(solution_data['target battery'][i], 1)}</p>
|
407 |
<p>Charging time : {hours_to_hours_minutes(solution_data['charging time'][i])}</p>
|
408 |
<p>Address : {solution_detail[i]['Address']}</p>
|
409 |
<p>Coordinates : {solution_detail[i]['Coordinates']}</p>
|
|
|
429 |
|
430 |
if solution_path == ['START', 'STOP']:
|
431 |
gr.Warning('You can reach the destination with your current battery. There is no need to optimize.')
|
432 |
+
charging_time = 'No charging time'
|
433 |
total_time = total_duration
|
434 |
elif solution_path != ['START', 'STOP'] and solution_data is not None:
|
435 |
charging_time = hours_to_hours_minutes(np.array(solution_data['charging time']).sum())
|
436 |
total_time = add_time_strings(charging_time, total_duration)
|
437 |
else:
|
438 |
+
charging_time = 'No charging time'
|
439 |
total_time = total_duration
|
440 |
|
441 |
return fig, total_distance, total_duration, charging_time, total_time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
442 |
|
443 |
# ********************** Find all station near route **********************
|
444 |
def find_all_station_near_route(origin_address:str, destination_address:str, data:pd.DataFrame,
|
445 |
search_type:str, gmaps:googlemaps.Client, radius_km:int=1,
|
446 |
+
plotcircle_radius:str='Without Circle',
|
447 |
+
progress:gr.Progress=gr.Progress()) -> branca.element.Figure:
|
448 |
|
449 |
icon_url = icons()
|
450 |
|
451 |
if search_type == 'Place Name':
|
452 |
+
origin_address = geocode_place(origin_address, gmaps, 'Location Not Found. Please check your place name or try to use Coordinate option instead.')
|
453 |
+
destination_address = geocode_place(destination_address, gmaps, 'Location Not Found. Please check your place name or try to use Coordinate option instead.')
|
454 |
|
455 |
elif search_type == 'Coordinate':
|
456 |
origin_address = convert_string_to_tuple(origin_address)
|
|
|
599 |
data = clean_data(data)
|
600 |
return data
|
601 |
|
602 |
+
def plot_fmap_provider(data:pd.DataFrame, center:list[float,float], show_progress:bool=False,
|
603 |
+
progress:gr.Progress=gr.Progress()) -> branca.element.Figure:
|
604 |
#***************************** fmap1 for Provider Map *****************************
|
605 |
|
606 |
icon_url = icons()
|
|
|
658 |
|
659 |
return fig1
|
660 |
|
661 |
+
def plot_fmap_chargetype(data:pd.DataFrame, center:list[float,float], show_progress:bool=False,
|
662 |
+
progress:gr.Progress=gr.Progress()) -> branca.element.Figure:
|
663 |
#***************************** fmap2 for Chage Type Map *****************************
|
664 |
icon_url = icons()
|
665 |
# create charge type feature groups
|