예제 #1
0
 /// <summary>
 /// Master constructor for the "top level" of our application
 /// TODO: create a factory method if initialization becomes complicated. Not needed now
 /// </summary>
 public FlightProcessor()
 {
     airports           = AirportCollection.LoadFromFile(AirportsFilePath);
     ProcessingType     = "file";
     EventsQueue        = new ConcurrentQueue <AdsbEvent>();
     FlightsQueue       = new ConcurrentQueue <Flight>();
     MainEventProcessor = new EventProcessor(FlightsQueue, airports);
 }
예제 #2
0
 /// <summary>
 /// Master constructor is used for unit tests. Clean it up later
 /// </summary>
 public FlightProcessor(string airportFile, string eventFile, string debugAirplane)
 {
     airports           = AirportCollection.LoadFromFile(airportFile);
     ProcessingType     = "file";
     EventsQueue        = new ConcurrentQueue <AdsbEvent>();
     FlightsQueue       = new ConcurrentQueue <Flight>();
     MainEventProcessor = new EventProcessor(FlightsQueue, airports);
     AdsbEventsFilePath = eventFile;
     DEBUG_FLIGHT       = debugAirplane;
 }
예제 #3
0
        private static void Execute()
        {
            // Load the input data
            AirportCollection   airports = AirportCollection.LoadFromFile(AirportsFilePath);
            AdsbEventCollection events   = AdsbEventCollection.LoadFromFile(AdsbEventsFilePath);

            // Create collection of identifiable flights
            FlightCollection flights = CalculateFlights(airports, events);

            // Write the output data
            flights.WriteToFile(OutputFilePath);
        }
예제 #4
0
 private static void Execute()
 {
     // Load the airports
     AirportCollection airports = AirportCollection.LoadFromFile(AirportsFilePath);
 }
예제 #5
0
        private static void Execute()
        {
            // Load the airports
            AirportCollection airports = AirportCollection.LoadFromFile(AirportsFilePath);

            var fileLines = System.IO.File.ReadAllLines(AdsbEventsFilePath);

            Dictionary <string, List <AdsbEvent> > airplanes = new Dictionary <string, List <AdsbEvent> >();

            foreach (var line in fileLines)
            {
                string airplaneId = Events.AdsbEvent.FromJson(line).Identifier;
                if (airplanes.ContainsKey(airplaneId))
                {
                    airplanes[airplaneId].Add(Events.AdsbEvent.FromJson(line));
                }
                else
                {
                    List <AdsbEvent> tmpEventList = new List <AdsbEvent>()
                    {
                        Events.AdsbEvent.FromJson(line)
                    };
                    airplanes.Add(Events.AdsbEvent.FromJson(line).Identifier, tmpEventList);
                }
            }

            System.IO.StreamWriter outFile = new System.IO.StreamWriter(OutputFilePath);

            foreach (var key in airplanes.Keys)
            {
                // debug output
                // System.Console.WriteLine(key);
                // setting defaults
                DateTime      prevTime            = DateTime.Parse("1/01/2020 12:00:00 AM");
                GeoCoordinate prevAirportLocation = null;
                Airport       prevAirport         = null;
                Flight        flight = new Flight();
                flight.AircraftIdentifier = key;

                foreach (var adsbEventEntry in airplanes[key])
                {
                    // create a geolocation based on airplane adsb event coords
                    string        latLong          = adsbEventEntry.Latitude.ToString() + "," + adsbEventEntry.Longitude.ToString();
                    GeoCoordinate airplaneLocation = GeoCoordinate.FromLatitudeAndLongitudeString(latLong);
                    // get closest airport based on current airplane location
                    Airport tempAirport = airports.GetClosestAirport(airplaneLocation);
                    // create airport geolocation
                    string        airportLatLong  = tempAirport.Latitude.ToString() + "," + tempAirport.Longitude.ToString();
                    GeoCoordinate airportLocation = GeoCoordinate.FromLatitudeAndLongitudeString(airportLatLong);

                    // In order for an event to be a landing/takeoff:
                    // 1. geolocation within 5 miles of an airport (Flight safety, no unregistered aircraft within 5 miles of an airport)
                    // 2. altitude diff within 500 feet (safety altitude)
                    // 3. take off and landing speed < 200 mph

                    // In order for an airport to have a takeoff for this airplane:
                    // 1. The timestamp reads must have a difference > 30 mins

                    // Airplane heading and speed is not always present in adsbevent data, which means we can't rely on it to determine landing vs takeoff
                    double tempDist = airplaneLocation.GetDistanceTo(airportLocation);
                    if (tempDist < 5)
                    {
                        if (adsbEventEntry.Altitude != null && (adsbEventEntry.Altitude - tempAirport.Elevation <= 500) && adsbEventEntry.Speed != null && adsbEventEntry.Speed <= 200)
                        {
                            //did some reasearch, it looks like it takes the crew around 30-60 mins to get the plane checked again for next flight
                            if (adsbEventEntry.Timestamp - prevTime > TimeSpan.Parse("00:30:00"))
                            {
                                // logic for arrivals and departures
                                if (prevAirportLocation != null && prevAirportLocation != airportLocation)
                                {
                                    //only departure is added w/ previous timestamp
                                    flight.DepartureTime    = prevTime;
                                    flight.DepartureAirport = prevAirport.Identifier;
                                }
                                else if (prevAirportLocation == airportLocation)
                                {
                                    //arrival is added w/ previous timestamp
                                    flight.ArrivalTime    = prevTime;
                                    flight.ArrivalAirport = prevAirport.Identifier;
                                }
                            }
                            prevAirportLocation = airportLocation;
                            prevTime            = adsbEventEntry.Timestamp;
                            prevAirport         = tempAirport;
                        }
                    }

                    //record flights if arrival time is populated
                    if (flight.ArrivalAirport != null)
                    {
                        outFile.WriteLine(flight.ToString());
                        flight = new Flight();
                        flight.AircraftIdentifier = key;
                    }
                }
            }

            outFile.Close();
        }
예제 #6
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);
        }