Beispiel #1
0
        public override void Configuration(IAppBuilder app)
        {
            var httpConfig = new HttpConfiguration();
            // this now returns ContainerBuilder instead of the container
            var builder = AutofacSetup.Register(httpConfig)
                          // register your mock, change this to whatever lifetime scope you need
                          var moqAirportCollection = new AirportCollection();

            moqAirportCollection.Airports = new List <Airport> {
                new Airport {
                    IATA = "moq", Name = "moqName"
                }
            };
            var mock = AutoMock.GetLoose()
                       var moqObj = MockObj = mock.Mock <IAirportService>()
                                              .Setup(x => x.GetAirports())
                                              .Returns(moqAirportCollection);

            builder.Register <IAirportService>(() => moqObj);


            container = builder.Build();
            WebApiConfig.Register(httpConfig);


            appBuilder.UseAutofacMiddleware(container);
            appBuilder.UseAutofacWebApi(httpConfig);
            appBuilder.UseWebApi(httpConfig);
        }
Beispiel #2
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);
 }
Beispiel #3
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;
 }
Beispiel #4
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);
        }
Beispiel #5
0
 /// <summary>
 /// Cntsructor. sets all the appropriate variables
 /// </summary>
 public AirplaneEventProcessor(IndividualAirplane individualAirplane, ConcurrentQueue <Flight> outputQueue, AirportCollection airportDB)
 {
     AirplaneProcessed   = individualAirplane;
     FlightsQueue        = outputQueue;
     Airports            = airportDB;
     LastEvent           = null;
     CurrentStatus       = AirplaneStatus.UNKNOWN;
     LastKnownPosition   = null;
     LastGrounded        = null;
     LastTakeoff         = null;
     LastDeviceSpeed     = null;
     LastDeviceSpeedTime = null;
 }
Beispiel #6
0
        public AirportCollection GetAllAirports()
        {
            AirportCollection results = new AirportCollection();
            IList             list    = AdoTemplate.QueryWithRowMapper(CommandType.Text,
                                                                       "SELECT * FROM airport", airportMapper);

            //TODO - add support to queries for supplying own collection implementation?
            // Why not using IResultSetExtrator ?
            foreach (Airport airport in list)
            {
                results.Add(airport);
            }
            return(results);
        }
Beispiel #7
0
 private static void Execute()
 {
     // Load the airports
     AirportCollection airports = AirportCollection.LoadFromFile(AirportsFilePath);
 }
Beispiel #8
0
        private static FlightCollection CalculateFlights(AirportCollection airports, AdsbEventCollection events)
        {
            // Organize all ADS-B events by aircraft ID
            FlightCollection flights = new FlightCollection();
            Dictionary <string, List <AdsbEvent> > eventsByID = new Dictionary <string, List <AdsbEvent> >();

            foreach (AdsbEvent adsbEvent in events.Events)
            {
                if (!eventsByID.ContainsKey(adsbEvent.Identifier))
                {
                    eventsByID.Add(adsbEvent.Identifier, new List <AdsbEvent>());
                    eventsByID[adsbEvent.Identifier].Add(adsbEvent);
                }
                else
                {
                    // Remove events that are soon after the previous one to improve performance
                    int       eventCount = eventsByID[adsbEvent.Identifier].Count;
                    AdsbEvent lastEvent  = eventsByID[adsbEvent.Identifier][eventCount - 1];
                    TimeSpan  timeDiff   = adsbEvent.Timestamp - lastEvent.Timestamp;
                    if (timeDiff.TotalSeconds >= TimeThreshold)
                    {
                        eventsByID[adsbEvent.Identifier].Add(adsbEvent);
                    }
                }
            }

            // For each aircraft identifier, step through the logged events in sequence to identify flights
            foreach (string identifier in eventsByID.Keys)
            {
                List <AdsbEvent> eventLog       = eventsByID[identifier];
                FlightStatus     flightStatus   = FlightStatus.Unknown;
                Airport          lastAirport    = new Airport();
                DateTime         lastGroundTime = DateTime.MinValue;
                foreach (AdsbEvent adsbEvent in eventLog)
                {
                    // Find closest airport to the logged coordinates, as long as the event has coordinate values
                    GeoCoordinate eventLoc = new GeoCoordinate(adsbEvent.Latitude ?? double.NaN, adsbEvent.Longitude ?? double.NaN);
                    if (eventLoc.HasLocation())
                    {
                        Airport       closestAirport  = airports.GetClosestAirport(eventLoc);
                        GeoCoordinate airportLoc      = new GeoCoordinate(closestAirport.Latitude, closestAirport.Longitude);
                        double        airportDistance = eventLoc.GetDistanceTo(airportLoc);
                        double        altitudeDiff    = adsbEvent.Altitude.HasValue ? Math.Abs(adsbEvent.Altitude.Value - closestAirport.Elevation) : 0f;
                        double        speed           = adsbEvent.Speed ?? 0f;

                        // If the event was logged close to an airport, assume the aircraft has landed at that airport
                        if (airportDistance <= DistanceThreshold && altitudeDiff <= AltitudeThreshold && speed <= SpeedThreshold)
                        {
                            // If this is not the first event (status unknown) and the new closest airport is different, create a new completed flight record
                            if (flightStatus != FlightStatus.Unknown && closestAirport.Identifier != lastAirport.Identifier)
                            {
                                flights.Flights.Add(new Flight
                                {
                                    AircraftIdentifier = identifier,
                                    DepartureTime      = lastGroundTime,
                                    DepartureAirport   = lastAirport.Identifier,
                                    ArrivalTime        = adsbEvent.Timestamp,
                                    ArrivalAirport     = closestAirport.Identifier
                                });
                            }
                            // In any case, update the status for the new airport
                            flightStatus   = FlightStatus.Ground;
                            lastAirport    = closestAirport;
                            lastGroundTime = adsbEvent.Timestamp;
                        }
                        // If the aircraft is not close to an airport and was not previously flying, set the status to airborne
                        else if ((airportDistance > DistanceThreshold || altitudeDiff > AltitudeThreshold) && flightStatus != FlightStatus.Air)
                        {
                            flightStatus = FlightStatus.Air;
                        }
                        // Otherwise, assume no status change
                    }
                }

                // If all events have been read and the aircraft was last known to be flying, record a final flight with no arrival
                if (flightStatus == FlightStatus.Air)
                {
                    flights.Flights.Add(new Flight
                    {
                        AircraftIdentifier = identifier,
                        DepartureTime      = lastGroundTime,
                        DepartureAirport   = lastAirport.Identifier,
                        ArrivalTime        = DateTime.MaxValue,
                        ArrivalAirport     = null
                    });
                }
            }

            return(flights);
        }
Beispiel #9
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();
        }
Beispiel #10
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);
        }
Beispiel #11
0
 public EventProcessor(ConcurrentQueue <Flight> outputQueue, AirportCollection airportDB)
 {
     IndividualPlaneProcessor = new Dictionary <string, AirplaneEventProcessor>();
     FlightsQueue             = outputQueue;
     Airports = airportDB;
 }