Update app.py
Browse files
app.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
|
|
3 |
|
4 |
# Load the Excel file
|
5 |
file_path = 'Dhaka Metro Rail Fare 2.XLSX' # Ensure the correct file path
|
@@ -101,3 +102,162 @@ else:
|
|
101 |
st.write("No fare data available for the selected origin and destinations.")
|
102 |
else:
|
103 |
st.write("Please select both an origin and at least one destination.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import streamlit as st
|
2 |
import pandas as pd
|
3 |
+
import streamlit.components.v1 as components
|
4 |
|
5 |
# Load the Excel file
|
6 |
file_path = 'Dhaka Metro Rail Fare 2.XLSX' # Ensure the correct file path
|
|
|
102 |
st.write("No fare data available for the selected origin and destinations.")
|
103 |
else:
|
104 |
st.write("Please select both an origin and at least one destination.")
|
105 |
+
|
106 |
+
# Embedding the interactive map
|
107 |
+
st.write("### Interactive Map of Dhaka Metro Stations")
|
108 |
+
map_html = """
|
109 |
+
<!DOCTYPE html>
|
110 |
+
<html lang="en">
|
111 |
+
<head>
|
112 |
+
<meta charset="UTF-8">
|
113 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
114 |
+
<title>Interactive Map</title>
|
115 |
+
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
|
116 |
+
<style>
|
117 |
+
#map {
|
118 |
+
height: 90vh;
|
119 |
+
width: 100%;
|
120 |
+
}
|
121 |
+
#controls {
|
122 |
+
height: 10vh;
|
123 |
+
padding: 10px;
|
124 |
+
display: flex;
|
125 |
+
justify-content: center;
|
126 |
+
align-items: center;
|
127 |
+
gap: 10px;
|
128 |
+
background-color: #f0f0f0;
|
129 |
+
}
|
130 |
+
</style>
|
131 |
+
</head>
|
132 |
+
<body>
|
133 |
+
<div id="controls">
|
134 |
+
<select id="source">
|
135 |
+
<option value="">Select Source</option>
|
136 |
+
</select>
|
137 |
+
<select id="destination">
|
138 |
+
<option value="">Select Destination</option>
|
139 |
+
</select>
|
140 |
+
<button onclick="startRouteAnimation()">Animate Route</button>
|
141 |
+
<button onclick="animateAllLocations()">Animate All Locations</button>
|
142 |
+
<button onclick="stopAnimation()">Stop Animation</button>
|
143 |
+
</div>
|
144 |
+
<div id="map"></div>
|
145 |
+
|
146 |
+
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
|
147 |
+
<script>
|
148 |
+
const coordinates = {
|
149 |
+
"Uttara North": [23.869066, 90.367445],
|
150 |
+
"Uttara Center": [23.860118, 90.365106],
|
151 |
+
"Uttara South": [23.845934, 90.363175],
|
152 |
+
"Pallabi": [23.82619516961383, 90.36481554252525],
|
153 |
+
"Mirpur 11": [23.819438208310213, 90.36528532902963],
|
154 |
+
"Mirpur 10": [23.808582994847285, 90.36821595330717],
|
155 |
+
"Kazipara": [23.800017952100532, 90.37178261495391],
|
156 |
+
"Shewrapara": [23.79070140857881, 90.37564622631841],
|
157 |
+
"Agargaon": [23.778385546736345, 90.3800557456356],
|
158 |
+
"Bijoy Sarani": [23.766638127271825, 90.38307537134754],
|
159 |
+
"Farmgate": [23.75923604938459, 90.38694218434738],
|
160 |
+
"Kawran Bazar": [23.751392319539104, 90.39275707447003],
|
161 |
+
"Shahbagh": [23.740324209546923, 90.39600784811131],
|
162 |
+
"Dhaka University": [23.732091083122114, 90.39659408796354],
|
163 |
+
"Bangladesh Secretariat": [23.73004754106779, 90.40764881366906],
|
164 |
+
"Motijheel": [23.72816566933198, 90.41923497972823],
|
165 |
+
"Kamalapur": [23.732367758919807, 90.42547378971085]
|
166 |
+
};
|
167 |
+
const map = L.map('map').setView([23.8103, 90.4125], 12); // Centered on Dhaka
|
168 |
+
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
169 |
+
maxZoom: 19,
|
170 |
+
attribution: '© OpenStreetMap contributors'
|
171 |
+
}).addTo(map);
|
172 |
+
// Populate source and destination dropdowns
|
173 |
+
const sourceSelect = document.getElementById('source');
|
174 |
+
const destinationSelect = document.getElementById('destination');
|
175 |
+
for (const location in coordinates) {
|
176 |
+
const option = document.createElement('option');
|
177 |
+
option.value = location;
|
178 |
+
option.textContent = location;
|
179 |
+
sourceSelect.appendChild(option);
|
180 |
+
destinationSelect.appendChild(option.cloneNode(true));
|
181 |
+
}
|
182 |
+
const markers = {};
|
183 |
+
for (const [name, coord] of Object.entries(coordinates)) {
|
184 |
+
const marker = L.marker(coord).addTo(map).bindPopup(`<b>${name}</b>`);
|
185 |
+
markers[name] = marker;
|
186 |
+
}
|
187 |
+
let currentIndex = 0;
|
188 |
+
const markerArray = Object.values(markers);
|
189 |
+
let animationTimeout; // Store the timeout ID to cancel animation
|
190 |
+
function getIntermediateNodes(source, destination) {
|
191 |
+
const allLocations = Object.keys(coordinates);
|
192 |
+
const sourceIndex = allLocations.indexOf(source);
|
193 |
+
const destinationIndex = allLocations.indexOf(destination);
|
194 |
+
const route = [];
|
195 |
+
if (sourceIndex < destinationIndex) {
|
196 |
+
// Forward direction (source to destination)
|
197 |
+
route.push(...allLocations.slice(sourceIndex, destinationIndex + 1));
|
198 |
+
} else {
|
199 |
+
// Reverse direction (destination to source)
|
200 |
+
route.push(...allLocations.slice(destinationIndex, sourceIndex + 1).reverse());
|
201 |
+
}
|
202 |
+
return route;
|
203 |
+
}
|
204 |
+
function startRouteAnimation() {
|
205 |
+
const source = sourceSelect.value;
|
206 |
+
const destination = destinationSelect.value;
|
207 |
+
if (!source || !destination) {
|
208 |
+
alert('Please select both source and destination locations.');
|
209 |
+
return;
|
210 |
+
}
|
211 |
+
const route = getIntermediateNodes(source, destination);
|
212 |
+
let routeIndex = 0;
|
213 |
+
function animateRoute() {
|
214 |
+
if (routeIndex >= route.length) {
|
215 |
+
return; // Animation completed
|
216 |
+
}
|
217 |
+
const currentLocation = route[routeIndex];
|
218 |
+
const marker = markers[currentLocation];
|
219 |
+
if (routeIndex === 0) {
|
220 |
+
map.flyTo(marker.getLatLng(), 14, { duration: 2 });
|
221 |
+
marker.openPopup();
|
222 |
+
} else {
|
223 |
+
setTimeout(() => {
|
224 |
+
map.flyTo(marker.getLatLng(), 14, { duration: 2 });
|
225 |
+
marker.openPopup();
|
226 |
+
}, 3000);
|
227 |
+
}
|
228 |
+
routeIndex++;
|
229 |
+
animationTimeout = setTimeout(animateRoute, 3000); // Wait before moving to the next
|
230 |
+
}
|
231 |
+
animateRoute();
|
232 |
+
}
|
233 |
+
function animateAllLocations() {
|
234 |
+
if (currentIndex > 0) {
|
235 |
+
markerArray[currentIndex - 1].closePopup();
|
236 |
+
}
|
237 |
+
if (currentIndex < markerArray.length) {
|
238 |
+
const marker = markerArray[currentIndex];
|
239 |
+
map.flyTo(marker.getLatLng(), 14, { duration: 2 });
|
240 |
+
marker.openPopup();
|
241 |
+
currentIndex++;
|
242 |
+
animationTimeout = setTimeout(animateAllLocations, 3000); // Wait 3 seconds before next
|
243 |
+
} else {
|
244 |
+
currentIndex = 0; // Restart animation
|
245 |
+
}
|
246 |
+
}
|
247 |
+
// Stop animation and reset everything
|
248 |
+
function stopAnimation() {
|
249 |
+
clearTimeout(animationTimeout); // Stop the timeout for animation
|
250 |
+
currentIndex = 0; // Reset index
|
251 |
+
for (const marker of markerArray) {
|
252 |
+
marker.closePopup(); // Close all popups
|
253 |
+
}
|
254 |
+
map.setView([23.8103, 90.4125], 12); // Reset map to initial view
|
255 |
+
sourceSelect.value = ''; // Clear source dropdown
|
256 |
+
destinationSelect.value = ''; // Clear destination dropdown
|
257 |
+
}
|
258 |
+
</script>
|
259 |
+
</body>
|
260 |
+
</html>
|
261 |
+
"""
|
262 |
+
components.html(map_html, height=600)
|
263 |
+
|