"use strict"; // Flight Tracking Scheduler Service // Efficiently batches flight API calls and manages tracking schedules Object.defineProperty(exports, "__esModule", { value: true }); class FlightTrackingScheduler { constructor(flightService) { this.trackingSchedule = {}; this.checkIntervals = new Map(); this.flightService = flightService; } // Add flights for a VIP to the tracking schedule addVipFlights(vipId, vipName, flights) { flights.forEach(flight => { const key = flight.flightDate; if (!this.trackingSchedule[key]) { this.trackingSchedule[key] = []; } // Check if this flight is already being tracked const existingIndex = this.trackingSchedule[key].findIndex(f => f.flightNumber === flight.flightNumber && f.vipId === vipId); const scheduledFlight = { vipId, vipName, flightNumber: flight.flightNumber, flightDate: flight.flightDate, segment: flight.segment, scheduledDeparture: flight.validationData?.departure?.scheduled }; if (existingIndex >= 0) { // Update existing entry this.trackingSchedule[key][existingIndex] = scheduledFlight; } else { // Add new entry this.trackingSchedule[key].push(scheduledFlight); } }); // Start or update tracking for affected dates this.updateTrackingSchedules(); } // Remove VIP flights from tracking removeVipFlights(vipId) { Object.keys(this.trackingSchedule).forEach(date => { this.trackingSchedule[date] = this.trackingSchedule[date].filter(f => f.vipId !== vipId); // Remove empty dates if (this.trackingSchedule[date].length === 0) { delete this.trackingSchedule[date]; } }); this.updateTrackingSchedules(); } // Update tracking schedules based on current flights updateTrackingSchedules() { // Clear existing intervals this.checkIntervals.forEach(interval => clearInterval(interval)); this.checkIntervals.clear(); // Set up tracking for each date Object.keys(this.trackingSchedule).forEach(date => { this.setupDateTracking(date); }); } // Set up tracking for a specific date setupDateTracking(date) { const flights = this.trackingSchedule[date]; if (!flights || flights.length === 0) return; // Check if we should start tracking (4 hours before first flight) const now = new Date(); const dateObj = new Date(date + 'T00:00:00'); // Find earliest departure time let earliestDeparture = null; flights.forEach(flight => { if (flight.scheduledDeparture) { const depTime = new Date(flight.scheduledDeparture); if (!earliestDeparture || depTime < earliestDeparture) { earliestDeparture = depTime; } } }); // If no departure times, assume noon if (!earliestDeparture) { earliestDeparture = new Date(date + 'T12:00:00'); } // Start tracking 4 hours before earliest departure const trackingStartTime = new Date(earliestDeparture.getTime() - 4 * 60 * 60 * 1000); // If tracking should have started, begin immediately if (now >= trackingStartTime) { this.performBatchCheck(date); // Set up recurring checks every 60 minutes (or 30 if any delays) const interval = setInterval(() => { this.performBatchCheck(date); }, 60 * 60 * 1000); // 60 minutes this.checkIntervals.set(date, interval); } else { // Schedule first check for tracking start time const timeUntilStart = trackingStartTime.getTime() - now.getTime(); setTimeout(() => { this.performBatchCheck(date); // Then set up recurring checks const interval = setInterval(() => { this.performBatchCheck(date); }, 60 * 60 * 1000); this.checkIntervals.set(date, interval); }, timeUntilStart); } } // Perform batch check for all flights on a date async performBatchCheck(date) { const flights = this.trackingSchedule[date]; if (!flights || flights.length === 0) return; console.log(`\n=== Batch Flight Check for ${date} ===`); console.log(`Checking ${flights.length} flights...`); // Filter out flights that have already landed const activeFlights = flights.filter(f => !f.hasLanded); if (activeFlights.length === 0) { console.log('All flights have landed. Stopping tracking for this date.'); this.stopDateTracking(date); return; } // Get unique flight numbers to check const uniqueFlights = Array.from(new Set(activeFlights.map(f => f.flightNumber))); console.log(`Unique flight numbers to check: ${uniqueFlights.join(', ')}`); try { // Make batch API call const flightParams = uniqueFlights.map(flightNumber => ({ flightNumber, date })); const results = await this.flightService.getMultipleFlights(flightParams); // Update flight statuses let hasDelays = false; let allLanded = true; activeFlights.forEach(flight => { const key = `${flight.flightNumber}_${date}`; const data = results[key]; if (data) { flight.lastChecked = new Date(); flight.status = data.status; if (data.status === 'landed') { flight.hasLanded = true; console.log(`✅ ${flight.flightNumber} has landed`); } else { allLanded = false; if (data.delay && data.delay > 0) { hasDelays = true; console.log(`⚠️ ${flight.flightNumber} is delayed by ${data.delay} minutes`); } } // Log status for each VIP console.log(` VIP: ${flight.vipName} - Flight ${flight.segment}: ${flight.flightNumber} - Status: ${data.status}`); } }); // Update check frequency if delays detected if (hasDelays && this.checkIntervals.has(date)) { console.log('Delays detected - increasing check frequency to 30 minutes'); clearInterval(this.checkIntervals.get(date)); const interval = setInterval(() => { this.performBatchCheck(date); }, 30 * 60 * 1000); // 30 minutes this.checkIntervals.set(date, interval); } // Stop tracking if all flights have landed if (allLanded) { console.log('All flights have landed. Stopping tracking for this date.'); this.stopDateTracking(date); } // Calculate next check time const nextCheckTime = new Date(Date.now() + (hasDelays ? 30 : 60) * 60 * 1000); console.log(`Next check scheduled for: ${nextCheckTime.toLocaleTimeString()}`); } catch (error) { console.error('Error performing batch flight check:', error); } } // Stop tracking for a specific date stopDateTracking(date) { const interval = this.checkIntervals.get(date); if (interval) { clearInterval(interval); this.checkIntervals.delete(date); } // Mark all flights as completed if (this.trackingSchedule[date]) { this.trackingSchedule[date].forEach(f => f.hasLanded = true); } } // Get current tracking status getTrackingStatus() { const status = {}; Object.entries(this.trackingSchedule).forEach(([date, flights]) => { const activeFlights = flights.filter(f => !f.hasLanded); const landedFlights = flights.filter(f => f.hasLanded); status[date] = { totalFlights: flights.length, activeFlights: activeFlights.length, landedFlights: landedFlights.length, flights: flights.map(f => ({ vipName: f.vipName, flightNumber: f.flightNumber, segment: f.segment, status: f.status || 'Not checked yet', lastChecked: f.lastChecked, hasLanded: f.hasLanded })) }; }); return status; } // Clean up all tracking cleanup() { this.checkIntervals.forEach(interval => clearInterval(interval)); this.checkIntervals.clear(); this.trackingSchedule = {}; } } exports.default = FlightTrackingScheduler; //# sourceMappingURL=flightTrackingScheduler.js.map