Complete Beast format implementation with enhanced features and fixes #19
7 changed files with 174 additions and 1415 deletions
Clean up excessive console logging and remove duplicate app files
- Remove verbose console.log statements from WebSocket, map, and aircraft managers - Keep essential error messages and warnings for debugging - Consolidate app-new.js into app.js to eliminate confusing duplicate files - Update HTML reference to use clean app.js with incremented cache version - Significantly reduce console noise for better user experience 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
commit
776cef1185
|
|
@ -222,6 +222,6 @@
|
|||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
|
||||
<!-- Custom JS -->
|
||||
<script type="module" src="/static/js/app-new.js?v=3"></script>
|
||||
<script type="module" src="/static/js/app.js?v=4"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -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();
|
||||
});
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
BIN
beast-dump-with-heli.bin
Normal file
BIN
beast-dump-with-heli.bin
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue