File size: 9,887 Bytes
3a3c7af
 
 
f38dba6
3a3c7af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f38dba6
3a3c7af
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a9e3a49
 
 
 
 
2fcd67c
a9e3a49
 
 
 
 
 
 
 
 
 
 
 
3a3c7af
 
 
 
 
f38dba6
2fcd67c
f38dba6
3a3c7af
 
 
 
 
 
f38dba6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3a3c7af
 
f38dba6
 
 
 
 
 
 
 
 
 
 
 
 
3a3c7af
 
 
 
 
 
f38dba6
 
 
 
 
 
 
 
 
3a3c7af
 
f38dba6
3a3c7af
 
f38dba6
 
 
3a3c7af
 
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
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
import streamlit as st
import pandas as pd
import plotly.graph_objects as go
import time

# Load the Excel file
file_path = 'Dhaka Metro Rail Fare 2.XLSX'  # Ensure the correct file path
df = pd.read_excel(file_path)

# Ensure necessary columns are present
required_columns = ['Origin', 'Destination', 'Fare (ΰ§³)']
if not all(col in df.columns for col in required_columns):
    st.write("Please ensure the file contains 'Origin', 'Destination', and 'Fare' columns.")
else:
    # Add coordinates for each station (example coordinates for illustration)
    coordinates = {
        "Uttara North": (23.869066, 90.367445),
        "Uttara Center": (23.860118, 90.365106),
        "Uttara South": (23.845934, 90.363175),
        "Pallabi": (23.82619516961383, 90.36481554252525),
        "Mirpur 11": (23.819438208310213, 90.36528532902963),
        "Mirpur 10": (23.808582994847285, 90.36821595330717),
        "Kazipara": (23.800017952100532, 90.37178261495391),
        "Shewrapara": (23.79070140857881, 90.37564622631841),
        "Agargaon": (23.778385546736345, 90.3800557456356),
        "Bijoy Sarani": (23.766638127271825, 90.38307537134754),
        "Farmgate": (23.75923604938459, 90.38694218434738),
        "Kawran Bazar": (23.751392319539104, 90.39275707447003),
        "Shahbagh": (23.740324209546923, 90.39600784811131),
        "Dhaka University": (23.732091083122114, 90.39659408796354),
        "Bangladesh Secretariat": (23.73004754106779, 90.40764881366906),
        "Motijheel": (23.72816566933198, 90.41923497972823),
        "Kamalapur": (23.732367758919807, 90.42547378971085)
    }

    # Add latitude and longitude for origin and destination based on the coordinates dictionary
    df['Origin_Lat'] = df['Origin'].map(lambda x: coordinates.get(x, (None, None))[0])
    df['Origin_Lon'] = df['Origin'].map(lambda x: coordinates.get(x, (None, None))[1])
    df['Destination_Lat'] = df['Destination'].map(lambda x: coordinates.get(x, (None, None))[0])
    df['Destination_Lon'] = df['Destination'].map(lambda x: coordinates.get(x, (None, None))[1])

    # Filter rows with missing coordinates
    df.dropna(subset=['Origin_Lat', 'Origin_Lon', 'Destination_Lat', 'Destination_Lon'], inplace=True)

    # Streamlit UI setup
    st.title("Dhaka Metro Rail Fare Checker πŸš‡")
    st.write("Below is the fare chart for Dhaka Metro Rail πŸ’Ά:")

    # Instruction sidebar
    st.sidebar.title("Instructions")
    st.sidebar.write("""
    **Welcome to the Dhaka Metro Rail Fare Checker!**
   
    *How to use:*
    1. Select your **Location station** from the dropdown menu.
    2. Select your **destination(s)** by clicking the destination buttons.
    3. The fare from your location to the selected destination(s) will be displayed below.
    4. You can also see the stations marked on a map with an animated train journey!
    
    **Note:** The map highlights your location in green and destinations in blue.
    
    If you face any issues or need further assistance, feel free to [Contact Support on WhatsApp](https://wa.me/+8801719296601).
    """)

    # Define the default "Select Journey from" message
    default_origin = "Select Journey from"

    # Dropdown for selecting origin (with "Select Journey from" as a default placeholder)
    origin = st.selectbox(
        "Select your Location:", 
        [default_origin] + df['Origin'].unique().tolist(),  # Add the "Select Journey from" option at the top
        index=0  # Ensure the first option is selected by default
    )

    # Initialize session state for destination selection if not already set
    if 'destination_select' not in st.session_state:
        st.session_state.destination_select = []

    # Display buttons for each destination in 3 columns
    if origin != default_origin:
        st.write(f"Select your destination(s) from {origin}:")

        # Create 3 columns
        cols = st.columns(3)

        # Loop through all possible destinations and create a button for each in the columns
        dest_buttons = df['Destination'].unique()
        for i, dest in enumerate(dest_buttons):
            col_idx = i % 3  # Determine column index based on button position
            with cols[col_idx]:
                if st.button(f"Select {dest}", key=f"btn_{dest}"):
                    if dest not in st.session_state.destination_select:
                        st.session_state.destination_select.append(dest)
                    else:
                        st.session_state.destination_select.remove(dest)

        # Clear all selected destinations button
        if st.button("Clear All Destinations"):
            st.session_state.destination_select = []

    # Display selected destinations and calculate fares
    destinations = st.session_state.destination_select

    if origin == default_origin:
        st.write("Please select a valid origin station to proceed.")
    elif origin and destinations:
        # Filter the dataframe based on user selection
        fare_data = df[(df['Origin'] == origin) & (df['Destination'].isin(destinations))]

        # Display the fare data
        if not fare_data.empty:
            for index, row in fare_data.iterrows():
                origin_to_dest_fare = row['Fare (ΰ§³)']
                destination = row['Destination']
        
                # Creative output with icons, emojis, and styled text
                fare_message = f"""
                <div style="background-color: #f0f8ff; padding: 10px; margin-bottom: 12px; border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);">
                    <h4 style="font-family: 'Arial', sans-serif; color: #003366;">
                        πŸš‡ <strong>{origin}</strong> to <strong>{destination}</strong> Fare
                    </h4>
                    <p style="font-family: 'Arial', sans-serif; font-size: 18px; color: #009688;">
                        πŸ’΅ Fare: <strong style="font-size: 20px; color: #e91e63;">{origin_to_dest_fare}ΰ§³</strong>
                    </p>
                    <p style="font-family: 'Arial', sans-serif; font-size: 14px; color: #555555;">
                        ✨ Enjoy your journey on the Dhaka Metro! πŸš‰
                    </p>
                </div>
                """
                st.markdown(fare_message, unsafe_allow_html=True)
        else:
            st.write("No fare data available for the selected origin and destinations.")
    else:
        st.write("Please select both an origin and at least one destination.")

    st.write("Below is the Animated Map for Dhaka Metro Rail πŸ’Ά:")

    # Plotting the map using Plotly with animation
    fig = go.Figure()

    # Add markers for each unique station
    unique_stations = pd.concat([df[['Origin', 'Origin_Lat', 'Origin_Lon']].rename(columns={'Origin': 'Station', 'Origin_Lat': 'Lat', 'Origin_Lon': 'Lon'}), 
                                 df[['Destination', 'Destination_Lat', 'Destination_Lon']].rename(columns={'Destination': 'Station', 'Destination_Lat': 'Lat', 'Destination_Lon': 'Lon'})]).drop_duplicates()

    # Store the animation frames for the train's movement
    frames = []

    # For each selected destination, animate the train from the origin to the destination
    if origin != default_origin and destinations:
        for dest in destinations:
            origin_coords = (coordinates[origin][0], coordinates[origin][1])
            destination_coords = (coordinates[dest][0], coordinates[dest][1])

            # Create frames for animation (move from origin to destination)
            num_frames = 30
            lat_diff = (destination_coords[0] - origin_coords[0]) / num_frames
            lon_diff = (destination_coords[1] - origin_coords[1]) / num_frames

            frames = [
                go.Frame(
                    data=[go.Scattermapbox(
                        mode="markers+text",
                        lon=[origin_coords[1] + lon_diff * i],
                        lat=[origin_coords[0] + lat_diff * i],
                        marker={'size': 15, 'color': 'orange'},
                        text="πŸš† Train",
                        textposition="top center"
                    )],
                    name=f"frame_{i}"
                ) for i in range(num_frames)
            ]

            # Add final frame for destination
            frames.append(go.Frame(
                data=[go.Scattermapbox(
                    mode="markers+text",
                    lon=[destination_coords[1]],
                    lat=[destination_coords[0]],
                    marker={'size': 15, 'color': 'orange'},
                    text="πŸš† Train",
                    textposition="top center"
                )],
                name=f"frame_{num_frames}"
            ))

    # Add base station markers
    for i, row in unique_stations.iterrows():
        fig.add_trace(go.Scattermapbox(
            mode="markers+text",
            lon=[row['Lon']],
            lat=[row['Lat']],
            marker={'size': 10, 'color': 'blue'},
            text=row['Station'],
            textposition="top center",
            name=row['Station']
        ))

    # Map layout with animation
    fig.update_layout(
        mapbox=dict(
            style="open-street-map",
            center=go.layout.mapbox.Center(lat=23.780, lon=90.400),  # Center on Dhaka
            zoom=11
        ),
        updatemenus=[dict(
            type="buttons",
            showactive=False,
            buttons=[dict(
                label="Play",
                method="animate",
                args=[None, dict(frame=dict(duration=100, redraw=True), fromcurrent=True)]
            )]
        )],
        margin={"r":0,"t":0,"l":0,"b":0},
        showlegend=False,
        title="Dhaka Metro Rail Location Map with Train Animation"
    )

    # Add frames for animation
    fig.frames = frames

    # Show plot in Streamlit
    st.plotly_chart(fig)