vincentiusyoshuac commited on
Commit
b1621cd
Β·
verified Β·
1 Parent(s): 7e41b66

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +102 -99
app.py CHANGED
@@ -120,22 +120,106 @@ def optimize_route(distances: np.ndarray) -> List[int]:
120
 
121
  return tour
122
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
123
  def main():
124
  st.set_page_config(page_title="AI Travel Route Optimizer", layout="wide")
125
-
126
  st.title("🌍 AI Travel Route Optimizer")
127
  st.markdown("""
128
  This app helps you find the optimal route between multiple destinations using real driving distances.
129
  Enter your destinations in the sidebar and get a customized route with turn-by-turn directions.
130
  """)
131
-
132
  # Sidebar for inputs
133
  with st.sidebar:
134
  st.header("πŸ“ Destinations")
135
-
136
- # Input for places
137
  num_places = st.number_input("Number of destinations", min_value=2, max_value=10, value=3)
138
-
139
  places = []
140
  for i in range(num_places):
141
  place = st.text_input(f"Destination {i+1}")
@@ -147,11 +231,10 @@ def main():
147
  st.success(f"βœ“ Found coordinates for {place}")
148
  else:
149
  st.error(f"❌ Couldn't find coordinates for {place}")
150
-
151
  # Main content area
152
- if len(places) == num_places and num_places >= 2:
153
  col1, col2 = st.columns([2, 1])
154
-
155
  with col1:
156
  with st.spinner("πŸš— Calculating optimal route..."):
157
  # Calculate real distances
@@ -160,100 +243,20 @@ def main():
160
  # Get optimized route order
161
  optimal_order = optimize_route(distances)
162
 
163
- # Create map
164
- center_lat = sum(coord[0] for _, coord in places) / len(places)
165
- center_lon = sum(coord[1] for _, coord in places) / len(places)
166
- m = folium.Map(location=[center_lat, center_lon], zoom_start=4)
167
-
168
- # Add markers and route lines
169
- total_distance = 0
170
- total_duration = 0
171
-
172
- for i in range(len(optimal_order)):
173
- current_idx = optimal_order[i]
174
- next_idx = optimal_order[(i + 1) % len(optimal_order)]
175
-
176
- current_place, (lat, lon) = places[current_idx]
177
- segment_info = routing_info.get((current_idx, next_idx), {})
178
-
179
- # Add marker
180
- popup_content = f"""
181
- <b>Stop {i+1}: {current_place}</b><br>
182
- """
183
- if i < len(optimal_order) - 1:
184
- popup_content += f"""
185
- To next stop:<br>
186
- Distance: {segment_info.get('distance_km', 'N/A')}<br>
187
- Duration: {segment_info.get('duration_mins', 'N/A')}
188
- """
189
-
190
- folium.Marker(
191
- [lat, lon],
192
- popup=folium.Popup(popup_content, max_width=300),
193
- icon=create_numbered_marker(i+1)
194
- ).add_to(m)
195
-
196
- # Draw route line
197
- if i < len(optimal_order) - 1:
198
- if 'geometry' in segment_info:
199
- try:
200
- route_coords = polyline.decode(segment_info['geometry'])
201
- folium.PolyLine(
202
- route_coords,
203
- weight=2,
204
- color='blue',
205
- opacity=0.8
206
- ).add_to(m)
207
- except Exception as e:
208
- st.warning(f"Error drawing route: {str(e)}")
209
- next_place = places[next_idx][1]
210
- folium.PolyLine(
211
- [[lat, lon], [next_place[0], next_place[1]]],
212
- weight=2,
213
- color='red',
214
- opacity=0.8
215
- ).add_to(m)
216
-
217
- # Add to totals
218
- if 'distance_km' in segment_info:
219
- total_distance += float(segment_info['distance_km'].split()[0])
220
- if 'duration_mins' in segment_info:
221
- total_duration += float(segment_info['duration_mins'].split()[0])
222
-
223
- # Display map
224
  st.components.v1.html(m._repr_html_(), height=600)
225
-
226
  with col2:
227
- st.header("πŸ“ Optimized Itinerary")
228
-
229
- # Display summary first
230
- st.markdown("### πŸ“Š Summary")
231
- st.info(f"""
232
- πŸ›£οΈ Total distance: **{total_distance:.1f} km**
233
- ⏱️ Total duration: **{total_duration:.0f} mins** ({total_duration/60:.1f} hours)
234
- """)
235
-
236
- st.markdown("### πŸ—ΊοΈ Route Details")
237
- for i in range(len(optimal_order)):
238
- current_idx = optimal_order[i]
239
- next_idx = optimal_order[(i + 1) % len(optimal_order)]
240
-
241
- current_place = places[current_idx][0]
242
- segment_info = routing_info.get((current_idx, next_idx), {})
243
-
244
- st.markdown(f"**Stop {i+1}: {current_place}**")
245
-
246
- if i < len(optimal_order) - 1:
247
- st.markdown(f"↓ *{segment_info.get('distance_km', 'N/A')}, "
248
- f"Duration: {segment_info.get('duration_mins', 'N/A')}*")
249
-
250
- if 'steps' in segment_info:
251
- with st.expander("πŸ“ Turn-by-turn directions"):
252
- instructions = format_instructions(segment_info['steps'])
253
- for idx, instruction in enumerate(instructions, 1):
254
- st.write(f"{idx}. {instruction}")
255
  else:
256
- st.info("πŸ‘ˆ Please enter all destinations in the sidebar to get started")
257
 
258
  if __name__ == "__main__":
259
  main()
 
120
 
121
  return tour
122
 
123
+ def add_markers_and_route(m: folium.Map, places: List[Tuple[str, Tuple[float, float]]], optimal_order: List[int], routing_info: Dict):
124
+ """Add markers and route lines to the map"""
125
+ total_distance = 0
126
+ total_duration = 0
127
+
128
+ for i in range(len(optimal_order)):
129
+ current_idx = optimal_order[i]
130
+ next_idx = optimal_order[(i + 1) % len(optimal_order)]
131
+
132
+ current_place, (lat, lon) = places[current_idx]
133
+ segment_info = routing_info.get((current_idx, next_idx), {})
134
+
135
+ # Add marker
136
+ popup_content = f"""
137
+ <b>Stop {i+1}: {current_place}</b><br>
138
+ """
139
+ if i < len(optimal_order) - 1:
140
+ popup_content += f"""
141
+ To next stop:<br>
142
+ Distance: {segment_info.get('distance_km', 'N/A')}<br>
143
+ Duration: {segment_info.get('duration_mins', 'N/A')}
144
+ """
145
+
146
+ folium.Marker(
147
+ [lat, lon],
148
+ popup=folium.Popup(popup_content, max_width=300),
149
+ icon=create_numbered_marker(i+1)
150
+ ).add_to(m)
151
+
152
+ # Draw route line
153
+ if i < len(optimal_order) - 1:
154
+ if 'geometry' in segment_info:
155
+ try:
156
+ route_coords = polyline.decode(segment_info['geometry'])
157
+ folium.PolyLine(
158
+ route_coords,
159
+ weight=2,
160
+ color='blue',
161
+ opacity=0.8
162
+ ).add_to(m)
163
+ except Exception as e:
164
+ st.warning(f"Error drawing route: {str(e)}")
165
+ next_place = places[next_idx][1]
166
+ folium.PolyLine(
167
+ [[lat, lon], [next_place[0], next_place[1]]],
168
+ weight=2,
169
+ color='red',
170
+ opacity=0.8
171
+ ).add_to(m)
172
+
173
+ # Add to totals
174
+ if 'distance_km' in segment_info:
175
+ total_distance += float(segment_info['distance_km'].split()[0])
176
+ if 'duration_mins' in segment_info:
177
+ total_duration += float(segment_info['duration_mins'].split()[0])
178
+
179
+ return total_distance, total_duration
180
+
181
+ def display_itinerary_summary(places: List[Tuple[str, Tuple[float, float]]], optimal_order: List[int], routing_info: Dict):
182
+ """Display the optimized itinerary summary"""
183
+ # Display summary first
184
+ st.markdown("### πŸ“Š Summary")
185
+ total_distance, total_duration = add_markers_and_route(folium.Map(), places, optimal_order, routing_info)
186
+ st.info(f"""
187
+ πŸ›£οΈ Total distance: **{total_distance:.1f} km**
188
+ ⏱️ Total duration: **{total_duration:.0f} mins** ({total_duration/60:.1f} hours)
189
+ """)
190
+
191
+ st.markdown("### πŸ—ΊοΈ Route Details")
192
+ for i in range(len(optimal_order)):
193
+ current_idx = optimal_order[i]
194
+ next_idx = optimal_order[(i + 1) % len(optimal_order)]
195
+
196
+ current_place = places[current_idx][0]
197
+ segment_info = routing_info.get((current_idx, next_idx), {})
198
+
199
+ st.markdown(f"**Stop {i+1}: {current_place}**")
200
+
201
+ if i < len(optimal_order) - 1:
202
+ st.markdown(f"↓ *{segment_info.get('distance_km', 'N/A')}, "
203
+ f"Duration: {segment_info.get('duration_mins', 'N/A')}*")
204
+
205
+ if 'steps' in segment_info:
206
+ with st.expander("πŸ“ Turn-by-turn directions"):
207
+ instructions = format_instructions(segment_info['steps'])
208
+ for idx, instruction in enumerate(instructions, 1):
209
+ st.write(f"{idx}. {instruction}")
210
+
211
  def main():
212
  st.set_page_config(page_title="AI Travel Route Optimizer", layout="wide")
 
213
  st.title("🌍 AI Travel Route Optimizer")
214
  st.markdown("""
215
  This app helps you find the optimal route between multiple destinations using real driving distances.
216
  Enter your destinations in the sidebar and get a customized route with turn-by-turn directions.
217
  """)
218
+
219
  # Sidebar for inputs
220
  with st.sidebar:
221
  st.header("πŸ“ Destinations")
 
 
222
  num_places = st.number_input("Number of destinations", min_value=2, max_value=10, value=3)
 
223
  places = []
224
  for i in range(num_places):
225
  place = st.text_input(f"Destination {i+1}")
 
231
  st.success(f"βœ“ Found coordinates for {place}")
232
  else:
233
  st.error(f"❌ Couldn't find coordinates for {place}")
234
+
235
  # Main content area
236
+ if len(places) >= 2:
237
  col1, col2 = st.columns([2, 1])
 
238
  with col1:
239
  with st.spinner("πŸš— Calculating optimal route..."):
240
  # Calculate real distances
 
243
  # Get optimized route order
244
  optimal_order = optimize_route(distances)
245
 
246
+ # Update the route if the user changes the input
247
+ if st.button("Recalculate Route"):
248
+ distances, routing_info = calculate_real_distances(places)
249
+ optimal_order = optimize_route(distances)
250
+
251
+ # Create map and display
252
+ m = folium.Map()
253
+ total_distance, total_duration = add_markers_and_route(m, places, optimal_order, routing_info)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  st.components.v1.html(m._repr_html_(), height=600)
255
+
256
  with col2:
257
+ display_itinerary_summary(places, optimal_order, routing_info)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  else:
259
+ st.info("πŸ‘ˆ Please enter at least 2 destinations in the sidebar to get started")
260
 
261
  if __name__ == "__main__":
262
  main()