From aae987cf1c80740363d712242294929607b9f6e7 Mon Sep 17 00:00:00 2001 From: Deepanshu Gautam Date: Fri, 24 Oct 2025 19:34:09 +0530 Subject: [PATCH 1/4] Delete ai-models/wardha_passenger_view.py --- ai-models/wardha_passenger_view.py | 187 ----------------------------- 1 file changed, 187 deletions(-) delete mode 100644 ai-models/wardha_passenger_view.py diff --git a/ai-models/wardha_passenger_view.py b/ai-models/wardha_passenger_view.py deleted file mode 100644 index 0db2885..0000000 --- a/ai-models/wardha_passenger_view.py +++ /dev/null @@ -1,187 +0,0 @@ - - -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.") From ae8c3af429a3918f8513e841386cf851154e5d91 Mon Sep 17 00:00:00 2001 From: Deepanshu Gautam Date: Fri, 24 Oct 2025 19:35:42 +0530 Subject: [PATCH 2/4] updates code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Key Changes Made: 1. Added Comprehensive Error Handling (Lines 94-153) βœ… try-except block wrapping all route planning logic βœ… Specific handling for nx.NetworkXNoPath exception βœ… Handling for KeyError (station not in graph) βœ… Generic exception handler as safety net 2. Improved User Feedback βœ… Clear error messages explaining what went wrong βœ… Actionable suggestions for users βœ… Shows reachable stations from selected start point 3. Network Status Indicator (Lines 80-85) βœ… Added sidebar connectivity check βœ… Visual indicator of network health 4. Code Quality Improvements βœ… Removed redundant np.random.seed(None) (Line 72) βœ… Added comments explaining the travel time formula βœ… Better code organization --- ai-models/wardha_passenger_view.py | 226 +++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 ai-models/wardha_passenger_view.py diff --git a/ai-models/wardha_passenger_view.py b/ai-models/wardha_passenger_view.py new file mode 100644 index 0000000..438cc5f --- /dev/null +++ b/ai-models/wardha_passenger_view.py @@ -0,0 +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 --- + # 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 From e04c98bc8b1db20cd22b90db4e0041f6c48b22ce Mon Sep 17 00:00:00 2001 From: Deepanshu Gautam Date: Sat, 25 Oct 2025 10:22:52 +0530 Subject: [PATCH 3/4] Delete ai-models/fare_estimation.py --- ai-models/fare_estimation.py | 85 ------------------------------------ 1 file changed, 85 deletions(-) delete mode 100644 ai-models/fare_estimation.py diff --git a/ai-models/fare_estimation.py b/ai-models/fare_estimation.py deleted file mode 100644 index 162420b..0000000 --- a/ai-models/fare_estimation.py +++ /dev/null @@ -1,85 +0,0 @@ -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) From 0992575f3c5c1250bc51020b568e123128bffaf6 Mon Sep 17 00:00:00 2001 From: Deepanshu Gautam Date: Sat, 25 Oct 2025 10:24:08 +0530 Subject: [PATCH 4/4] updated fare estimation --- ai-models/fare_estimation.py | 192 +++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 ai-models/fare_estimation.py diff --git a/ai-models/fare_estimation.py b/ai-models/fare_estimation.py new file mode 100644 index 0000000..c1ebedb --- /dev/null +++ b/ai-models/fare_estimation.py @@ -0,0 +1,192 @@ +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