File size: 7,095 Bytes
b1b06e6
b4a460e
b1b06e6
 
b4a460e
 
 
d15b1e2
b4a460e
b1b06e6
b517951
b4a460e
 
b1b06e6
b4a460e
b1b06e6
 
 
b4a460e
 
 
 
b1b06e6
b4a460e
 
 
b1b06e6
 
b4a460e
b1b06e6
d15b1e2
b4a460e
b1b06e6
 
 
 
 
b4a460e
 
 
b1b06e6
b4a460e
 
 
 
 
 
 
b1b06e6
 
 
 
 
 
 
 
d15b1e2
b1b06e6
 
b4a460e
b1b06e6
d15b1e2
 
 
 
 
 
 
 
 
b1b06e6
 
 
d15b1e2
 
b1b06e6
d15b1e2
 
 
 
 
 
 
 
 
 
 
 
 
 
b1b06e6
 
 
 
d15b1e2
b1b06e6
 
 
 
 
 
b4a460e
b1b06e6
 
 
 
 
 
 
 
 
b4a460e
 
 
b1b06e6
d15b1e2
 
 
 
 
 
 
 
 
 
 
 
 
 
b1b06e6
b4a460e
 
b1b06e6
b4a460e
 
 
 
 
 
 
 
 
b1b06e6
 
b4a460e
b1b06e6
b4a460e
b1b06e6
b4a460e
d15b1e2
 
 
 
b1b06e6
d15b1e2
b1b06e6
 
 
 
 
 
 
 
 
 
b4a460e
 
b1b06e6
 
 
b4a460e
b1b06e6
d15b1e2
b1b06e6
 
 
 
 
b4a460e
d15b1e2
b1b06e6
b4a460e
b1b06e6
b4a460e
 
b1b06e6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
import streamlit as st
import pandas as pd
import random
from datetime import datetime, timedelta
import folium
from streamlit_folium import folium_static
import groq
import time

# --- ๐Ÿ“‚ Load Bus Data ---
data_path = "pdp.csv"
df = pd.read_csv(data_path)

# --- ๐Ÿ” Dummy User Credentials ---
USER_CREDENTIALS = {
    "Muthuraja": "virat",
    "Praveen": "dhoni",
    "Pandi": "kabadi",
    "admin": "password123",
    "user": "buspass2025"
}

# --- ๐Ÿ”‘ Groq API Key ---
GROQ_API_KEY = "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"
groq.api_key = GROQ_API_KEY


# --- ๐Ÿ”“ Authenticate User ---
def authenticate(username, password):
    """Authenticate user."""
    return USER_CREDENTIALS.get(username) == password


# --- ๐Ÿ”ฎ Predict Bus Status using Groq API ---
def predict_bus_status(bus_number, city, source_area, destination_area):
    """Predict bus arrival and status with Groq API."""
    prompt = f"Predict the status, route, and arrival time for bus {bus_number} from {source_area} to {destination_area} in {city}."
    try:
        client = groq.Client(api_key=GROQ_API_KEY)
        response = client.chat.completions.create(
            model="llama3-70b-8192",
            messages=[{"role": "system", "content": prompt}]
        )
        return response.choices[0].message.content.strip()
    except Exception as e:
        return f"Error: {e}"


# --- ๐Ÿ•ฐ๏ธ Add Random Delay to Predicted Time ---
def add_random_delay(arrival_time_str):
    """Add 1 to 10 minutes delay to arrival time."""
    try:
        arrival_time = datetime.strptime(arrival_time_str, "%d-%m-%Y %H:%M")
    except ValueError:
        arrival_time = datetime.strptime(arrival_time_str, "%Y-%m-%d %H:%M:%S")

    delay_minutes = random.randint(1, 10)
    new_arrival_time = arrival_time + timedelta(minutes=delay_minutes)
    return new_arrival_time.strftime("%Y-%m-%d %H:%M:%S")


# --- ๐Ÿš Predict Upcoming Buses on Same Route / Nearby Area ---
def predict_upcoming_buses(bus_number, city, source_area, destination_area, area_df):
    """Predict upcoming buses on the same route or nearby areas."""
    # Filter buses on the same route
    same_route_df = area_df[
        (area_df["bus_route"] == area_df[area_df["bus_number"] == bus_number]["bus_route"].values[0]) &
        (area_df["arrival_time"] > datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
    ]

    if not same_route_df.empty:
        upcoming_buses = []
        for _, row in same_route_df.iterrows():
            delayed_time = add_random_delay(row['arrival_time'])
            upcoming_buses.append(f"๐ŸšŒ Bus {row['bus_number']} โ†’ {row['bus_route']} arriving at {delayed_time}")
        return "\n".join(upcoming_buses)

    # Fallback: Suggest nearby same-area buses
    nearby_buses_df = area_df[
        (area_df["area"] == source_area) | (area_df["area"] == destination_area)
    ]

    if not nearby_buses_df.empty:
        nearby_buses = []
        for _, row in nearby_buses_df.iterrows():
            delayed_time = add_random_delay(row['arrival_time'])
            nearby_buses.append(f"๐ŸšŒ Nearby Bus {row['bus_number']} โ†’ {row['bus_route']} arriving at {delayed_time}")
        return "\n".join(nearby_buses)

    return "โš ๏ธ No upcoming buses available for the same route or nearby areas."


# --- ๐Ÿ—บ๏ธ Plot Bus Route Map ---
def plot_bus_route(source_area, destination_area, area_df):
    """Plot bus route between source and destination."""
    source_df = area_df[area_df["area"] == source_area]
    dest_df = area_df[area_df["area"] == destination_area]

    if source_df.empty or dest_df.empty:
        st.warning("โŒ Invalid source or destination. Please try again.")
        return

    source_lat, source_lon = source_df.iloc[0]["latitude"], source_df.iloc[0]["longitude"]
    dest_lat, dest_lon = dest_df.iloc[0]["latitude"], dest_df.iloc[0]["longitude"]

    m = folium.Map(location=[(source_lat + dest_lat) / 2, (source_lon + dest_lon) / 2], zoom_start=12)

    folium.Marker([source_lat, source_lon], popup=f"๐ŸšŒ Source: {source_area}", icon=folium.Icon(color="green")).add_to(m)
    folium.Marker([dest_lat, dest_lon], popup=f"๐Ÿ Destination: {destination_area}", icon=folium.Icon(color="red")).add_to(m)

    folium.PolyLine([(source_lat, source_lon), (dest_lat, dest_lon)], color="blue", weight=5, opacity=0.8).add_to(m)

    folium_static(m)


# --- โฐ Stable Real-Time Clock on Top ---
def update_clock(clock_placeholder):
    """Continuously update and display a real-time clock after login."""
    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    clock_placeholder.markdown(
        f"""
        <h3 style="text-align: center; color: green;">
        โฐ Live Time: {now}
        </h3>
        """,
        unsafe_allow_html=True
    )


# --- ๐Ÿš€ Streamlit App Interface ---
st.title("๐Ÿš Tamil Nadu Bus Tracking & Prediction System")

# --- ๐Ÿ” Login System ---
if "authenticated" not in st.session_state:
    st.session_state.authenticated = False

if not st.session_state.authenticated:
    username = st.text_input("Username")
    password = st.text_input("Password", type="password")
    if st.button("Login"):
        if authenticate(username, password):
            st.session_state.authenticated = True
            st.success("โœ… Login successful!")
            st.rerun()
        else:
            st.error("โŒ Invalid username or password")

# --- ๐Ÿ—บ๏ธ Main Content after Login ---
if st.session_state.authenticated:
    # --- โฐ Live Clock after Login ---
    clock_placeholder = st.empty()
    update_clock(clock_placeholder)

    st.sidebar.header("๐ŸŒ† City, Source & Destination Selection")

    city = st.sidebar.selectbox("Select City", df["city"].unique())
    area_df = df[df["city"] == city]

    # Select Source & Destination Area
    source_area = st.sidebar.selectbox("Select Source Area", area_df["area"].unique())
    destination_area = st.sidebar.selectbox("Select Destination Area", area_df["area"].unique())

    # --- ๐ŸšŒ Show Bus Details ---
    st.subheader(f"๐ŸšŒ Bus Details for Route: {source_area} โžก๏ธ {destination_area} in {city}")
    filtered_df = area_df[(area_df["area"] == source_area) | (area_df["area"] == destination_area)]
    st.dataframe(filtered_df)

    # --- ๐Ÿ—บ๏ธ Show Live Route Map ---
    st.subheader("๐Ÿ—บ๏ธ Live Bus Route Map")
    plot_bus_route(source_area, destination_area, area_df)

    # --- ๐Ÿ”ฎ Predict Bus and Same Route Buses ---
    st.subheader("๐Ÿ”ฎ Bus Prediction & Same Route/Area Upcoming Buses")
    if not filtered_df.empty:
        for _, row in filtered_df.iterrows():
            bus_number = row['bus_number']
            prediction = predict_bus_status(bus_number, city, source_area, destination_area)
            st.success(f"๐Ÿ”ฎ Prediction for Bus {bus_number}: {prediction}")

            upcoming_buses_info = predict_upcoming_buses(bus_number, city, source_area, destination_area, area_df)
            st.info(upcoming_buses_info)

    # --- ๐Ÿ”“ Logout Option ---
    if st.button("Logout"):
        st.session_state.authenticated = False
        st.rerun()