Spaces:
Running
Running
| document.addEventListener('DOMContentLoaded', function() { | |
| // Initialize any interactive elements | |
| initDemoSimulation(); | |
| // Smooth scroll for anchor links | |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
| anchor.addEventListener('click', function (e) { | |
| e.preventDefault(); | |
| document.querySelector(this.getAttribute('href')).scrollIntoView({ | |
| behavior: 'smooth' | |
| }); | |
| }); | |
| }); | |
| }); | |
| async function initTransportSystem() { | |
| console.log("Initializing Delhi Metro system..."); | |
| try { | |
| // Load static GTFS data from GitHub repository | |
| const routes = await fetch('https://raw.githubusercontent.com/emote-warrior/GTFSDelhi/main/routes.txt') | |
| .then(res => res.text()); | |
| const trips = await fetch('https://raw.githubusercontent.com/emote-warrior/GTFSDelhi/main/trips.txt') | |
| .then(res => res.text()); | |
| const stops = await fetch('https://raw.githubusercontent.com/emote-warrior/GTFSDelhi/main/stops.txt') | |
| .then(res => res.text()); | |
| // Parse CSV data | |
| const routesData = parseCSV(routes); | |
| const tripsData = parseCSV(trips); | |
| const stopsData = parseCSV(stops); | |
| // Process and visualize data | |
| visualizeNetwork(routesData, tripsData, stopsData); | |
| updateRealTimeStatus(); | |
| } catch (error) { | |
| console.error('Error loading transport data:', error); | |
| document.querySelector('#network-visualization').innerHTML = | |
| `<p class="text-red-500">Error loading data. Please try again later.</p>`; | |
| } | |
| } | |
| function parseCSV(csvText) { | |
| const lines = csvText.split('\n'); | |
| const headers = lines[0].split(','); | |
| const result = []; | |
| for (let i = 1; i < lines.length; i++) { | |
| if (!lines[i]) continue; | |
| const obj = {}; | |
| const currentline = lines[i].split(','); | |
| for (let j = 0; j < headers.length; j++) { | |
| obj[headers[j]] = currentline[j]; | |
| } | |
| result.push(obj); | |
| } | |
| return result; | |
| } | |
| let map; | |
| let routeLayers = {}; | |
| let stopMarkers = {}; | |
| let tripLines = {}; | |
| function visualizeNetwork(routes, trips, stops) { | |
| // Initialize map centered on Delhi | |
| map = L.map('network-visualization').setView([28.6139, 77.2090], 12); | |
| // Add base tile layer | |
| L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { | |
| attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' | |
| }).addTo(map); | |
| // Process stops data (need to convert stop_lat/stop_lon to numbers) | |
| stops.forEach(stop => { | |
| stop.stop_lat = parseFloat(stop.stop_lat); | |
| stop.stop_lon = parseFloat(stop.stop_lon); | |
| }); | |
| // Group stops by route (simplified - in real app you'd use trips.txt and stop_times.txt) | |
| const stopsByRoute = {}; | |
| routes.forEach(route => { | |
| stopsByRoute[route.route_id] = stops.slice(0, 10); // Just show first 10 stops per route for demo | |
| }); | |
| // Create route layers | |
| routes.forEach(route => { | |
| const routeStops = stopsByRoute[route.route_id] || []; | |
| const routeCoordinates = routeStops.map(stop => [stop.stop_lat, stop.stop_lon]); | |
| routeLayers[route.route_id] = L.polyline(routeCoordinates, { | |
| color: `#${route.route_color || '333'}`, | |
| weight: 5, | |
| opacity: 0.7 | |
| }).bindPopup(`<b>${route.route_long_name}</b><br>Route ID: ${route.route_id}`); | |
| }); | |
| // Create stop markers | |
| stops.forEach(stop => { | |
| stopMarkers[stop.stop_id] = L.circleMarker([stop.stop_lat, stop.stop_lon], { | |
| radius: 6, | |
| fillColor: "#ff7800", | |
| color: "#000", | |
| weight: 1, | |
| opacity: 1, | |
| fillOpacity: 0.8 | |
| }).bindPopup(`<b>${stop.stop_name}</b><br>Stop ID: ${stop.stop_id}`); | |
| }); | |
| // Create trip lines (simplified - in real app you'd use actual trip paths) | |
| trips.slice(0, 20).forEach(trip => { // Limit to 20 trips for demo | |
| const routeStops = stopsByRoute[trip.route_id] || []; | |
| if (routeStops.length > 1) { | |
| const tripCoordinates = [ | |
| [routeStops[0].stop_lat, routeStops[0].stop_lon], | |
| [routeStops[routeStops.length-1].stop_lat, routeStops[routeStops.length-1].stop_lon] | |
| ]; | |
| tripLines[trip.trip_id] = L.polyline(tripCoordinates, { | |
| color: '#555', | |
| weight: 2, | |
| dashArray: '5, 5' | |
| }).bindPopup(`Trip ID: ${trip.trip_id}<br>Route: ${trip.route_id}`); | |
| } | |
| }); | |
| // Set up layer controls | |
| document.getElementById('show-routes').addEventListener('click', () => { | |
| Object.values(routeLayers).forEach(layer => map.addLayer(layer)); | |
| }); | |
| document.getElementById('show-stops').addEventListener('click', () => { | |
| Object.values(stopMarkers).forEach(marker => map.addLayer(marker)); | |
| }); | |
| document.getElementById('show-trips').addEventListener('click', () => { | |
| Object.values(tripLines).forEach(line => map.addLayer(line)); | |
| }); | |
| document.getElementById('reset-view').addEventListener('click', () => { | |
| map.setView([28.6139, 77.2090], 12); | |
| map.eachLayer(layer => { | |
| if (layer instanceof L.Polyline || layer instanceof L.CircleMarker) { | |
| map.removeLayer(layer); | |
| } | |
| }); | |
| }); | |
| // Show routes by default | |
| Object.values(routeLayers).forEach(layer => map.addLayer(layer)); | |
| } | |
| function updateRealTimeStatus() { | |
| // Simulate real-time updates | |
| setInterval(() => { | |
| const alerts = document.querySelectorAll('#current-alerts li'); | |
| const suggestions = document.querySelectorAll('#optimization-suggestions li'); | |
| // Rotate alerts and suggestions | |
| if (alerts.length > 0) { | |
| const firstAlert = alerts[0]; | |
| firstAlert.parentNode.appendChild(firstAlert); | |
| firstAlert.classList.add('animate-pulse'); | |
| setTimeout(() => firstAlert.classList.remove('animate-pulse'), 1000); | |
| } | |
| if (suggestions.length > 0) { | |
| const firstSuggestion = suggestions[0]; | |
| firstSuggestion.parentNode.appendChild(firstSuggestion); | |
| } | |
| }, 8000); | |
| } | |
| // Initialize on DOM load | |
| document.addEventListener('DOMContentLoaded', function() { | |
| initTransportSystem(); | |
| document.querySelectorAll('a[href^="#"]').forEach(anchor => { | |
| anchor.addEventListener('click', function (e) { | |
| e.preventDefault(); | |
| document.querySelector(this.getAttribute('href')).scrollIntoView({ | |
| behavior: 'smooth' | |
| }); | |
| }); | |
| }); | |
| }); | |