shukdevdatta123 commited on
Commit
feed0f9
Β·
verified Β·
1 Parent(s): 8c77b27

Create v1.txt

Browse files
Files changed (1) hide show
  1. v1.txt +440 -0
v1.txt ADDED
@@ -0,0 +1,440 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script type="text/javascript">
2
+ var gk_isXlsx = false;
3
+ var gk_xlsxFileLookup = {};
4
+ var gk_fileData = {};
5
+ function filledCell(cell) {
6
+ return cell !== '' && cell != null;
7
+ }
8
+ function loadFileData(filename) {
9
+ if (gk_isXlsx && gk_xlsxFileLookup[filename]) {
10
+ try {
11
+ var workbook = XLSX.read(gk_fileData[filename], { type: 'base64' });
12
+ var firstSheetName = workbook.SheetNames[0];
13
+ var worksheet = workbook.Sheets[firstSheetName];
14
+ // Convert sheet to JSON to filter blank rows
15
+ var jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1, blankrows: false, defval: '' });
16
+ // Filter out blank rows (rows where all cells are empty, null, or undefined)
17
+ var filteredData = jsonData.filter(row => row.some(filledCell));
18
+ // Heuristic to find the header row by ignoring rows with fewer filled cells than the next row
19
+ var headerRowIndex = filteredData.findIndex((row, index) =>
20
+ row.filter(filledCell).length >= filteredData[index + 1]?.filter(filledCell).length
21
+ );
22
+ // Fallback
23
+ if (headerRowIndex === -1 || headerRowIndex > 25) {
24
+ headerRowIndex = 0;
25
+ }
26
+ // Convert filtered JSON back to CSV
27
+ var csv = XLSX.utils.aoa_to_sheet(filteredData.slice(headerRowIndex)); // Create a new sheet from filtered array of arrays
28
+ csv = XLSX.utils.sheet_to_csv(csv, { header: 1 });
29
+ return csv;
30
+ } catch (e) {
31
+ console.error(e);
32
+ return "";
33
+ }
34
+ }
35
+ return gk_fileData[filename] || "";
36
+ }
37
+ </script><!DOCTYPE html>
38
+ <html lang="en">
39
+ <head>
40
+ <meta charset="UTF-8">
41
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
42
+ <title>Dhaka Metro Rail Fare Checker</title>
43
+ <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
44
+ <style>
45
+ @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
46
+ * {
47
+ margin: 0;
48
+ padding: 0;
49
+ box-sizing: border-box;
50
+ }
51
+ body {
52
+ font-family: 'Roboto', sans-serif;
53
+ background-color: #f4f4f4;
54
+ color: #333;
55
+ overflow-x: hidden;
56
+ }
57
+ header {
58
+ background: linear-gradient(135deg, #003366, #005588);
59
+ color: white;
60
+ padding: 2rem;
61
+ text-align: center;
62
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
63
+ animation: slideInDown 1s ease-out;
64
+ }
65
+ header h1 {
66
+ font-size: 2.5rem;
67
+ display: flex;
68
+ align-items: center;
69
+ justify-content: center;
70
+ gap: 10px;
71
+ }
72
+ aside#sidebar {
73
+ position: fixed;
74
+ top: 0;
75
+ left: 0;
76
+ width: 280px;
77
+ height: 100%;
78
+ background: #D8C4B6;
79
+ padding: 20px;
80
+ overflow-y: auto;
81
+ box-shadow: 2px 0 10px rgba(0, 0, 0, 0.1);
82
+ transform: translateX(-100%);
83
+ animation: slideInLeft 0.8s ease-out forwards;
84
+ }
85
+ aside h2 {
86
+ color: #003366;
87
+ margin-bottom: 15px;
88
+ }
89
+ aside p {
90
+ font-size: 0.95rem;
91
+ line-height: 1.6;
92
+ }
93
+ aside a {
94
+ color: #009688;
95
+ text-decoration: none;
96
+ }
97
+ main {
98
+ margin-left: 300px;
99
+ padding: 30px;
100
+ animation: fadeIn 1s ease-in;
101
+ }
102
+ #fare-checker, #map-section {
103
+ background: white;
104
+ padding: 25px;
105
+ border-radius: 12px;
106
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1);
107
+ margin-bottom: 30px;
108
+ transition: transform 0.3s ease;
109
+ }
110
+ #fare-checker:hover, #map-section:hover {
111
+ transform: translateY(-5px);
112
+ }
113
+ h2 {
114
+ color: #003366;
115
+ margin-bottom: 20px;
116
+ }
117
+ label {
118
+ font-weight: bold;
119
+ margin-bottom: 10px;
120
+ display: block;
121
+ }
122
+ select {
123
+ width: 100%;
124
+ padding: 12px;
125
+ margin-bottom: 20px;
126
+ border: 2px solid #009688;
127
+ border-radius: 6px;
128
+ font-size: 1rem;
129
+ transition: border-color 0.3s ease;
130
+ }
131
+ select:focus {
132
+ border-color: #e91e63;
133
+ outline: none;
134
+ }
135
+ #destination-buttons {
136
+ display: flex;
137
+ flex-wrap: wrap;
138
+ gap: 12px;
139
+ margin-bottom: 20px;
140
+ }
141
+ #destination-buttons button {
142
+ background: #009688;
143
+ color: white;
144
+ border: none;
145
+ padding: 10px 20px;
146
+ border-radius: 25px;
147
+ cursor: pointer;
148
+ transition: all 0.3s ease;
149
+ }
150
+ #destination-buttons button:hover {
151
+ background: #00796b;
152
+ transform: scale(1.05);
153
+ }
154
+ #destination-buttons button.selected {
155
+ background: #e91e63;
156
+ transform: scale(1.05);
157
+ }
158
+ #clear-destinations {
159
+ background: #e91e63;
160
+ color: white;
161
+ border: none;
162
+ padding: 12px 25px;
163
+ border-radius: 25px;
164
+ cursor: pointer;
165
+ transition: all 0.3s ease;
166
+ }
167
+ #clear-destinations:hover {
168
+ background: #c2185b;
169
+ transform: scale(1.05);
170
+ }
171
+ #fare-display .fare-item {
172
+ background: #f0f8ff;
173
+ padding: 15px;
174
+ margin-bottom: 15px;
175
+ border-radius: 8px;
176
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
177
+ animation: fadeInUp 0.5s ease-out;
178
+ }
179
+ #map {
180
+ height: 500px;
181
+ border-radius: 8px;
182
+ margin-top: 20px;
183
+ }
184
+ #map-controls {
185
+ display: flex;
186
+ justify-content: center;
187
+ gap: 10px;
188
+ margin-top: 15px;
189
+ flex-wrap: wrap;
190
+ }
191
+ #map-controls button {
192
+ background: #003366;
193
+ color: white;
194
+ border: none;
195
+ padding: 10px 20px;
196
+ border-radius: 25px;
197
+ cursor: pointer;
198
+ transition: all 0.3s ease;
199
+ }
200
+ #map-controls button:hover {
201
+ background: #005588;
202
+ transform: scale(1.05);
203
+ }
204
+ @keyframes slideInDown {
205
+ from { transform: translateY(-100%); }
206
+ to { transform: translateY(0); }
207
+ }
208
+ @keyframes slideInLeft {
209
+ from { transform: translateX(-100%); }
210
+ to { transform: translateX(0); }
211
+ }
212
+ @keyframes fadeIn {
213
+ from { opacity: 0; }
214
+ to { opacity: 1; }
215
+ }
216
+ @keyframes fadeInUp {
217
+ from { opacity: 0; transform: translateY(20px); }
218
+ to { opacity: 1; transform: translateY(0); }
219
+ }
220
+ @media (max-width: 768px) {
221
+ aside#sidebar {
222
+ position: relative;
223
+ width: 100%;
224
+ height: auto;
225
+ transform: none;
226
+ animation: none;
227
+ }
228
+ main {
229
+ margin-left: 0;
230
+ padding: 15px;
231
+ }
232
+ #map {
233
+ height: 300px;
234
+ }
235
+ header h1 {
236
+ font-size: 1.8rem;
237
+ }
238
+ }
239
+ </style>
240
+ </head>
241
+ <body>
242
+ <header>
243
+ <h1>Dhaka Metro Rail Fare Checker πŸš‡</h1>
244
+ </header>
245
+ <aside id="sidebar">
246
+ <h2>Instructions</h2>
247
+ <p>
248
+ <strong>Welcome to the Dhaka Metro Rail Fare Checker! πŸš‡</strong><br>
249
+ <em>How to use:</em><br>
250
+ 1. <strong>Select your Location station</strong>: Choose your starting station from the "Select your Location" dropdown.<br>
251
+ 2. <strong>Select your destination(s)</strong>: Click the buttons for your desired destinations. Select multiple for different routes!<br>
252
+ 3. <strong>Fare Calculation</strong>: See fares below for your selected routes.<br>
253
+ 4. <strong>Clear Destinations</strong>: Hit "Clear All Destinations" to reset.<br>
254
+ <hr>
255
+ <strong>Interactive Map</strong>: Visualize routes and animate stations below.<br>
256
+ - <strong>Dropdowns</strong>: Pick source and destination.<br>
257
+ - <strong>Animate Route</strong>: Watch your route come to life.<br>
258
+ - <strong>Animate All</strong>: See all stations animated.<br>
259
+ - <strong>Stop</strong>: Pause animations anytime.<br>
260
+ Enjoy your journey! πŸš‰<br>
261
+ Need help? <a href="https://wa.me/+8801719296601">Contact Support</a>.
262
+ </p>
263
+ </aside>
264
+ <main>
265
+ <section id="fare-checker">
266
+ <h2>Check Your Fare</h2>
267
+ <label for="origin">Select your Location:</label>
268
+ <select id="origin">
269
+ <option value="">Select Journey from</option>
270
+ </select>
271
+ <div id="destination-buttons"></div>
272
+ <button id="clear-destinations">Clear All Destinations</button>
273
+ <div id="fare-display"></div>
274
+ </section>
275
+ <section id="map-section">
276
+ <h2>Interactive Map</h2>
277
+ <div id="map"></div>
278
+ <div id="map-controls">
279
+ <select id="map-source">
280
+ <option value="">Select Source</option>
281
+ </select>
282
+ <select id="map-destination">
283
+ <option value="">Select Destination</option>
284
+ </select>
285
+ <button onclick="startRouteAnimation()">Animate Route</button>
286
+ <button onclick="animateAllLocations()">Animate All Locations</button>
287
+ <button onclick="stopAnimation()">Stop Animation</button>
288
+ </div>
289
+ </section>
290
+ </main>
291
+ <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
292
+ <script src="data.js"></script>
293
+ <script>
294
+ // Populate origin dropdown
295
+ const originSelect = document.getElementById('origin');
296
+ const origins = [...new Set(fareData.map(item => item.Origin))];
297
+ origins.forEach(origin => {
298
+ const option = document.createElement('option');
299
+ option.value = option.textContent = origin;
300
+ originSelect.appendChild(option);
301
+ });
302
+ // Handle origin selection
303
+ let selectedDestinations = [];
304
+ originSelect.addEventListener('change', () => {
305
+ const origin = originSelect.value;
306
+ const destButtons = document.getElementById('destination-buttons');
307
+ destButtons.innerHTML = '';
308
+ selectedDestinations = [];
309
+ document.getElementById('fare-display').innerHTML = '';
310
+ if (origin) {
311
+ const destinations = fareData.filter(item => item.Origin === origin).map(item => item.Destination);
312
+ destinations.forEach(dest => {
313
+ const btn = document.createElement('button');
314
+ btn.textContent = `Select ${dest}`;
315
+ btn.dataset.dest = dest;
316
+ btn.addEventListener('click', () => {
317
+ btn.classList.toggle('selected');
318
+ if (btn.classList.contains('selected')) {
319
+ selectedDestinations.push(dest);
320
+ } else {
321
+ selectedDestinations = selectedDestinations.filter(d => d !== dest);
322
+ }
323
+ updateFareDisplay(origin);
324
+ });
325
+ destButtons.appendChild(btn);
326
+ });
327
+ }
328
+ });
329
+ // Update fare display
330
+ function updateFareDisplay(origin) {
331
+ const fareDisplay = document.getElementById('fare-display');
332
+ fareDisplay.innerHTML = '';
333
+ if (origin && selectedDestinations.length) {
334
+ selectedDestinations.forEach(dest => {
335
+ const fare = fareData.find(item => item.Origin === origin && item.Destination === dest);
336
+ if (fare) {
337
+ const div = document.createElement('div');
338
+ div.className = 'fare-item';
339
+ div.innerHTML = `
340
+ <h4>πŸš‡ <strong>${origin}</strong> to <strong>${dest}</strong> Fare</h4>
341
+ <p>πŸ’΅ Fare: <strong>${fare['Fare (ΰ§³)']}ΰ§³</strong></p>
342
+ <p>✨ Enjoy your journey!</p>
343
+ `;
344
+ fareDisplay.appendChild(div);
345
+ }
346
+ });
347
+ }
348
+ }
349
+ // Clear destinations
350
+ document.getElementById('clear-destinations').addEventListener('click', () => {
351
+ document.querySelectorAll('#destination-buttons button.selected').forEach(btn => {
352
+ btn.classList.remove('selected');
353
+ });
354
+ selectedDestinations = [];
355
+ updateFareDisplay(originSelect.value);
356
+ });
357
+ // Map setup
358
+ const coordinates = {
359
+ "Uttara North": [23.869066, 90.367445],
360
+ "Uttara Center": [23.860118, 90.365106],
361
+ "Uttara South": [23.845934, 90.363175],
362
+ "Pallabi": [23.82619516961383, 90.36481554252525],
363
+ "Mirpur 11": [23.819438208310213, 90.36528532902963],
364
+ "Mirpur 10": [23.808582994847285, 90.36821595330717],
365
+ "Kazipara": [23.800017952100532, 90.37178261495391],
366
+ "Shewrapara": [23.79070140857881, 90.37564622631841],
367
+ "Agargaon": [23.778385546736345, 90.3800557456356],
368
+ "Bijoy Sarani": [23.766638127271825, 90.38307537134754],
369
+ "Farmgate": [23.75923604938459, 90.38694218434738],
370
+ "Kawran Bazar": [23.751392319539104, 90.39275707447003],
371
+ "Shahbagh": [23.740324209546923, 90.39600784811131],
372
+ "Dhaka University": [23.732091083122114, 90.39659408796354],
373
+ "Bangladesh Secretariat": [23.73004754106779, 90.40764881366906],
374
+ "Motijheel": [23.72816566933198, 90.41923497972823],
375
+ "Kamalapur": [23.732367758919807, 90.42547378971085]
376
+ };
377
+ const map = L.map('map').setView([23.8103, 90.4125], 12);
378
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
379
+ maxZoom: 19,
380
+ attribution: 'Β© OpenStreetMap contributors'
381
+ }).addTo(map);
382
+ const markers = {};
383
+ for (const [name, coord] of Object.entries(coordinates)) {
384
+ markers[name] = L.marker(coord).addTo(map).bindPopup(`<b>${name}</b>`);
385
+ }
386
+ const mapSource = document.getElementById('map-source');
387
+ const mapDest = document.getElementById('map-destination');
388
+ Object.keys(coordinates).forEach(loc => {
389
+ const opt = document.createElement('option');
390
+ opt.value = opt.textContent = loc;
391
+ mapSource.appendChild(opt.cloneNode(true));
392
+ mapDest.appendChild(opt);
393
+ });
394
+ let currentIndex = 0;
395
+ const markerArray = Object.values(markers);
396
+ let animationTimeout;
397
+ function getIntermediateNodes(source, dest) {
398
+ const locations = Object.keys(coordinates);
399
+ const sIdx = locations.indexOf(source);
400
+ const dIdx = locations.indexOf(dest);
401
+ return sIdx < dIdx ? locations.slice(sIdx, dIdx + 1) : locations.slice(dIdx, sIdx + 1).reverse();
402
+ }
403
+ function startRouteAnimation() {
404
+ const source = mapSource.value;
405
+ const dest = mapDest.value;
406
+ if (!source || !dest) return alert('Select source and destination.');
407
+ const route = getIntermediateNodes(source, dest);
408
+ let idx = 0;
409
+ function animate() {
410
+ if (idx >= route.length) return;
411
+ const marker = markers[route[idx]];
412
+ map.flyTo(marker.getLatLng(), 14, { duration: 2 });
413
+ marker.openPopup();
414
+ idx++;
415
+ animationTimeout = setTimeout(animate, 3000);
416
+ }
417
+ animate();
418
+ }
419
+ function animateAllLocations() {
420
+ if (currentIndex > 0) markerArray[currentIndex - 1].closePopup();
421
+ if (currentIndex < markerArray.length) {
422
+ const marker = markerArray[currentIndex];
423
+ map.flyTo(marker.getLatLng(), 14, { duration: 2 });
424
+ marker.openPopup();
425
+ currentIndex++;
426
+ animationTimeout = setTimeout(animateAllLocations, 3000);
427
+ } else {
428
+ currentIndex = 0;
429
+ }
430
+ }
431
+ function stopAnimation() {
432
+ clearTimeout(animationTimeout);
433
+ currentIndex = 0;
434
+ markerArray.forEach(m => m.closePopup());
435
+ map.setView([23.8103, 90.4125], 12);
436
+ mapSource.value = mapDest.value = '';
437
+ }
438
+ </script>
439
+ </body>
440
+ </html>