Esempio n. 1
0
        private static void Execute()
        {
            // Process data files
            var airports   = AirportCollection.LoadFromFile(AirportsFilePath);
            var adsbEvents = LoadFromFile(AdsbEventsFilePath);

            Console.WriteLine($"Loaded {airports.Count} airports and {adsbEvents.Count} events");

            // Sort events by aircraft
            var allAircraft = new Dictionary <string, Aircraft>();

            adsbEvents.ForEach((adsbEvent) =>
            {
                if (allAircraft.TryGetValue(adsbEvent.Identifier, out Aircraft aircraft))
                {
                    aircraft.AdsbEvents.Add(adsbEvent);
                }
                else
                {
                    allAircraft.Add(adsbEvent.Identifier,
                                    new Aircraft(adsbEvent.Identifier, new List <AdsbEvent>()
                    {
                        adsbEvent
                    }));
                }
            });

            Console.WriteLine($"Identified {allAircraft.Count} aircraft");

            // Find potential flights
            var flights = new List <Flight>();

            allAircraft.Select(kv => kv.Value).ToList().ForEach((aircraft) =>
            {
                var flight = new Flight()
                {
                    AircraftIdentifier = aircraft.AircraftIdentifier
                };

                // Filter out events without coordinates
                var aircraftEvents = aircraft.AdsbEvents
                                     .Where(adsbEvent => adsbEvent.Latitude != null && adsbEvent.Longitude != null)
                                     .OrderBy(adsbEvent => adsbEvent.Timestamp);

                // Implement a sliding window by analyzing the altitude data
                // This could also be implemented by analyzing the speed data, but the altitude data is
                // more consistent
                var events        = aircraftEvents.Where(adsbEvent => adsbEvent.Altitude != null);
                var step          = 10;
                var sampleSize    = 25;
                var previousTrend = Trend.Unknown;

                // Check the start events for departure
                var startSample = events.Take(sampleSize);
                if (startSample.First().Altitude < startSample.Last().Altitude)
                {
                    flight.DepartureTime    = events.First().Timestamp;
                    flight.DepartureAirport = airports.GetClosestAirport(events.First().GeoCoordinate).Identifier;
                }

                // Check the middle events for additional flights
                for (var i = 0; i < events.Count() - sampleSize; i += step)
                {
                    var sample       = events.Skip(i).Take(sampleSize);
                    var currentTrend = GuessTrend(sample.Select(adsbEvent => adsbEvent.Altitude.Value));

                    // If the aircraft's altitude trend changes from decreasing to increasing below the altitude threshold,
                    // assume that it's started a new flight
                    if (previousTrend == Trend.Decrease &&
                        currentTrend == Trend.Increase &&
                        sample.First().Altitude < MAX_ALTITUDE)
                    {
                        var airport = airports.GetClosestAirport(sample.First().GeoCoordinate);

                        // If there isn't an airport nearby, the airplane may have made an unexpected descent and ascent
                        if (airport == null)
                        {
                            continue;
                        }

                        // Check if the aircraft is flying over the airport
                        if (Math.Abs(airport.Elevation - sample.First().Altitude.Value) >= GROUND_TOLERANCE)
                        {
                            continue;
                        }

                        flight.ArrivalTime    = sample.First().Timestamp;
                        flight.ArrivalAirport = airport.Identifier;
                        flights.Add(flight);

                        flight = new Flight
                        {
                            AircraftIdentifier = aircraft.AircraftIdentifier,
                            DepartureTime      = sample.Last().Timestamp,
                            DepartureAirport   = airports.GetClosestAirport(sample.Last().GeoCoordinate).Identifier
                        };
                    }

                    previousTrend = currentTrend;
                }

                // Check the end events for arrival
                var endSample = events.TakeLast(sampleSize);

                if (endSample.First().Altitude > endSample.Last().Altitude)
                {
                    flight.ArrivalTime    = events.Last().Timestamp;
                    flight.ArrivalAirport = airports.GetClosestAirport(events.Last().GeoCoordinate).Identifier;
                }

                if (flight.DepartureAirport != null || flight.ArrivalAirport != null)
                {
                    flights.Add(flight);
                }
            });

            Console.WriteLine($"Identified {flights.Count} potential flights");
            WriteResults(flights);
        }