diff --git a/ai-models/fare_estimation.py b/ai-models/fare_estimation.py
index 162420b..c1ebedb 100644
--- a/ai-models/fare_estimation.py
+++ b/ai-models/fare_estimation.py
@@ -1,85 +1,192 @@
-import streamlit as st
-import folium
-from streamlit_folium import st_folium
-import random
-
-# Sample metro stations with coordinates
-stations = {
- "Wardha Junction": [20.738, 78.601],
- "Indira Chowk": [20.742, 78.623],
- "Mahatma Nagar": [20.753, 78.634],
- "Wardha Bazaar": [20.756, 78.61],
- "IT Park": [20.77, 78.645]
-}
-
-station_list = list(stations.keys())
-
-# Fare calculation logic
-def calculate_fare(start, end):
- distance = abs(station_list.index(start) - station_list.index(end))
- if distance == 0:
- return 0, 0, 0
- base_fare = 10
- extra_fare = 5 * (distance - 1)
- total = base_fare + extra_fare
- return total, base_fare, extra_fare
-
-# Travel time estimation
-def estimate_time(start, end):
- distance = abs(station_list.index(start) - station_list.index(end))
- return distance * 2 # assume 2 minutes per station
-
-# Crowd level generator
-def crowd_level():
- levels = ["Low π’", "Moderate π‘", "High π΄"]
- return random.choice(levels)
-
-# Streamlit UI
-st.set_page_config(page_title="WardhaMetroFlow - Fare Estimator", layout="wide")
-st.title("π° Wardha Metro Fare Estimator")
-
-col1, col2 = st.columns(2)
-with col1:
- start_station = st.selectbox("Select Start Station", station_list)
-with col2:
- end_station = st.selectbox("Select Destination Station", station_list)
-
-if start_station and end_station:
- total_fare, base_fare, extra_fare = calculate_fare(start_station, end_station)
- time_estimate = estimate_time(start_station, end_station)
-
- # Display results
- st.success(f"**Route:** {start_station} β {end_station}")
- st.info(f"π Stations covered: {abs(station_list.index(start_station) - station_list.index(end_station)) + 1}")
- st.success(f"π° Fare: βΉ{total_fare} (Base βΉ{base_fare} + Extra βΉ{extra_fare})")
- st.warning(f"β± Estimated Travel Time: {time_estimate} minutes")
- st.error(f"π¦ Current Crowd Level: {crowd_level()}")
-
- # Intermediate stations
- idx_start = station_list.index(start_station)
- idx_end = station_list.index(end_station)
- if idx_start < idx_end:
- route_stations = station_list[idx_start:idx_end+1]
- else:
- route_stations = station_list[idx_end:idx_start+1][::-1]
-
- st.markdown("### π Intermediate Stations on this Route:")
- st.write(" β ".join(route_stations))
-
- # Show map
- m = folium.Map(location=[20.75, 78.62], zoom_start=13, tiles="CartoDB Positron")
-
- # Add all stations
- for station, coords in stations.items():
- color = "blue"
- if station == start_station:
- color = "green"
- elif station == end_station:
- color = "red"
- folium.Marker(coords, tooltip=station, icon=folium.Icon(color=color, icon="train")).add_to(m)
-
- # Highlight route path
- route_coords = [stations[s] for s in route_stations]
- folium.PolyLine(route_coords, color="purple", weight=5).add_to(m)
-
- st_folium(m, width=750, height=500)
+import streamlit as st
+import folium
+from streamlit_folium import st_folium
+import pickle
+import pandas as pd
+from datetime import datetime
+
+# Sample metro stations with coordinates
+stations = {
+ "Wardha Junction": [20.738, 78.601],
+ "Indira Chowk": [20.742, 78.623],
+ "Mahatma Nagar": [20.753, 78.634],
+ "Wardha Bazaar": [20.756, 78.61],
+ "IT Park": [20.77, 78.645]
+}
+station_list = list(stations.keys())
+
+# Load ML model with caching
+@st.cache_resource
+def load_model():
+ try:
+ with open('passenger_flow_model.pkl', 'rb') as f:
+ model = pickle.load(f)
+ return model
+ except FileNotFoundError:
+ return None
+
+# Fare calculation logic
+def calculate_fare(start, end):
+ distance = abs(station_list.index(start) - station_list.index(end))
+ if distance == 0:
+ return 0, 0, 0
+ base_fare = 10
+ extra_fare = 5 * (distance - 1)
+ total = base_fare + extra_fare
+ return total, base_fare, extra_fare
+
+# Travel time estimation
+def estimate_time(start, end):
+ distance = abs(station_list.index(start) - station_list.index(end))
+ return distance * 2 # assume 2 minutes per station
+
+# ML-based crowd prediction
+def predict_crowd_level(model, station_name, hour, day_of_week):
+ """
+ Predict crowd level using ML model
+
+ Args:
+ model: Trained RandomForestRegressor
+ station_name: Name of the station
+ hour: Hour of day (0-23)
+ day_of_week: Day (0=Monday, 6=Sunday)
+
+ Returns:
+ tuple: (crowd_label, passenger_count)
+ """
+ if model is None:
+ # Fallback to time-based logic if model not available
+ if hour in range(7, 10) or hour in range(17, 20): # Peak hours
+ return "High π΄", 450
+ elif hour in range(10, 17): # Moderate hours
+ return "Moderate π‘", 250
+ else: # Off-peak
+ return "Low π’", 100
+
+ try:
+ # Create feature dataframe matching model training format
+ # Adjust features based on your actual model training
+ station_idx = station_list.index(station_name)
+
+ features = pd.DataFrame({
+ 'hour': [hour],
+ 'day_of_week': [day_of_week],
+ 'station_id': [station_idx],
+ 'is_weekend': [1 if day_of_week >= 5 else 0],
+ 'is_peak_hour': [1 if hour in range(7, 10) or hour in range(17, 20) else 0]
+ })
+
+ # Predict passenger count
+ passenger_count = int(model.predict(features)[0])
+
+ # Convert to crowd level
+ if passenger_count < 150:
+ crowd_label = "Low π’"
+ elif passenger_count < 300:
+ crowd_label = "Moderate π‘"
+ else:
+ crowd_label = "High π΄"
+
+ return crowd_label, passenger_count
+
+ except Exception as e:
+ st.error(f"Prediction error: {str(e)}")
+ return "Unknown βͺ", 0
+
+# Streamlit UI
+st.set_page_config(page_title="WardhaMetroFlow - Fare Estimator", layout="wide")
+st.title("π° Wardha Metro Fare Estimator")
+
+# Load model
+model = load_model()
+if model is None:
+ st.warning("β οΈ ML model not found. Using time-based crowd estimation as fallback.")
+
+# Time and day selection
+st.sidebar.header("π Travel Time Settings")
+current_hour = datetime.now().hour
+selected_hour = st.sidebar.slider("Select Hour of Day", 0, 23, current_hour,
+ help="Choose travel time (24-hour format)")
+days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
+current_day = datetime.now().weekday()
+selected_day = st.sidebar.selectbox("Select Day of Week", days, index=current_day)
+day_of_week = days.index(selected_day)
+
+# Display selected time
+st.sidebar.info(f"π
{selected_day}, {selected_hour}:00")
+
+# Station selection
+col1, col2 = st.columns(2)
+with col1:
+ start_station = st.selectbox("Select Start Station", station_list)
+with col2:
+ end_station = st.selectbox("Select Destination Station", station_list)
+
+if start_station and end_station:
+ total_fare, base_fare, extra_fare = calculate_fare(start_station, end_station)
+ time_estimate = estimate_time(start_station, end_station)
+
+ # Get crowd predictions for both stations
+ start_crowd, start_passengers = predict_crowd_level(model, start_station, selected_hour, day_of_week)
+ end_crowd, end_passengers = predict_crowd_level(model, end_station, selected_hour, day_of_week)
+
+ # Display results
+ st.success(f"**Route:** {start_station} β {end_station}")
+ st.info(f"π Stations covered: {abs(station_list.index(start_station) - station_list.index(end_station)) + 1}")
+ st.success(f"π° Fare: βΉ{total_fare} (Base βΉ{base_fare} + Extra βΉ{extra_fare})")
+ st.warning(f"β± Estimated Travel Time: {time_estimate} minutes")
+
+ # Display crowd predictions with metrics
+ st.markdown("### π¦ Real-Time Crowd Predictions")
+ col_crowd1, col_crowd2 = st.columns(2)
+
+ with col_crowd1:
+ st.metric(
+ label=f"π {start_station}",
+ value=start_crowd,
+ delta=f"{start_passengers} passengers"
+ )
+
+ with col_crowd2:
+ st.metric(
+ label=f"π {end_station}",
+ value=end_crowd,
+ delta=f"{end_passengers} passengers"
+ )
+
+ # Intermediate stations
+ idx_start = station_list.index(start_station)
+ idx_end = station_list.index(end_station)
+ if idx_start < idx_end:
+ route_stations = station_list[idx_start:idx_end+1]
+ else:
+ route_stations = station_list[idx_end:idx_start+1][::-1]
+
+ st.markdown("### π Intermediate Stations on this Route:")
+ st.write(" β ".join(route_stations))
+
+ # Show map
+ m = folium.Map(location=[20.75, 78.62], zoom_start=13, tiles="CartoDB Positron")
+
+ # Add all stations
+ for station, coords in stations.items():
+ color = "blue"
+ if station == start_station:
+ color = "green"
+ elif station == end_station:
+ color = "red"
+ folium.Marker(coords, tooltip=station, icon=folium.Icon(color=color, icon="train")).add_to(m)
+
+ # Highlight route path
+ route_coords = [stations[s] for s in route_stations]
+ folium.PolyLine(route_coords, color="purple", weight=5).add_to(m)
+
+ st_folium(m, width=750, height=500)
+
+# Footer with info
+st.markdown("---")
+st.markdown("**π Powered by Machine Learning** | Predictions based on historical passenger flow data")
+if model:
+ st.success("β
ML Model Active: Using RandomForestRegressor for accurate crowd predictions")
+else:
+ st.info("βΉοΈ Using time-based heuristics for crowd estimation")
\ No newline at end of file
diff --git a/ai-models/wardha_passenger_view.py b/ai-models/wardha_passenger_view.py
index 0db2885..438cc5f 100644
--- a/ai-models/wardha_passenger_view.py
+++ b/ai-models/wardha_passenger_view.py
@@ -1,187 +1,226 @@
-
-
-import streamlit as st
-import pandas as pd
-import numpy as np
-import networkx as nx
-import folium
-from streamlit_folium import st_folium
-from folium.plugins import HeatMap, AntPath
-
-st.set_page_config(page_title="WardhaMetroFlow - Passenger Route Planner", layout="wide")
-
-# --- Sidebar Navigation ---
-st.sidebar.title("π Navigation")
-page = st.sidebar.radio("Go to:", ["About", "Passenger Route Planner"])
-
-# =========================
-# ABOUT PAGE
-# =========================
-if page == "About":
- st.title("βΉοΈ About WardhaMetroFlow")
- st.markdown("""
- ## π Welcome to WardhaMetroFlow
-
- **WardhaMetroFlow** is an AI-powered metro simulation designed for **Wardha city**, built to showcase how **smart transit systems**
- can improve daily commuting and city transport management.
-
- ### π Key Features
- 1. **Passenger View**
- - Plan metro routes between any two stations
- - Get **real-time congestion-aware suggestions**
- - View **estimated travel time**
- - Explore an **interactive metro map** with congestion heatmaps and station info
- - Watch a **live simulation** of your route π¬
-
- 2. **Admin View** *(future scope)*
- - Monitor traffic flow across the network
- - Manage stations and track congestion
- - Analyze predictive AI trends for future capacity planning
-
- 3. **Congestion Heatmap**
- - Color-coded visualization of congestion across all stations
- - Helps both passengers and admins make better decisions
-
- ### π§ How to Use This App
- - Use the **sidebar navigation** to switch between sections.
- - In **Passenger Route Planner**:
- - Select a **Start Station** and **Destination Station**
- - See the **optimal route** and estimated travel time
- - Check congestion levels at each station along the way
- - Explore the **interactive metro map**
- - Run the **live simulation** to see how your journey progresses
-
- ### π― Vision
- WardhaMetroFlow envisions **smarter, AI-driven public transit systems** for emerging smart cities like Wardha.
- Itβs a step toward building efficient, reliable, and commuter-friendly metro systems.
-
- ---
- """)
-
-# =========================
-# PASSENGER ROUTE PLANNER
-# =========================
-elif page == "Passenger Route Planner":
- st.title("π Passenger Route Planner")
- st.markdown("Plan your journey with **smart AI suggestions**, explore the **metro map**, and even watch a **live simulation** of your route.")
-
- # --- Metro Stations ---
- stations = {
- "Wardha Junction": [20.7453, 78.6022],
- "Civil Lines": [20.7458, 78.6101],
- "Ram Nagar": [20.7502, 78.6187],
- "Mahatma Nagar": [20.7408, 78.6202],
- "Industrial Area": [20.7351, 78.6155],
- }
-
- # --- Simulated congestion data ---
- if "congestion" not in st.session_state:
- np.random.seed(None)
- st.session_state["congestion"] = {s: np.random.randint(10, 100) for s in stations.keys()}
-
- congestion_levels = st.session_state["congestion"]
-
- # --- Create metro network graph ---
- G = nx.Graph()
- G.add_edges_from([
- ("Wardha Junction", "Civil Lines", {"distance": 2}),
- ("Civil Lines", "Ram Nagar", {"distance": 2}),
- ("Ram Nagar", "Mahatma Nagar", {"distance": 3}),
- ("Civil Lines", "Industrial Area", {"distance": 4}),
- ("Industrial Area", "Mahatma Nagar", {"distance": 3}),
- ])
-
- # --- Passenger Input ---
- start = st.selectbox("π’ Start Station", list(stations.keys()))
- end = st.selectbox("π΄ Destination Station", list(stations.keys()))
-
- if start and end and start != end:
- # Shortest path using distance
- path = nx.shortest_path(G, source=start, target=end, weight="distance")
- distance = nx.shortest_path_length(G, source=start, target=end, weight="distance")
-
- # Estimate travel time
- avg_congestion = np.mean([congestion_levels[stn] for stn in path])
- travel_time = distance * 2 + avg_congestion * 0.05 # minutes
-
- # Show route info
- st.success(f"π Best Route: {' β '.join(path)}")
- st.info(f"π Estimated Travel Time: {travel_time:.1f} minutes")
-
- # Smart Suggestion
- if avg_congestion > 70:
- st.warning("β οΈ High congestion detected. Consider leaving 10β15 mins earlier.")
- elif avg_congestion < 40:
- st.success("β
Smooth journey ahead! Congestion is low.")
-
- # Show congestion levels along the route
- route_data = pd.DataFrame({
- "Station": path,
- "Congestion (%)": [congestion_levels[stn] for stn in path]
- })
- st.subheader("π Congestion along your route")
- st.dataframe(route_data.style.background_gradient(cmap="RdYlGn_r"))
-
- # =========================
- # ENHANCED MAP VISUALIZATION
- # =========================
- st.subheader("πΊοΈ Interactive Route Map")
-
- # Focus map on midpoint of route
- route_coords = [stations[stn] for stn in path]
- mid_lat = np.mean([lat for lat, lon in route_coords])
- mid_lon = np.mean([lon for lat, lon in route_coords])
- m = folium.Map(location=[mid_lat, mid_lon], zoom_start=15, tiles="OpenStreetMap")
-
- # Add heatmap layer for congestion
- heat_data = [[stations[s][0], stations[s][1], congestion_levels[s]] for s in stations]
- HeatMap(heat_data, min_opacity=0.4, radius=25, blur=15).add_to(m)
-
- # Add stations with metro icons + popup cards
- for stn, coords in stations.items():
- level = congestion_levels[stn]
- color = "green" if level < 40 else "orange" if level < 70 else "red"
-
- popup_html = f"""
- {stn}
- π¦ Congestion: {level}%
- π Lat: {coords[0]}, Lon: {coords[1]}
- """
- folium.Marker(
- location=coords,
- popup=popup_html,
- icon=folium.Icon(color=color, icon="train", prefix="fa")
- ).add_to(m)
-
- # Add route polyline with color-coded congestion
- for i in range(len(path) - 1):
- seg = [stations[path[i]], stations[path[i+1]]]
- seg_congestion = (congestion_levels[path[i]] + congestion_levels[path[i+1]]) / 2
- seg_color = "green" if seg_congestion < 40 else "orange" if seg_congestion < 70 else "red"
-
- folium.PolyLine(
- locations=seg,
- color=seg_color,
- weight=6,
- opacity=0.8,
- tooltip=f"{path[i]} β {path[i+1]} (Cong: {seg_congestion:.1f}%)"
- ).add_to(m)
-
- # =========================
- # LIVE SIMULATION FEATURE
- # =========================
- st.subheader("π¬ Live Simulation of Your Route")
-
- # AntPath creates animated moving dashes
- AntPath(
- locations=route_coords,
- color="blue",
- weight=6,
- delay=800,
- dash_array=[10, 20]
- ).add_to(m)
-
- st_folium(m, width=800, height=550)
-
- elif start == end:
- st.warning("β οΈ Start and Destination stations must be different.")
+import streamlit as st
+import pandas as pd
+import numpy as np
+import networkx as nx
+import folium
+from streamlit_folium import st_folium
+from folium.plugins import HeatMap, AntPath
+
+st.set_page_config(page_title="WardhaMetroFlow - Passenger Route Planner", layout="wide")
+
+# --- Sidebar Navigation ---
+st.sidebar.title("π Navigation")
+page = st.sidebar.radio("Go to:", ["About", "Passenger Route Planner"])
+
+# =========================
+# ABOUT PAGE
+# =========================
+if page == "About":
+ st.title("βΉοΈ About WardhaMetroFlow")
+ st.markdown("""
+ ## π Welcome to WardhaMetroFlow
+
+ **WardhaMetroFlow** is an AI-powered metro simulation designed for **Wardha city**, built to showcase how **smart transit systems**
+ can improve daily commuting and city transport management.
+
+ ### π Key Features
+ 1. **Passenger View**
+ - Plan metro routes between any two stations
+ - Get **real-time congestion-aware suggestions**
+ - View **estimated travel time**
+ - Explore an **interactive metro map** with congestion heatmaps and station info
+ - Watch a **live simulation** of your route π¬
+
+ 2. **Admin View** *(future scope)*
+ - Monitor traffic flow across the network
+ - Manage stations and track congestion
+ - Analyze predictive AI trends for future capacity planning
+
+ 3. **Congestion Heatmap**
+ - Color-coded visualization of congestion across all stations
+ - Helps both passengers and admins make better decisions
+
+ ### π§ How to Use This App
+ - Use the **sidebar navigation** to switch between sections.
+ - In **Passenger Route Planner**:
+ - Select a **Start Station** and **Destination Station**
+ - See the **optimal route** and estimated travel time
+ - Check congestion levels at each station along the way
+ - Explore the **interactive metro map**
+ - Run the **live simulation** to see how your journey progresses
+
+ ### π― Vision
+ WardhaMetroFlow envisions **smarter, AI-driven public transit systems** for emerging smart cities like Wardha.
+ It's a step toward building efficient, reliable, and commuter-friendly metro systems.
+
+ ---
+ """)
+
+# =========================
+# PASSENGER ROUTE PLANNER
+# =========================
+elif page == "Passenger Route Planner":
+ st.title("π Passenger Route Planner")
+ st.markdown("Plan your journey with **smart AI suggestions**, explore the **metro map**, and even watch a **live simulation** of your route.")
+
+ # --- Metro Stations ---
+ stations = {
+ "Wardha Junction": [20.7453, 78.6022],
+ "Civil Lines": [20.7458, 78.6101],
+ "Ram Nagar": [20.7502, 78.6187],
+ "Mahatma Nagar": [20.7408, 78.6202],
+ "Industrial Area": [20.7351, 78.6155],
+ }
+
+ # --- Simulated congestion data ---
+ # Fixed: Removed np.random.seed(None) as it's redundant
+ if "congestion" not in st.session_state:
+ st.session_state["congestion"] = {s: np.random.randint(10, 100) for s in stations.keys()}
+
+ congestion_levels = st.session_state["congestion"]
+
+ # --- Create metro network graph ---
+ G = nx.Graph()
+ G.add_edges_from([
+ ("Wardha Junction", "Civil Lines", {"distance": 2}),
+ ("Civil Lines", "Ram Nagar", {"distance": 2}),
+ ("Ram Nagar", "Mahatma Nagar", {"distance": 3}),
+ ("Civil Lines", "Industrial Area", {"distance": 4}),
+ ("Industrial Area", "Mahatma Nagar", {"distance": 3}),
+ ])
+
+ # --- Network Connectivity Check (Optional Enhancement) ---
+ # Display network status in sidebar
+ is_connected = nx.is_connected(G)
+ if is_connected:
+ st.sidebar.success("π’ Metro Network: Fully Connected")
+ else:
+ st.sidebar.warning("π‘ Metro Network: Some stations may not be reachable")
+
+ # --- Passenger Input ---
+ start = st.selectbox("π’ Start Station", list(stations.keys()))
+ end = st.selectbox("π΄ Destination Station", list(stations.keys()))
+
+ if start and end and start != end:
+ # === CRITICAL FIX: Added Error Handling ===
+ try:
+ # Shortest path using distance
+ path = nx.shortest_path(G, source=start, target=end, weight="distance")
+ distance = nx.shortest_path_length(G, source=start, target=end, weight="distance")
+
+ # Estimate travel time
+ # Formula: base_time (2 min/km) + congestion_delay (5% of congestion level)
+ avg_congestion = np.mean([congestion_levels[stn] for stn in path])
+ travel_time = distance * 2 + avg_congestion * 0.05 # minutes
+
+ # Show route info
+ st.success(f"π Best Route: {' β '.join(path)}")
+ st.info(f"π Estimated Travel Time: {travel_time:.1f} minutes")
+
+ # Smart Suggestion
+ if avg_congestion > 70:
+ st.warning("β οΈ High congestion detected. Consider leaving 10β15 mins earlier.")
+ elif avg_congestion < 40:
+ st.success("β
Smooth journey ahead! Congestion is low.")
+
+ # Show congestion levels along the route
+ route_data = pd.DataFrame({
+ "Station": path,
+ "Congestion (%)": [congestion_levels[stn] for stn in path]
+ })
+ st.subheader("π Congestion along your route")
+ st.dataframe(route_data.style.background_gradient(cmap="RdYlGn_r"))
+
+ # =========================
+ # ENHANCED MAP VISUALIZATION
+ # =========================
+ st.subheader("πΊοΈ Interactive Route Map")
+
+ # Focus map on midpoint of route
+ route_coords = [stations[stn] for stn in path]
+ mid_lat = np.mean([lat for lat, lon in route_coords])
+ mid_lon = np.mean([lon for lat, lon in route_coords])
+ m = folium.Map(location=[mid_lat, mid_lon], zoom_start=15, tiles="OpenStreetMap")
+
+ # Add heatmap layer for congestion
+ heat_data = [[stations[s][0], stations[s][1], congestion_levels[s]] for s in stations]
+ HeatMap(heat_data, min_opacity=0.4, radius=25, blur=15).add_to(m)
+
+ # Add stations with metro icons + popup cards
+ for stn, coords in stations.items():
+ level = congestion_levels[stn]
+ color = "green" if level < 40 else "orange" if level < 70 else "red"
+
+ popup_html = f"""
+ {stn}
+ π¦ Congestion: {level}%
+ π Lat: {coords[0]}, Lon: {coords[1]}
+ """
+ folium.Marker(
+ location=coords,
+ popup=popup_html,
+ icon=folium.Icon(color=color, icon="train", prefix="fa")
+ ).add_to(m)
+
+ # Add route polyline with color-coded congestion
+ for i in range(len(path) - 1):
+ seg = [stations[path[i]], stations[path[i+1]]]
+ seg_congestion = (congestion_levels[path[i]] + congestion_levels[path[i+1]]) / 2
+ seg_color = "green" if seg_congestion < 40 else "orange" if seg_congestion < 70 else "red"
+
+ folium.PolyLine(
+ locations=seg,
+ color=seg_color,
+ weight=6,
+ opacity=0.8,
+ tooltip=f"{path[i]} β {path[i+1]} (Cong: {seg_congestion:.1f}%)"
+ ).add_to(m)
+
+ # =========================
+ # LIVE SIMULATION FEATURE
+ # =========================
+ st.subheader("π¬ Live Simulation of Your Route")
+
+ # AntPath creates animated moving dashes
+ AntPath(
+ locations=route_coords,
+ color="blue",
+ weight=6,
+ delay=800,
+ dash_array=[10, 20]
+ ).add_to(m)
+
+ st_folium(m, width=800, height=550)
+
+ except nx.NetworkXNoPath:
+ # Handle case when no path exists between stations
+ st.error(f"β No route available between **{start}** and **{end}**.")
+ st.info("π‘ **Possible reasons:**")
+ st.markdown("""
+ - These stations are not connected in the current metro network
+ - There may be maintenance or service disruptions
+ - Please try selecting different stations
+ """)
+
+ # Optional: Show which stations are reachable from start
+ try:
+ reachable = list(nx.descendants(G, start))
+ reachable.append(start) # Include the start station itself
+ if reachable:
+ st.info(f"π **Stations reachable from {start}:** {', '.join(reachable)}")
+ except:
+ pass # If this fails, just skip showing reachable stations
+
+ except KeyError as e:
+ # Handle case when station doesn't exist in the graph
+ st.error(f"β οΈ Station not found in the network: {str(e)}")
+ st.info("π‘ Please refresh the page or contact support if this issue persists.")
+
+ except Exception as e:
+ # Catch any other unexpected errors
+ st.error(f"β οΈ An unexpected error occurred while planning your route.")
+ st.warning(f"**Error details:** {str(e)}")
+ st.info("π‘ Please try again or contact support if the problem continues.")
+
+ elif start == end:
+ st.warning("β οΈ Start and Destination stations must be different.")
\ No newline at end of file