/** * Flight Display * This class handles displaying flight path on a map and flight information */ class FlightDisplay { /** * Create a flight display handler * @param {string} mapElementId - The ID of the element to render the map in * @param {string} infoElementId - The ID of the element to display flight info */ constructor(mapElementId, infoElementId) { this.mapElementId = mapElementId; this.infoElementId = infoElementId; this.map = null; this.flightPath = null; this.markers = { start: null, end: null }; this.initMap(); } /** * Initialize the Leaflet map */ initMap() { // Initialize the map this.map = L.map(this.mapElementId).setView([51.505, -0.09], 13); // Add OpenStreetMap tiles L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(this.map); } /** * Display the flight path and information * @param {object} flightData - Parsed flight data from IGCParser */ displayFlight(flightData) { if (!flightData || !flightData.fixes || flightData.fixes.length === 0) { return; } // Clear previous flight display this.clearFlight(); // Get coordinates for flight path const coordinates = flightData.fixes.map(fix => [fix.latitude, fix.longitude]); // Create a polyline for the flight path this.flightPath = L.polyline(coordinates, { color: '#4682b4', weight: 3, opacity: 0.8 }).addTo(this.map); // Add takeoff and landing markers const startPoint = coordinates[0]; const endPoint = coordinates[coordinates.length - 1]; this.markers.start = L.marker(startPoint, { title: 'Takeoff', icon: L.divIcon({ className: 'takeoff-marker', html: '
', iconSize: [16, 16], iconAnchor: [8, 8] }) }).addTo(this.map); this.markers.end = L.marker(endPoint, { title: 'Landing', icon: L.divIcon({ className: 'landing-marker', html: '', iconSize: [16, 16], iconAnchor: [8, 8] }) }).addTo(this.map); // Fit the map to show the entire flight path this.map.fitBounds(this.flightPath.getBounds(), { padding: [30, 30] }); // Display flight information this.displayFlightInfo(flightData); } /** * Clear the flight path and markers from the map */ clearFlight() { if (this.flightPath) { this.map.removeLayer(this.flightPath); this.flightPath = null; } if (this.markers.start) { this.map.removeLayer(this.markers.start); this.markers.start = null; } if (this.markers.end) { this.map.removeLayer(this.markers.end); this.markers.end = null; } } /** * Display flight information * @param {object} flightData - Parsed flight data */ displayFlightInfo(flightData) { const infoElement = document.getElementById(this.infoElementId); if (!infoElement) { console.error(`Element with ID ${this.infoElementId} not found`); return; } const header = flightData.header; const stats = flightData.stats; // Format duration const duration = this.formatDuration(stats.duration); // Format altitudes with 500m scale const altitudeScaleFactor = 500; const maxAltitudeScaled = (stats.maxAltitude / altitudeScaleFactor).toFixed(2); const minAltitudeScaled = (stats.minAltitude / altitudeScaleFactor).toFixed(2); // Create HTML for flight info const html = `| Date: | ${header.date || 'Unknown'} |
| Pilot: | ${header.pilot} |
| Glider: | ${header.gliderType} (${header.gliderReg}) |
| Duration: | ${duration} |
| Distance: | ${stats.distance.toFixed(2)} km |
| Max Altitude: | ${maxAltitudeScaled} x 500m (${stats.maxAltitude}m) |
| Min Altitude: | ${minAltitudeScaled} x 500m (${stats.minAltitude}m) |
| Max Climb: | ${stats.maxClimb.toFixed(1)} m/min |
| Max Sink: | ${stats.maxSink.toFixed(1)} m/min |