diff --git a/assets/static/index.html b/assets/static/index.html index 40ae4e3..4428bdd 100644 --- a/assets/static/index.html +++ b/assets/static/index.html @@ -222,6 +222,6 @@ - + \ No newline at end of file diff --git a/assets/static/js/app-new.js b/assets/static/js/app-new.js deleted file mode 100644 index 8800296..0000000 --- a/assets/static/js/app-new.js +++ /dev/null @@ -1,391 +0,0 @@ -// Import Three.js modules -import * as THREE from 'three'; -import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; - -// Import our modular components -import { WebSocketManager } from './modules/websocket.js?v=2'; -import { AircraftManager } from './modules/aircraft-manager.js?v=2'; -import { MapManager } from './modules/map-manager.js?v=2'; -import { UIManager } from './modules/ui-manager.js?v=2'; - -class SkyView { - constructor() { - console.log('🚀 SkyView v2 - KISS approach loaded'); - // Initialize managers - this.wsManager = null; - this.aircraftManager = null; - this.mapManager = null; - this.uiManager = null; - - // 3D Radar - this.radar3d = null; - - // Charts - this.charts = {}; - - this.init(); - } - - async init() { - try { - console.log('Initializing SkyView application...'); - - // Initialize UI manager first - this.uiManager = new UIManager(); - this.uiManager.initializeViews(); - this.uiManager.initializeEventListeners(); - - // Initialize map manager and get the main map - this.mapManager = new MapManager(); - const map = await this.mapManager.initializeMap(); - - // Initialize aircraft manager with the map - this.aircraftManager = new AircraftManager(map); - - // Initialize WebSocket with callbacks - this.wsManager = new WebSocketManager( - (message) => this.handleWebSocketMessage(message), - (status) => this.uiManager.updateConnectionStatus(status) - ); - - await this.wsManager.connect(); - - // Initialize other components - this.initializeCharts(); - this.uiManager.updateClocks(); - this.initialize3DRadar(); - - // Set up map controls - this.setupMapControls(); - - // Set up aircraft selection listener - this.setupAircraftSelection(); - - this.startPeriodicTasks(); - - console.log('SkyView application initialized successfully'); - } catch (error) { - console.error('Initialization failed:', error); - this.uiManager.showError('Failed to initialize application'); - } - } - - setupMapControls() { - const centerMapBtn = document.getElementById('center-map'); - const resetMapBtn = document.getElementById('reset-map'); - const toggleTrailsBtn = document.getElementById('toggle-trails'); - const toggleRangeBtn = document.getElementById('toggle-range'); - const toggleSourcesBtn = document.getElementById('toggle-sources'); - - if (centerMapBtn) { - centerMapBtn.addEventListener('click', () => this.aircraftManager.centerMapOnAircraft()); - } - - if (resetMapBtn) { - resetMapBtn.addEventListener('click', () => this.mapManager.resetMap()); - } - - if (toggleTrailsBtn) { - toggleTrailsBtn.addEventListener('click', () => { - const showTrails = this.aircraftManager.toggleTrails(); - toggleTrailsBtn.textContent = showTrails ? 'Hide Trails' : 'Show Trails'; - }); - } - - if (toggleRangeBtn) { - toggleRangeBtn.addEventListener('click', () => { - const showRange = this.mapManager.toggleRangeCircles(); - toggleRangeBtn.textContent = showRange ? 'Hide Range' : 'Show Range'; - }); - } - - if (toggleSourcesBtn) { - toggleSourcesBtn.addEventListener('click', () => { - const showSources = this.mapManager.toggleSources(); - toggleSourcesBtn.textContent = showSources ? 'Hide Sources' : 'Show Sources'; - }); - } - - // Coverage controls - const toggleHeatmapBtn = document.getElementById('toggle-heatmap'); - const coverageSourceSelect = document.getElementById('coverage-source'); - - if (toggleHeatmapBtn) { - toggleHeatmapBtn.addEventListener('click', async () => { - const isActive = await this.mapManager.toggleHeatmap(); - toggleHeatmapBtn.textContent = isActive ? 'Hide Heatmap' : 'Show Heatmap'; - }); - } - - if (coverageSourceSelect) { - coverageSourceSelect.addEventListener('change', (e) => { - this.mapManager.setSelectedSource(e.target.value); - this.mapManager.updateCoverageDisplay(); - }); - } - } - - setupAircraftSelection() { - document.addEventListener('aircraftSelected', (e) => { - const { icao, aircraft } = e.detail; - this.uiManager.switchView('map-view'); - - // DON'T change map view - just open popup like Leaflet expects - if (this.mapManager.map && aircraft.Latitude && aircraft.Longitude) { - const marker = this.aircraftManager.aircraftMarkers.get(icao); - if (marker) { - marker.openPopup(); - } - } - }); - } - - handleWebSocketMessage(message) { - switch (message.type) { - case 'initial_data': - console.log('Received initial data - setting up source markers'); - this.updateData(message.data); - // Setup source markers only on initial data load - this.mapManager.updateSourceMarkers(); - break; - case 'aircraft_update': - this.updateData(message.data); - break; - default: - console.log('Unknown message type:', message.type); - } - } - - updateData(data) { - // Update all managers with new data - this.uiManager.updateData(data); - this.aircraftManager.updateAircraftData(data); - this.mapManager.updateSourcesData(data); - - // Update UI components - this.aircraftManager.updateMarkers(); - this.uiManager.updateAircraftTable(); - this.uiManager.updateStatistics(); - this.uiManager.updateHeaderInfo(); - - // Update coverage controls - this.mapManager.updateCoverageControls(); - - if (this.uiManager.currentView === 'radar3d-view') { - this.update3DRadar(); - } - } - - // View switching - async switchView(viewId) { - const actualViewId = this.uiManager.switchView(viewId); - - // Handle view-specific initialization - const baseName = actualViewId.replace('-view', ''); - switch (baseName) { - case 'coverage': - await this.mapManager.initializeCoverageMap(); - break; - case 'radar3d': - this.update3DRadar(); - break; - } - } - - // Charts - initializeCharts() { - const aircraftChartCanvas = document.getElementById('aircraft-chart'); - if (!aircraftChartCanvas) { - console.warn('Aircraft chart canvas not found'); - return; - } - - try { - this.charts.aircraft = new Chart(aircraftChartCanvas, { - type: 'line', - data: { - labels: [], - datasets: [{ - label: 'Aircraft Count', - data: [], - borderColor: '#00d4ff', - backgroundColor: 'rgba(0, 212, 255, 0.1)', - tension: 0.4 - }] - }, - options: { - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { display: false } - }, - scales: { - x: { display: false }, - y: { - beginAtZero: true, - ticks: { color: '#888' } - } - } - } - }); - } catch (error) { - console.warn('Chart.js not available, skipping charts initialization'); - } - } - - updateCharts() { - if (!this.charts.aircraft) return; - - const now = new Date(); - const timeLabel = now.toLocaleTimeString(); - - // Update aircraft count chart - const chart = this.charts.aircraft; - chart.data.labels.push(timeLabel); - chart.data.datasets[0].data.push(this.aircraftManager.aircraftData.size); - - if (chart.data.labels.length > 20) { - chart.data.labels.shift(); - chart.data.datasets[0].data.shift(); - } - - chart.update('none'); - } - - // 3D Radar (basic implementation) - initialize3DRadar() { - try { - const container = document.getElementById('radar3d-container'); - if (!container) return; - - // Create scene - this.radar3d = { - scene: new THREE.Scene(), - camera: new THREE.PerspectiveCamera(75, container.clientWidth / container.clientHeight, 0.1, 1000), - renderer: new THREE.WebGLRenderer({ alpha: true, antialias: true }), - controls: null, - aircraftMeshes: new Map() - }; - - // Set up renderer - this.radar3d.renderer.setSize(container.clientWidth, container.clientHeight); - this.radar3d.renderer.setClearColor(0x0a0a0a, 0.9); - container.appendChild(this.radar3d.renderer.domElement); - - // Add lighting - const ambientLight = new THREE.AmbientLight(0x404040, 0.6); - this.radar3d.scene.add(ambientLight); - - const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8); - directionalLight.position.set(10, 10, 5); - this.radar3d.scene.add(directionalLight); - - // Set up camera - this.radar3d.camera.position.set(0, 50, 50); - this.radar3d.camera.lookAt(0, 0, 0); - - // Add controls - this.radar3d.controls = new OrbitControls(this.radar3d.camera, this.radar3d.renderer.domElement); - this.radar3d.controls.enableDamping = true; - this.radar3d.controls.dampingFactor = 0.05; - - // Add ground plane - const groundGeometry = new THREE.PlaneGeometry(200, 200); - const groundMaterial = new THREE.MeshLambertMaterial({ - color: 0x2a4d3a, - transparent: true, - opacity: 0.5 - }); - const ground = new THREE.Mesh(groundGeometry, groundMaterial); - ground.rotation.x = -Math.PI / 2; - this.radar3d.scene.add(ground); - - // Add grid - const gridHelper = new THREE.GridHelper(200, 20, 0x44aa44, 0x44aa44); - this.radar3d.scene.add(gridHelper); - - // Start render loop - this.render3DRadar(); - - console.log('3D Radar initialized successfully'); - } catch (error) { - console.error('Failed to initialize 3D radar:', error); - } - } - - update3DRadar() { - if (!this.radar3d || !this.radar3d.scene || !this.aircraftManager) return; - - try { - // Update aircraft positions in 3D space - this.aircraftManager.aircraftData.forEach((aircraft, icao) => { - if (aircraft.Latitude && aircraft.Longitude) { - const key = icao.toString(); - - if (!this.radar3d.aircraftMeshes.has(key)) { - // Create new aircraft mesh - const geometry = new THREE.ConeGeometry(0.5, 2, 6); - const material = new THREE.MeshLambertMaterial({ color: 0x00ff00 }); - const mesh = new THREE.Mesh(geometry, material); - this.radar3d.aircraftMeshes.set(key, mesh); - this.radar3d.scene.add(mesh); - } - - const mesh = this.radar3d.aircraftMeshes.get(key); - - // Convert lat/lon to local coordinates (simplified) - const x = (aircraft.Longitude - (-0.4600)) * 111320 * Math.cos(aircraft.Latitude * Math.PI / 180) / 1000; - const z = -(aircraft.Latitude - 51.4700) * 111320 / 1000; - const y = (aircraft.Altitude || 0) / 1000; // Convert feet to km for display - - mesh.position.set(x, y, z); - - // Orient mesh based on track - if (aircraft.Track !== undefined) { - mesh.rotation.y = -aircraft.Track * Math.PI / 180; - } - } - }); - - // Remove old aircraft - this.radar3d.aircraftMeshes.forEach((mesh, key) => { - if (!this.aircraftManager.aircraftData.has(key)) { - this.radar3d.scene.remove(mesh); - this.radar3d.aircraftMeshes.delete(key); - } - }); - } catch (error) { - console.error('Failed to update 3D radar:', error); - } - } - - render3DRadar() { - if (!this.radar3d) return; - - requestAnimationFrame(() => this.render3DRadar()); - - if (this.radar3d.controls) { - this.radar3d.controls.update(); - } - - this.radar3d.renderer.render(this.radar3d.scene, this.radar3d.camera); - } - - startPeriodicTasks() { - // Update clocks every second - setInterval(() => this.uiManager.updateClocks(), 1000); - - // Update charts every 10 seconds - setInterval(() => this.updateCharts(), 10000); - - // Periodic cleanup - setInterval(() => { - // Clean up old trail data, etc. - }, 30000); - } -} - -// Initialize application when DOM is ready -document.addEventListener('DOMContentLoaded', () => { - window.skyview = new SkyView(); -}); \ No newline at end of file diff --git a/assets/static/js/app.js b/assets/static/js/app.js index 20fef9b..5bf6e94 100644 --- a/assets/static/js/app.js +++ b/assets/static/js/app.js @@ -2,96 +2,184 @@ import * as THREE from 'three'; import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; +// Import our modular components +import { WebSocketManager } from './modules/websocket.js?v=2'; +import { AircraftManager } from './modules/aircraft-manager.js?v=2'; +import { MapManager } from './modules/map-manager.js?v=2'; +import { UIManager } from './modules/ui-manager.js?v=2'; + class SkyView { constructor() { - this.map = null; - this.coverageMap = null; + // Initialize managers + this.wsManager = null; + this.aircraftManager = null; + this.mapManager = null; + this.uiManager = null; + + // 3D Radar this.radar3d = null; - this.websocket = null; - - // Data storage - this.aircraftData = new Map(); - this.sourcesData = new Map(); - this.stats = {}; - - // Map markers and overlays - this.aircraftMarkers = new Map(); - this.sourceMarkers = new Map(); - this.aircraftTrails = new Map(); - this.rangeCircles = new Map(); - this.heatmapLayer = null; - - // UI state - this.currentView = 'map-view'; - this.showTrails = false; - this.showRange = false; - this.showSources = true; - this.selectedSource = null; // Charts this.charts = {}; - // Update tracking - this.lastUpdateTime = new Date(); - this.init(); } async init() { try { - this.initializeViews(); - this.initializeMap(); - await this.initializeWebSocket(); - this.initializeEventListeners(); + + // Initialize UI manager first + this.uiManager = new UIManager(); + this.uiManager.initializeViews(); + this.uiManager.initializeEventListeners(); + + // Initialize map manager and get the main map + this.mapManager = new MapManager(); + const map = await this.mapManager.initializeMap(); + + // Initialize aircraft manager with the map + this.aircraftManager = new AircraftManager(map); + + // Initialize WebSocket with callbacks + this.wsManager = new WebSocketManager( + (message) => this.handleWebSocketMessage(message), + (status) => this.uiManager.updateConnectionStatus(status) + ); + + await this.wsManager.connect(); + + // Initialize other components this.initializeCharts(); - this.initializeClocks(); + this.uiManager.updateClocks(); this.initialize3DRadar(); + // Set up map controls + this.setupMapControls(); + + // Set up aircraft selection listener + this.setupAircraftSelection(); + this.startPeriodicTasks(); + } catch (error) { console.error('Initialization failed:', error); - this.showError('Failed to initialize application'); + this.uiManager.showError('Failed to initialize application'); } } - // View Management - initializeViews() { - const viewButtons = document.querySelectorAll('.view-btn'); - const views = document.querySelectorAll('.view'); - - viewButtons.forEach(btn => { - btn.addEventListener('click', () => { - const viewId = btn.id.replace('-btn', ''); - this.switchView(viewId); + setupMapControls() { + const centerMapBtn = document.getElementById('center-map'); + const resetMapBtn = document.getElementById('reset-map'); + const toggleTrailsBtn = document.getElementById('toggle-trails'); + const toggleRangeBtn = document.getElementById('toggle-range'); + const toggleSourcesBtn = document.getElementById('toggle-sources'); + + if (centerMapBtn) { + centerMapBtn.addEventListener('click', () => this.aircraftManager.centerMapOnAircraft()); + } + + if (resetMapBtn) { + resetMapBtn.addEventListener('click', () => this.mapManager.resetMap()); + } + + if (toggleTrailsBtn) { + toggleTrailsBtn.addEventListener('click', () => { + const showTrails = this.aircraftManager.toggleTrails(); + toggleTrailsBtn.textContent = showTrails ? 'Hide Trails' : 'Show Trails'; }); + } + + if (toggleRangeBtn) { + toggleRangeBtn.addEventListener('click', () => { + const showRange = this.mapManager.toggleRangeCircles(); + toggleRangeBtn.textContent = showRange ? 'Hide Range' : 'Show Range'; + }); + } + + if (toggleSourcesBtn) { + toggleSourcesBtn.addEventListener('click', () => { + const showSources = this.mapManager.toggleSources(); + toggleSourcesBtn.textContent = showSources ? 'Hide Sources' : 'Show Sources'; + }); + } + + // Coverage controls + const toggleHeatmapBtn = document.getElementById('toggle-heatmap'); + const coverageSourceSelect = document.getElementById('coverage-source'); + + if (toggleHeatmapBtn) { + toggleHeatmapBtn.addEventListener('click', async () => { + const isActive = await this.mapManager.toggleHeatmap(); + toggleHeatmapBtn.textContent = isActive ? 'Hide Heatmap' : 'Show Heatmap'; + }); + } + + if (coverageSourceSelect) { + coverageSourceSelect.addEventListener('change', (e) => { + this.mapManager.setSelectedSource(e.target.value); + this.mapManager.updateCoverageDisplay(); + }); + } + } + + setupAircraftSelection() { + document.addEventListener('aircraftSelected', (e) => { + const { icao, aircraft } = e.detail; + this.uiManager.switchView('map-view'); + + // DON'T change map view - just open popup like Leaflet expects + if (this.mapManager.map && aircraft.Latitude && aircraft.Longitude) { + const marker = this.aircraftManager.aircraftMarkers.get(icao); + if (marker) { + marker.openPopup(); + } + } }); } - switchView(viewId) { - // Update buttons - document.querySelectorAll('.view-btn').forEach(btn => btn.classList.remove('active')); - const activeBtn = document.getElementById(`${viewId}-btn`); - if (activeBtn) { - activeBtn.classList.add('active'); + handleWebSocketMessage(message) { + switch (message.type) { + case 'initial_data': + this.updateData(message.data); + // Setup source markers only on initial data load + this.mapManager.updateSourceMarkers(); + break; + case 'aircraft_update': + this.updateData(message.data); + break; + default: } + } + + updateData(data) { + // Update all managers with new data + this.uiManager.updateData(data); + this.aircraftManager.updateAircraftData(data); + this.mapManager.updateSourcesData(data); - // Update views (viewId already includes the full view ID like "map-view") - document.querySelectorAll('.view').forEach(view => view.classList.remove('active')); - const activeView = document.getElementById(viewId); - if (activeView) { - activeView.classList.add('active'); - } else { - console.warn(`View element not found: ${viewId}`); - return; + // Update UI components + this.aircraftManager.updateMarkers(); + this.uiManager.updateAircraftTable(); + this.uiManager.updateStatistics(); + this.uiManager.updateHeaderInfo(); + + // Update coverage controls + this.mapManager.updateCoverageControls(); + + if (this.uiManager.currentView === 'radar3d-view') { + this.update3DRadar(); } + } + + // View switching + async switchView(viewId) { + const actualViewId = this.uiManager.switchView(viewId); - this.currentView = viewId; - - // Handle view-specific initialization (extract base name for switch) - const baseName = viewId.replace('-view', ''); + // Handle view-specific initialization + const baseName = actualViewId.replace('-view', ''); switch (baseName) { case 'coverage': - this.initializeCoverageMap(); + await this.mapManager.initializeCoverageMap(); break; case 'radar3d': this.update3DRadar(); @@ -99,889 +187,64 @@ class SkyView { } } - // Map Initialization - async initializeMap() { - // Get origin from server - let origin = { latitude: 51.4700, longitude: -0.4600 }; // fallback - try { - const response = await fetch('/api/origin'); - if (response.ok) { - origin = await response.json(); - } - } catch (error) { - console.warn('Could not fetch origin, using default:', error); - } - - // Store origin for reset functionality - this.mapOrigin = origin; - - this.map = L.map('map').setView([origin.latitude, origin.longitude], 10); - - // Dark tile layer - L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', { - attribution: '© OpenStreetMap contributors © CARTO', - subdomains: 'abcd', - maxZoom: 19 - }).addTo(this.map); - - // Map controls - document.getElementById('center-map').addEventListener('click', () => this.centerMapOnAircraft()); - document.getElementById('reset-map').addEventListener('click', () => this.resetMap()); - document.getElementById('toggle-trails').addEventListener('click', () => this.toggleTrails()); - document.getElementById('toggle-range').addEventListener('click', () => this.toggleRangeCircles()); - document.getElementById('toggle-sources').addEventListener('click', () => this.toggleSources()); - - // If we already have aircraft data waiting, update markers now that map is ready - if (this.aircraftData.size > 0) { - this.updateMapMarkers(); - } - } - - async initializeCoverageMap() { - if (!this.coverageMap) { - // Get origin from server - let origin = { latitude: 51.4700, longitude: -0.4600 }; // fallback - try { - const response = await fetch('/api/origin'); - if (response.ok) { - origin = await response.json(); - } - } catch (error) { - console.warn('Could not fetch origin for coverage map, using default:', error); - } - - this.coverageMap = L.map('coverage-map').setView([origin.latitude, origin.longitude], 10); - - L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png', { - attribution: '© OpenStreetMap contributors' - }).addTo(this.coverageMap); - } - - // Update coverage controls - this.updateCoverageControls(); - - // Coverage controls - document.getElementById('toggle-heatmap').addEventListener('click', () => this.toggleHeatmap()); - document.getElementById('coverage-source').addEventListener('change', (e) => { - this.selectedSource = e.target.value; - this.updateCoverageDisplay(); - }); - } - - // WebSocket Connection - async initializeWebSocket() { - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; - const wsUrl = `${protocol}//${window.location.host}/ws`; - - try { - this.websocket = new WebSocket(wsUrl); - - this.websocket.onopen = () => { - console.log('WebSocket connected'); - this.updateConnectionStatus('connected'); - }; - - this.websocket.onclose = () => { - console.log('WebSocket disconnected'); - this.updateConnectionStatus('disconnected'); - // Reconnect after 5 seconds - setTimeout(() => this.initializeWebSocket(), 5000); - }; - - this.websocket.onerror = (error) => { - console.error('WebSocket error:', error); - this.updateConnectionStatus('disconnected'); - }; - - this.websocket.onmessage = (event) => { - try { - const message = JSON.parse(event.data); - this.handleWebSocketMessage(message); - } catch (error) { - console.error('Failed to parse WebSocket message:', error); - } - }; - - } catch (error) { - console.error('WebSocket connection failed:', error); - this.updateConnectionStatus('disconnected'); - } - } - - handleWebSocketMessage(message) { - switch (message.type) { - case 'initial_data': - case 'aircraft_update': - this.updateData(message.data); - break; - default: - console.log('Unknown message type:', message.type); - } - } - - updateData(data) { - // Update aircraft data - if (data.aircraft) { - this.aircraftData.clear(); - for (const [icao, aircraft] of Object.entries(data.aircraft)) { - this.aircraftData.set(icao, aircraft); - } - } - - // Update sources data - if (data.sources) { - this.sourcesData.clear(); - data.sources.forEach(source => { - this.sourcesData.set(source.id, source); - }); - } - - // Update statistics - if (data.stats) { - this.stats = data.stats; - } - - this.lastUpdateTime = new Date(); - - // Update UI - this.updateMapMarkers(); - this.updateAircraftTable(); - this.updateStatistics(); - this.updateHeaderInfo(); - - if (this.currentView === 'radar3d-view') { - this.update3DRadar(); - } - } - - // Map Updates - updateMapMarkers() { - // Check if map is initialized - if (!this.map) { - return; - } - - // Clear stale aircraft markers - const currentICAOs = new Set(this.aircraftData.keys()); - for (const [icao, marker] of this.aircraftMarkers) { - if (!currentICAOs.has(icao)) { - this.map.removeLayer(marker); - this.aircraftMarkers.delete(icao); - this.aircraftTrails.delete(icao); - } - } - - // Update aircraft markers - only for aircraft with valid positions - // Note: Aircraft without positions are still shown in the table view - for (const [icao, aircraft] of this.aircraftData) { - if (aircraft.Latitude && aircraft.Longitude && aircraft.Latitude !== 0 && aircraft.Longitude !== 0) { - this.updateAircraftMarker(icao, aircraft); - } - } - - // Update source markers - if (this.showSources) { - this.updateSourceMarkers(); - } - - // Update range circles - if (this.showRange) { - this.updateRangeCircles(); - } - } - - updateAircraftMarker(icao, aircraft) { - const pos = [aircraft.Latitude, aircraft.Longitude]; - - if (this.aircraftMarkers.has(icao)) { - // Update existing marker - const marker = this.aircraftMarkers.get(icao); - marker.setLatLng(pos); - this.updateMarkerRotation(marker, aircraft.Track || 0); - this.updatePopupContent(marker, aircraft); - } else { - // Create new marker - const icon = this.createAircraftIcon(aircraft); - const marker = L.marker(pos, { - icon: icon, - rotationAngle: aircraft.Track || 0 - }).addTo(this.map); - - marker.bindPopup(this.createPopupContent(aircraft), { - maxWidth: 450, - className: 'aircraft-popup' - }); - - this.aircraftMarkers.set(icao, marker); - } - - // Update trails - if (this.showTrails) { - this.updateAircraftTrail(icao, pos); - } - } - - createAircraftIcon(aircraft) { - const type = this.getAircraftType(aircraft); - const color = this.getAircraftColor(type); - const size = aircraft.OnGround ? 12 : 16; - - const svg = ` - - - - - - `; - - return L.divIcon({ - html: svg, - iconSize: [size * 2, size * 2], - iconAnchor: [size, size], - className: 'aircraft-marker' - }); - } - - getAircraftType(aircraft) { - if (aircraft.OnGround) return 'ground'; - if (aircraft.Category) { - const cat = aircraft.Category.toLowerCase(); - if (cat.includes('military')) return 'military'; - if (cat.includes('cargo') || cat.includes('heavy')) return 'cargo'; - if (cat.includes('light') || cat.includes('glider')) return 'ga'; - } - if (aircraft.Callsign) { - const cs = aircraft.Callsign.toLowerCase(); - if (cs.includes('mil') || cs.includes('army') || cs.includes('navy')) return 'military'; - if (cs.includes('cargo') || cs.includes('fedex') || cs.includes('ups')) return 'cargo'; - } - return 'commercial'; - } - - getAircraftColor(type) { - const colors = { - commercial: '#00ff88', - cargo: '#ff8c00', - military: '#ff4444', - ga: '#ffff00', - ground: '#888888' - }; - return colors[type] || colors.commercial; - } - - updateMarkerRotation(marker, track) { - if (marker._icon) { - marker._icon.style.transform = `rotate(${track}deg)`; - } - } - - updateSourceMarkers() { - // Remove markers for sources that no longer exist - const currentSourceIds = new Set(this.sourcesData.keys()); - for (const [id, marker] of this.sourceMarkers) { - if (!currentSourceIds.has(id)) { - this.map.removeLayer(marker); - this.sourceMarkers.delete(id); - } - } - - // Update or create markers for current sources - for (const [id, source] of this.sourcesData) { - if (source.latitude && source.longitude) { - if (this.sourceMarkers.has(id)) { - // Update existing marker - const marker = this.sourceMarkers.get(id); - - // Update marker style if status changed - marker.setStyle({ - radius: source.active ? 10 : 6, - fillColor: source.active ? '#00d4ff' : '#666666', - fillOpacity: 0.8 - }); - - // Update popup content if it's open - if (marker.isPopupOpen()) { - marker.setPopupContent(this.createSourcePopupContent(source)); - } - } else { - // Create new marker - const marker = L.circleMarker([source.latitude, source.longitude], { - radius: source.active ? 10 : 6, - fillColor: source.active ? '#00d4ff' : '#666666', - color: '#ffffff', - weight: 2, - fillOpacity: 0.8, - className: 'source-marker' - }).addTo(this.map); - - marker.bindPopup(this.createSourcePopupContent(source), { - maxWidth: 300 - }); - - this.sourceMarkers.set(id, marker); - } - } - } - - this.updateSourcesLegend(); - } - - updateRangeCircles() { - // Clear existing circles - this.rangeCircles.forEach(circle => this.map.removeLayer(circle)); - this.rangeCircles.clear(); - - // Add range circles for active sources - for (const [id, source] of this.sourcesData) { - if (source.active && source.latitude && source.longitude) { - // Add multiple range circles (50km, 100km, 200km) - const ranges = [50000, 100000, 200000]; - ranges.forEach((range, index) => { - const circle = L.circle([source.latitude, source.longitude], { - radius: range, - fillColor: 'transparent', - color: '#00d4ff', - weight: 1, - opacity: 0.3 - (index * 0.1), - dashArray: '5,5' - }).addTo(this.map); - - this.rangeCircles.set(`${id}_${range}`, circle); - }); - } - } - } - - updateAircraftTrail(icao, pos) { - if (!this.aircraftTrails.has(icao)) { - this.aircraftTrails.set(icao, []); - } - - const trail = this.aircraftTrails.get(icao); - trail.push(pos); - - // Keep only last 50 positions - if (trail.length > 50) { - trail.shift(); - } - - // Draw polyline - const trailLine = L.polyline(trail, { - color: '#00d4ff', - weight: 2, - opacity: 0.6 - }).addTo(this.map); - - // Store reference for cleanup - if (!this.aircraftTrails.get(icao).polyline) { - this.aircraftTrails.get(icao).polyline = trailLine; - } else { - this.map.removeLayer(this.aircraftTrails.get(icao).polyline); - this.aircraftTrails.get(icao).polyline = trailLine; - } - } - - // Popup Content - createPopupContent(aircraft) { - const type = this.getAircraftType(aircraft); - const country = this.getCountryFromICAO(aircraft.ICAO24 || ''); - const flag = this.getCountryFlag(country); - - const altitude = aircraft.Altitude || aircraft.BaroAltitude || 0; - const altitudeM = altitude ? Math.round(altitude * 0.3048) : 0; - const speedKmh = aircraft.GroundSpeed ? Math.round(aircraft.GroundSpeed * 1.852) : 0; - const distance = this.calculateDistance(aircraft); - const distanceKm = distance ? (distance * 1.852).toFixed(1) : 'N/A'; - - const sources = aircraft.sources ? Object.keys(aircraft.sources).map(id => { - const source = this.sourcesData.get(id); - const srcData = aircraft.sources[id]; - return ` - ${source?.name || id} - `; - }).join('') : 'N/A'; - - return ` -
- - - -
- `; - } - - updatePopupContent(marker, aircraft) { - if (marker && marker.isPopupOpen()) { - const newContent = this.createPopupContent(aircraft); - marker.setPopupContent(newContent); - } - } - - createSourcePopupContent(source) { - const aircraftCount = Array.from(this.aircraftData.values()) - .filter(aircraft => aircraft.sources && aircraft.sources[source.id]).length; - - return ` -
-

${source.name}

-

ID: ${source.id}

-

Location: ${source.latitude.toFixed(4)}°, ${source.longitude.toFixed(4)}°

-

Status: ${source.active ? 'Active' : 'Inactive'}

-

Aircraft: ${aircraftCount}

-

Messages: ${source.messages || 0}

-

Last Seen: ${source.last_seen ? new Date(source.last_seen).toLocaleString() : 'N/A'}

-
- `; - } - - updateSourcesLegend() { - const legend = document.getElementById('sources-legend'); - legend.innerHTML = ''; - - for (const [id, source] of this.sourcesData) { - const item = document.createElement('div'); - item.className = 'legend-item'; - item.innerHTML = ` - - ${source.name} - `; - legend.appendChild(item); - } - } - - // Table Management - updateAircraftTable() { - // Note: This table shows ALL aircraft we're tracking, including those without - // position data. Aircraft without positions will show "No position" in the - // location column but still provide useful info like callsign, altitude, etc. - const tbody = document.getElementById('aircraft-tbody'); - tbody.innerHTML = ''; - - let filteredData = Array.from(this.aircraftData.values()); - - // Apply filters - const searchTerm = document.getElementById('search-input').value.toLowerCase(); - const sourceFilter = document.getElementById('source-filter').value; - - if (searchTerm) { - filteredData = filteredData.filter(aircraft => - (aircraft.Callsign && aircraft.Callsign.toLowerCase().includes(searchTerm)) || - (aircraft.ICAO24 && aircraft.ICAO24.toLowerCase().includes(searchTerm)) || - (aircraft.Squawk && aircraft.Squawk.includes(searchTerm)) - ); - } - - if (sourceFilter) { - filteredData = filteredData.filter(aircraft => - aircraft.sources && aircraft.sources[sourceFilter] - ); - } - - // Sort data - const sortBy = document.getElementById('sort-select').value; - this.sortAircraft(filteredData, sortBy); - - // Populate table - filteredData.forEach(aircraft => { - const row = this.createTableRow(aircraft); - tbody.appendChild(row); - }); - - // Update source filter options - this.updateSourceFilter(); - } - - createTableRow(aircraft) { - const type = this.getAircraftType(aircraft); - // ICAO24 is already a hex string from the server - const icao = aircraft.ICAO24 || 'N/A'; - const altitude = aircraft.Altitude || aircraft.BaroAltitude || 0; - const distance = this.calculateDistance(aircraft); - const sources = aircraft.sources ? Object.keys(aircraft.sources).length : 0; - const bestSignal = this.getBestSignalFromSources(aircraft.sources); - - const row = document.createElement('tr'); - row.innerHTML = ` - ${icao} - ${aircraft.Callsign || '-'} - ${aircraft.Squawk || '-'} - ${altitude ? `${altitude} ft` : '-'} - ${aircraft.GroundSpeed || '-'} kt - ${distance ? distance.toFixed(1) : '-'} km - ${aircraft.Track || '-'}° - ${sources} - ${bestSignal ? bestSignal.toFixed(1) : '-'} - ${aircraft.Age ? aircraft.Age.toFixed(0) : '0'}s - `; - - row.addEventListener('click', () => { - if (aircraft.Latitude && aircraft.Longitude) { - this.switchView('map'); - this.map.setView([aircraft.Latitude, aircraft.Longitude], 12); - const marker = this.aircraftMarkers.get(icao); - if (marker) { - marker.openPopup(); - } - } - }); - - return row; - } - - getBestSignalFromSources(sources) { - if (!sources) return null; - let bestSignal = -999; - for (const [id, data] of Object.entries(sources)) { - if (data.signal_level > bestSignal) { - bestSignal = data.signal_level; - } - } - return bestSignal === -999 ? null : bestSignal; - } - - getSignalClass(signal) { - if (!signal) return ''; - if (signal > -10) return 'signal-strong'; - if (signal > -20) return 'signal-good'; - if (signal > -30) return 'signal-weak'; - return 'signal-poor'; - } - - updateSourceFilter() { - const select = document.getElementById('source-filter'); - const currentValue = select.value; - - // Clear options except "All Sources" - select.innerHTML = ''; - - // Add source options - for (const [id, source] of this.sourcesData) { - const option = document.createElement('option'); - option.value = id; - option.textContent = source.name; - if (id === currentValue) option.selected = true; - select.appendChild(option); - } - } - - sortAircraft(aircraft, sortBy) { - aircraft.sort((a, b) => { - switch (sortBy) { - case 'distance': - return (this.calculateDistance(a) || Infinity) - (this.calculateDistance(b) || Infinity); - case 'altitude': - return (b.Altitude || b.BaroAltitude || 0) - (a.Altitude || a.BaroAltitude || 0); - case 'speed': - return (b.GroundSpeed || 0) - (a.GroundSpeed || 0); - case 'flight': - return (a.Callsign || a.ICAO24 || '').localeCompare(b.Callsign || b.ICAO24 || ''); - case 'icao': - return (a.ICAO24 || '').localeCompare(b.ICAO24 || ''); - case 'squawk': - return (a.Squawk || '').localeCompare(b.Squawk || ''); - case 'signal': - return (this.getBestSignalFromSources(b.sources) || -999) - (this.getBestSignalFromSources(a.sources) || -999); - case 'age': - return (a.Age || 0) - (b.Age || 0); - default: - return 0; - } - }); - } - - // Statistics - updateStatistics() { - document.getElementById('total-aircraft').textContent = this.aircraftData.size; - document.getElementById('active-sources').textContent = - Array.from(this.sourcesData.values()).filter(s => s.active).length; - - // Calculate max range - let maxDistance = 0; - for (const aircraft of this.aircraftData.values()) { - const distance = this.calculateDistance(aircraft); - if (distance && distance > maxDistance) { - maxDistance = distance; - } - } - document.getElementById('max-range').textContent = `${maxDistance.toFixed(1)} km`; - - // Update message rate - const totalMessages = this.stats.total_messages || 0; - document.getElementById('messages-sec').textContent = Math.round(totalMessages / 60); - - this.updateCharts(); - } - - updateHeaderInfo() { - document.getElementById('aircraft-count').textContent = `${this.aircraftData.size} aircraft`; - document.getElementById('sources-count').textContent = `${this.sourcesData.size} sources`; - - this.updateClocks(); - } - - // Event Listeners - initializeEventListeners() { - document.getElementById('search-input').addEventListener('input', () => this.updateAircraftTable()); - document.getElementById('sort-select').addEventListener('change', () => this.updateAircraftTable()); - document.getElementById('source-filter').addEventListener('change', () => this.updateAircraftTable()); - } - - // Map Controls - centerMapOnAircraft() { - if (this.aircraftData.size === 0) return; - - const validAircraft = Array.from(this.aircraftData.values()) - .filter(a => a.Latitude && a.Longitude); - - if (validAircraft.length === 0) return; - - if (validAircraft.length === 1) { - // Center on single aircraft - const aircraft = validAircraft[0]; - this.map.setView([aircraft.Latitude, aircraft.Longitude], 12); - } else { - // Fit bounds to all aircraft - const bounds = L.latLngBounds( - validAircraft.map(a => [a.Latitude, a.Longitude]) - ); - this.map.fitBounds(bounds.pad(0.1)); - } - } - - resetMap() { - if (this.mapOrigin && this.map) { - this.map.setView([this.mapOrigin.latitude, this.mapOrigin.longitude], 10); - } - } - - toggleTrails() { - this.showTrails = !this.showTrails; - document.getElementById('toggle-trails').textContent = - this.showTrails ? 'Hide Trails' : 'Show Trails'; - - if (!this.showTrails) { - // Clear all trails - this.aircraftTrails.forEach((trail, icao) => { - if (trail.polyline) { - this.map.removeLayer(trail.polyline); - } - }); - this.aircraftTrails.clear(); - } - } - - toggleRangeCircles() { - this.showRange = !this.showRange; - document.getElementById('toggle-range').textContent = - this.showRange ? 'Hide Range' : 'Show Range'; - - if (this.showRange) { - this.updateRangeCircles(); - } else { - this.rangeCircles.forEach(circle => this.map.removeLayer(circle)); - this.rangeCircles.clear(); - } - } - - toggleSources() { - this.showSources = !this.showSources; - document.getElementById('toggle-sources').textContent = - this.showSources ? 'Hide Sources' : 'Show Sources'; - - if (this.showSources) { - this.updateSourceMarkers(); - } else { - this.sourceMarkers.forEach(marker => this.map.removeLayer(marker)); - this.sourceMarkers.clear(); - } - } - - // Coverage and Heatmap - updateCoverageControls() { - const select = document.getElementById('coverage-source'); - select.innerHTML = ''; - - for (const [id, source] of this.sourcesData) { - const option = document.createElement('option'); - option.value = id; - option.textContent = source.name; - select.appendChild(option); - } - } - - async updateCoverageDisplay() { - if (!this.selectedSource) return; - - try { - const response = await fetch(`/api/coverage/${this.selectedSource}`); - const data = await response.json(); - - // Clear existing coverage markers - this.coverageMap.eachLayer(layer => { - if (layer instanceof L.CircleMarker) { - this.coverageMap.removeLayer(layer); - } - }); - - // Add coverage points - data.points.forEach(point => { - const intensity = Math.max(0, (point.signal + 50) / 50); // Normalize signal strength - L.circleMarker([point.lat, point.lon], { - radius: 3, - fillColor: this.getSignalColor(point.signal), - color: 'white', - weight: 1, - fillOpacity: intensity - }).addTo(this.coverageMap); - }); - - } catch (error) { - console.error('Failed to load coverage data:', error); - } - } - - async toggleHeatmap() { - if (!this.selectedSource) { - alert('Please select a source first'); - return; - } - - if (this.heatmapLayer) { - this.coverageMap.removeLayer(this.heatmapLayer); - this.heatmapLayer = null; - document.getElementById('toggle-heatmap').textContent = 'Show Heatmap'; - } else { - try { - const response = await fetch(`/api/heatmap/${this.selectedSource}`); - const data = await response.json(); - - // Create heatmap layer (simplified) - // In a real implementation, you'd use a proper heatmap library - this.createHeatmapOverlay(data); - document.getElementById('toggle-heatmap').textContent = 'Hide Heatmap'; - - } catch (error) { - console.error('Failed to load heatmap data:', error); - } - } - } - - getSignalColor(signal) { - if (signal > -10) return '#00ff88'; - if (signal > -20) return '#ffff00'; - if (signal > -30) return '#ff8c00'; - return '#ff4444'; - } - - // Charts (continued in next part due to length) + // Charts initializeCharts() { - this.charts.aircraft = new Chart(document.getElementById('aircraft-chart'), { - type: 'line', - data: { - labels: [], - datasets: [{ - label: 'Aircraft Count', - data: [], - borderColor: '#00d4ff', - backgroundColor: 'rgba(0, 212, 255, 0.1)', - tension: 0.4 - }] - }, - options: { - responsive: true, - maintainAspectRatio: false, - plugins: { - legend: { display: false } + const aircraftChartCanvas = document.getElementById('aircraft-chart'); + if (!aircraftChartCanvas) { + console.warn('Aircraft chart canvas not found'); + return; + } + + try { + this.charts.aircraft = new Chart(aircraftChartCanvas, { + type: 'line', + data: { + labels: [], + datasets: [{ + label: 'Aircraft Count', + data: [], + borderColor: '#00d4ff', + backgroundColor: 'rgba(0, 212, 255, 0.1)', + tension: 0.4 + }] }, - scales: { - x: { display: false }, - y: { - beginAtZero: true, - ticks: { color: '#888' } + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { display: false } + }, + scales: { + x: { display: false }, + y: { + beginAtZero: true, + ticks: { color: '#888' } + } } } - } - }); - - // Add other charts... + }); + } catch (error) { + console.warn('Chart.js not available, skipping charts initialization'); + } } updateCharts() { + if (!this.charts.aircraft) return; + const now = new Date(); const timeLabel = now.toLocaleTimeString(); // Update aircraft count chart - if (this.charts.aircraft) { - const chart = this.charts.aircraft; - chart.data.labels.push(timeLabel); - chart.data.datasets[0].data.push(this.aircraftData.size); - - if (chart.data.labels.length > 20) { - chart.data.labels.shift(); - chart.data.datasets[0].data.shift(); - } - - chart.update('none'); + const chart = this.charts.aircraft; + chart.data.labels.push(timeLabel); + chart.data.datasets[0].data.push(this.aircraftManager.aircraftData.size); + + if (chart.data.labels.length > 20) { + chart.data.labels.shift(); + chart.data.datasets[0].data.shift(); } + + chart.update('none'); } // 3D Radar (basic implementation) @@ -1039,18 +302,17 @@ class SkyView { // Start render loop this.render3DRadar(); - console.log('3D Radar initialized successfully'); } catch (error) { console.error('Failed to initialize 3D radar:', error); } } update3DRadar() { - if (!this.radar3d || !this.radar3d.scene) return; + if (!this.radar3d || !this.radar3d.scene || !this.aircraftManager) return; try { // Update aircraft positions in 3D space - this.aircraftData.forEach((aircraft, icao) => { + this.aircraftManager.aircraftData.forEach((aircraft, icao) => { if (aircraft.Latitude && aircraft.Longitude) { const key = icao.toString(); @@ -1081,7 +343,7 @@ class SkyView { // Remove old aircraft this.radar3d.aircraftMeshes.forEach((mesh, key) => { - if (!this.aircraftData.has(parseInt(key, 16))) { + if (!this.aircraftManager.aircraftData.has(key)) { this.radar3d.scene.remove(mesh); this.radar3d.aircraftMeshes.delete(key); } @@ -1103,99 +365,18 @@ class SkyView { this.radar3d.renderer.render(this.radar3d.scene, this.radar3d.camera); } - // Utility functions - updateConnectionStatus(status) { - const statusEl = document.getElementById('connection-status'); - statusEl.className = `connection-status ${status}`; - statusEl.textContent = status === 'connected' ? 'Connected' : 'Disconnected'; - } - - initializeClocks() { - this.updateClocks(); - } - - updateClocks() { - const now = new Date(); - const utcNow = new Date(now.getTime() + (now.getTimezoneOffset() * 60000)); - - this.updateClock('utc', utcNow); - this.updateClock('update', this.lastUpdateTime); - } - - updateClock(prefix, time) { - const hours = time.getUTCHours(); - const minutes = time.getUTCMinutes(); - - const hourAngle = (hours % 12) * 30 + minutes * 0.5; - const minuteAngle = minutes * 6; - - const hourHand = document.getElementById(`${prefix}-hour`); - const minuteHand = document.getElementById(`${prefix}-minute`); - - if (hourHand) hourHand.style.transform = `rotate(${hourAngle}deg)`; - if (minuteHand) minuteHand.style.transform = `rotate(${minuteAngle}deg)`; - } - - calculateDistance(aircraft) { - if (!aircraft.Latitude || !aircraft.Longitude) return null; - - // Use closest source as reference point - let minDistance = Infinity; - for (const [id, srcData] of Object.entries(aircraft.sources || {})) { - if (srcData.distance && srcData.distance < minDistance) { - minDistance = srcData.distance; - } - } - - return minDistance === Infinity ? null : minDistance; - } - - getCountryFromICAO(icao) { - if (!icao || icao.length < 6) return 'Unknown'; - - const prefix = icao[0]; - const countryMap = { - '4': 'Europe', - 'A': 'United States', - 'C': 'Canada', - 'D': 'Germany', - 'F': 'France', - 'G': 'United Kingdom', - 'I': 'Italy', - 'J': 'Japan' - }; - - return countryMap[prefix] || 'Unknown'; - } - - getCountryFlag(country) { - const flags = { - 'United States': '🇺🇸', - 'Canada': '🇨🇦', - 'Germany': '🇩🇪', - 'France': '🇫🇷', - 'United Kingdom': '🇬🇧', - 'Italy': '🇮🇹', - 'Japan': '🇯🇵', - 'Europe': '🇪🇺' - }; - return flags[country] || '🏳️'; - } - startPeriodicTasks() { // Update clocks every second - setInterval(() => this.updateClocks(), 1000); + setInterval(() => this.uiManager.updateClocks(), 1000); + + // Update charts every 10 seconds + setInterval(() => this.updateCharts(), 10000); // Periodic cleanup setInterval(() => { // Clean up old trail data, etc. }, 30000); } - - showError(message) { - console.error(message); - // Could implement toast notifications here - } } // Initialize application when DOM is ready diff --git a/assets/static/js/modules/aircraft-manager.js b/assets/static/js/modules/aircraft-manager.js index a5351cb..82d3b76 100644 --- a/assets/static/js/modules/aircraft-manager.js +++ b/assets/static/js/modules/aircraft-manager.js @@ -22,7 +22,6 @@ export class AircraftManager { for (const [icao, aircraft] of Object.entries(data.aircraft)) { this.aircraftData.set(icao, aircraft); } - console.log(`Aircraft data updated: ${this.aircraftData.size} aircraft`); } } @@ -57,9 +56,6 @@ export class AircraftManager { updateAircraftMarker(icao, aircraft) { const pos = [aircraft.Latitude, aircraft.Longitude]; - // Debug: Log coordinate format and values - console.log(`📍 ${icao}: pos=[${pos[0]}, ${pos[1]}], types=[${typeof pos[0]}, ${typeof pos[1]}]`); - console.log(`🔍 Marker check for ${icao}: has=${this.aircraftMarkers.has(icao)}, map_size=${this.aircraftMarkers.size}`); // Check for invalid coordinates - proper geographic bounds const isValidLat = pos[0] >= -90 && pos[0] <= 90; @@ -76,7 +72,6 @@ export class AircraftManager { // Always update position - let Leaflet handle everything const oldPos = marker.getLatLng(); - console.log(`🔄 Updating ${icao}: [${oldPos.lat}, ${oldPos.lng}] -> [${pos[0]}, ${pos[1]}]`); marker.setLatLng(pos); // Update rotation using Leaflet's options if available, otherwise skip rotation @@ -100,7 +95,6 @@ export class AircraftManager { } else { // Create new marker - console.log(`Creating new marker for ${icao}`); const icon = this.createAircraftIcon(aircraft); try { @@ -116,14 +110,12 @@ export class AircraftManager { this.aircraftMarkers.set(icao, marker); this.markerCreateCount++; - console.log(`Created marker for ${icao}, total markers: ${this.aircraftMarkers.size}`); // Force immediate visibility if (marker._icon) { marker._icon.style.display = 'block'; marker._icon.style.opacity = '1'; marker._icon.style.visibility = 'visible'; - console.log(`Forced visibility for new marker ${icao}`); } } catch (error) { console.error(`Failed to create marker for ${icao}:`, error); @@ -442,8 +434,4 @@ export class AircraftManager { } } - // Simple debug method - debugState() { - console.log(`Aircraft: ${this.aircraftData.size}, Markers: ${this.aircraftMarkers.size}`); - } } \ No newline at end of file diff --git a/assets/static/js/modules/map-manager.js b/assets/static/js/modules/map-manager.js index 0f93fec..e4716c9 100644 --- a/assets/static/js/modules/map-manager.js +++ b/assets/static/js/modules/map-manager.js @@ -32,7 +32,6 @@ export class MapManager { // Store origin for reset functionality this.mapOrigin = origin; - console.log(`🗺️ Map origin: [${origin.latitude}, ${origin.longitude}]`); this.map = L.map('map').setView([origin.latitude, origin.longitude], 10); // Dark tile layer @@ -42,7 +41,6 @@ export class MapManager { maxZoom: 19 }).addTo(this.map); - console.log('Main map initialized'); return this.map; } @@ -307,7 +305,6 @@ export class MapManager { createHeatmapOverlay(data) { // Simplified heatmap implementation // In production, would use proper heatmap library like Leaflet.heat - console.log('Creating heatmap overlay with data:', data); } setSelectedSource(sourceId) { diff --git a/assets/static/js/modules/websocket.js b/assets/static/js/modules/websocket.js index 40e08f7..5fa733c 100644 --- a/assets/static/js/modules/websocket.js +++ b/assets/static/js/modules/websocket.js @@ -14,12 +14,10 @@ export class WebSocketManager { this.websocket = new WebSocket(wsUrl); this.websocket.onopen = () => { - console.log('WebSocket connected'); this.onStatusChange('connected'); }; this.websocket.onclose = () => { - console.log('WebSocket disconnected'); this.onStatusChange('disconnected'); // Reconnect after 5 seconds setTimeout(() => this.connect(), 5000); @@ -34,20 +32,6 @@ export class WebSocketManager { try { const message = JSON.parse(event.data); - // Debug: Log WebSocket messages to see what we're receiving - if (message.data && message.data.aircraft) { - const aircraftCount = Object.keys(message.data.aircraft).length; - console.log(`📡 WebSocket: ${message.type} with ${aircraftCount} aircraft`); - - // Log first few aircraft with coordinates - let count = 0; - for (const [icao, aircraft] of Object.entries(message.data.aircraft)) { - if (count < 3 && aircraft.Latitude && aircraft.Longitude) { - console.log(`📡 ${icao}: lat=${aircraft.Latitude}, lon=${aircraft.Longitude}`); - } - count++; - } - } this.onMessage(message); } catch (error) { diff --git a/beast-dump-with-heli.bin b/beast-dump-with-heli.bin new file mode 100644 index 0000000..fa579ea Binary files /dev/null and b/beast-dump-with-heli.bin differ