Esempio n. 1
0
        /// <summary>
        /// Sorts the aircraft list using the parameters in the args object.
        /// </summary>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>]
        /// <param name="distances"></param>
        private void SortAircraft(List <IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, Dictionary <int, double?> distances)
        {
            IAircraftComparer comparer = Factory.Singleton.Resolve <IAircraftComparer>();

            comparer.BrowserLocation = args.BrowserLatitude == null || args.BrowserLongitude == null ? null : new Coordinate((float)args.BrowserLatitude, (float)args.BrowserLongitude);
            foreach (var sortBy in args.SortBy)
            {
                comparer.SortBy.Add(sortBy);
            }
            foreach (var distance in distances)
            {
                comparer.PrecalculatedDistances.Add(distance.Key, distance.Value);
            }

            aircraftListSnapshot.Sort(comparer);
        }
Esempio n. 2
0
        /// <summary>
        /// Creates an object that holds all of the aircraft list arguments that were extracted from the request.
        /// </summary>
        /// <param name="args"></param>
        /// <param name="aircraftList"></param>
        /// <param name="isFlightSimulator"></param>
        /// <returns></returns>
        private AircraftListJsonBuilderArgs ConstructBuildArgs(RequestReceivedEventArgs args, IAircraftList aircraftList, bool isFlightSimulator)
        {
            var result = new AircraftListJsonBuilderArgs()
            {
                AircraftList          = aircraftList,
                BrowserLatitude       = QueryNDouble(args, "lat"),
                BrowserLongitude      = QueryNDouble(args, "lng"),
                Filter                = isFlightSimulator ? null : ConstructFilter(args),
                IsFlightSimulatorList = isFlightSimulator,
                IsInternetClient      = args.IsInternetRequest,
                PreviousDataVersion   = QueryLong(args, "ldv", -1),
                ResendTrails          = QueryString(args, "refreshTrails", false) == "1",
                ShowShortTrail        = QueryString(args, "trFmt", true) == "S",
            };

            for (int sortColumnCount = 0; sortColumnCount < 2; ++sortColumnCount)
            {
                var sortColumn = QueryString(args, String.Format("sortBy{0}", sortColumnCount + 1), true);
                var sortOrder  = QueryString(args, String.Format("sortOrder{0}", sortColumnCount + 1), true);
                if (String.IsNullOrEmpty(sortColumn) || String.IsNullOrEmpty(sortOrder))
                {
                    break;
                }
                result.SortBy.Add(new KeyValuePair <string, bool>(sortColumn, sortOrder == "ASC"));
            }
            if (result.SortBy.Count == 0)
            {
                result.SortBy.Add(new KeyValuePair <string, bool>(AircraftComparerColumn.FirstSeen, false));
            }

            var previousAircraftIds = args.Request.Headers["X-VirtualRadarServer-AircraftIds"];

            if (!String.IsNullOrEmpty(previousAircraftIds))
            {
                var decodedPreviousAircraftIds = HttpUtility.UrlDecode(previousAircraftIds);
                foreach (var chunk in decodedPreviousAircraftIds.Split(','))
                {
                    int id;
                    if (int.TryParse(chunk, out id))
                    {
                        result.PreviousAircraft.Add(id);
                    }
                }
            }

            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Returns a fully-formed <see cref="AircraftListJson"/> from the aircraft list passed across.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public AircraftListJson Build(AircraftListJsonBuilderArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("aircraftList");
            }
            if (args.AircraftList == null)
            {
                throw new InvalidOperationException("The AircraftList must be supplied");
            }

            var result = new AircraftListJson()
            {
                FlagHeight              = 20,
                FlagWidth               = 85,
                ShowFlags               = _ShowFlags && !args.IsFlightSimulatorList,
                ShowPictures            = _ShowPictures && (!args.IsInternetClient || _ShowPicturesToInternetClients) && !args.IsFlightSimulatorList,
                ShowSilhouettes         = _ShowSilhouettes && !args.IsFlightSimulatorList,
                ShortTrailLengthSeconds = _ShortTrailLength,
                Source = (int)args.AircraftList.Source,
            };

            long timestamp, dataVersion;
            var  aircraft = args.AircraftList.TakeSnapshot(out timestamp, out dataVersion);

            result.AvailableAircraft = aircraft.Count;
            result.LastDataVersion   = dataVersion.ToString();
            result.ServerTime        = JavascriptHelper.ToJavascriptTicks(timestamp);

            Dictionary <int, double?> distances = new Dictionary <int, double?>();

            aircraft = FilterAircraft(aircraft, args, ref distances);
            SortAircraft(aircraft, args, distances);
            CopyAircraft(result, aircraft, args, distances);

            return(result);
        }
        /// <summary>
        /// Builds the full or short coordinates list and attaches it to the aircraft JSON object.
        /// </summary>
        /// <param name="shortCoordinates"></param>
        /// <param name="firstTimeSeen"></param>
        /// <param name="aircraftJson"></param>
        /// <param name="aircraftSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="sendAltitude"></param>
        /// <param name="sendSpeed"></param>
        private void BuildCoordinatesList(bool shortCoordinates, bool firstTimeSeen, AircraftJson aircraftJson, IAircraft aircraftSnapshot, AircraftListJsonBuilderArgs args, bool sendAltitude, bool sendSpeed)
        {
            aircraftJson.ResetTrail = firstTimeSeen || args.ResendTrails || aircraftSnapshot.FirstCoordinateChanged > args.PreviousDataVersion;
            List <double?> list = new List <double?>();

            List <Coordinate> coordinates    = shortCoordinates ? aircraftSnapshot.ShortCoordinates : aircraftSnapshot.FullCoordinates;
            Coordinate        lastCoordinate = null;
            Coordinate        nextCoordinate = null;

            for (var i = 0; i < coordinates.Count; ++i)
            {
                var coordinate = nextCoordinate ?? coordinates[i];
                nextCoordinate = i + 1 == coordinates.Count ? null : coordinates[i + 1];

                if (aircraftJson.ResetTrail || coordinate.DataVersion > args.PreviousDataVersion)
                {
                    // If this is a full coordinate list then entries can be in here that only record a change in altitude or speed, and not a change in track. Those
                    // entries are to be ignored. They can be identified by having a track that is the same as their immediate neighbours in the list.
                    if (!shortCoordinates && lastCoordinate != null && nextCoordinate != null)
                    {
                        var dupeHeading = lastCoordinate.Heading == coordinate.Heading && coordinate.Heading == nextCoordinate.Heading;
                        if (dupeHeading && !sendAltitude && !sendSpeed)
                        {
                            continue;
                        }
                        var dupeAltitude = lastCoordinate.Altitude == coordinate.Altitude && coordinate.Altitude == nextCoordinate.Altitude;
                        if (sendAltitude && dupeHeading && dupeAltitude)
                        {
                            continue;
                        }
                        var dupeSpeed = lastCoordinate.GroundSpeed == coordinate.GroundSpeed && coordinate.GroundSpeed == nextCoordinate.GroundSpeed;
                        if (sendSpeed && dupeHeading && dupeSpeed)
                        {
                            continue;
                        }
                    }

                    list.Add(Round.Coordinate(coordinate.Latitude));
                    list.Add(Round.Coordinate(coordinate.Longitude));
                    if (shortCoordinates)
                    {
                        list.Add(JavascriptHelper.ToJavascriptTicks(coordinate.Tick));
                    }
                    else
                    {
                        list.Add((int?)coordinate.Heading);
                    }
                    if (sendAltitude)
                    {
                        list.Add(coordinate.Altitude);
                    }
                    else if (sendSpeed)
                    {
                        list.Add(coordinate.GroundSpeed);
                    }
                }

                lastCoordinate = coordinate;
            }

            if (aircraftSnapshot.Latitude != null && aircraftSnapshot.Longitude != null &&
                (lastCoordinate.Latitude != aircraftSnapshot.Latitude || lastCoordinate.Longitude != aircraftSnapshot.Longitude) &&
                aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion)
            {
                list.Add(Round.Coordinate(aircraftSnapshot.Latitude));
                list.Add(Round.Coordinate(aircraftSnapshot.Longitude));
                if (shortCoordinates)
                {
                    list.Add(JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value));
                }
                else
                {
                    list.Add((int?)Round.TrackHeading(aircraftSnapshot.Track));
                }
                if (sendAltitude)
                {
                    list.Add(Round.TrackAltitude(aircraftSnapshot.Altitude));
                }
                else if (sendSpeed)
                {
                    list.Add(Round.TrackGroundSpeed(aircraftSnapshot.GroundSpeed));
                }
            }

            if (list.Count != 0)
            {
                if (shortCoordinates)
                {
                    aircraftJson.ShortCoordinates = list;
                }
                else
                {
                    aircraftJson.FullCoordinates = list;
                }
            }
        }
        /// <summary>
        /// Copies the aircraft from the snapshot to the JSON object.
        /// </summary>
        /// <param name="aircraftListJson"></param>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        private void CopyAircraft(AircraftListJson aircraftListJson, List <IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, Dictionary <int, double?> distances)
        {
            var now                      = Provider.UtcNow;
            var configuration            = _SharedConfiguration.Get();
            var positionTimeoutThreshold = now.AddSeconds(-(configuration.BaseStationSettings.DisplayTimeoutSeconds + BoostStalePositionSeconds));

            HashSet <int> previousAircraftSet = null;
            List <int>    previousAircraft    = args.PreviousAircraft;

            if (previousAircraft.Count > 15)
            {
                previousAircraftSet = new HashSet <int>(previousAircraft);
                previousAircraft    = null;
            }

            double?distance = null;

            for (var i = 0; i < aircraftListSnapshot.Count; ++i)
            {
                var aircraftSnapshot = aircraftListSnapshot[i];
                if (distances != null)
                {
                    distances.TryGetValue(aircraftSnapshot.UniqueId, out distance);
                }

                var aircraftJson = new AircraftJson()
                {
                    UniqueId     = aircraftSnapshot.UniqueId,
                    IsSatcomFeed = aircraftSnapshot.LastSatcomUpdate != DateTime.MinValue,
                };
                if (!args.OnlyIncludeMessageFields)
                {
                    aircraftJson.BearingFromHere  = GreatCircleMaths.Bearing(args.BrowserLatitude, args.BrowserLongitude, aircraftSnapshot.Latitude, aircraftSnapshot.Longitude, null, false, true);
                    aircraftJson.DistanceFromHere = distance == null ? (double?)null : Math.Round(distance.Value, 2);
                    if (aircraftJson.BearingFromHere != null)
                    {
                        aircraftJson.BearingFromHere = Math.Round(aircraftJson.BearingFromHere.Value, 1);
                    }
                }

                var firstTimeSeen = previousAircraft != null ? !previousAircraft.Contains(aircraftSnapshot.UniqueId)
                                                             : !previousAircraftSet.Contains(aircraftSnapshot.UniqueId);

                if (firstTimeSeen || aircraftSnapshot.AirPressureInHgChanged > args.PreviousDataVersion)
                {
                    aircraftJson.AirPressureInHg = aircraftSnapshot.AirPressureInHg;
                }
                if (firstTimeSeen || aircraftSnapshot.AltitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Altitude = aircraftSnapshot.Altitude;
                }
                if (firstTimeSeen || aircraftSnapshot.AltitudeTypeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.AltitudeType = (int)aircraftSnapshot.AltitudeType;
                }
                if (firstTimeSeen || aircraftSnapshot.CallsignChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Callsign = aircraftSnapshot.Callsign;
                }
                if (firstTimeSeen || aircraftSnapshot.CallsignIsSuspectChanged > args.PreviousDataVersion)
                {
                    aircraftJson.CallsignIsSuspect = aircraftSnapshot.CallsignIsSuspect;
                }
                if (firstTimeSeen || aircraftSnapshot.GroundSpeedChanged > args.PreviousDataVersion)
                {
                    aircraftJson.GroundSpeed = Round.GroundSpeed(aircraftSnapshot.GroundSpeed);
                }
                if (firstTimeSeen || aircraftSnapshot.EmergencyChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Emergency = aircraftSnapshot.Emergency;
                }
                if (firstTimeSeen || aircraftSnapshot.GeometricAltitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.GeometricAltitude = aircraftSnapshot.GeometricAltitude;
                }
                if (firstTimeSeen || args.AlwaysShowIcao || aircraftSnapshot.Icao24Changed > args.PreviousDataVersion)
                {
                    aircraftJson.Icao24 = aircraftSnapshot.Icao24;
                }
                if (firstTimeSeen || aircraftSnapshot.IsTisbChanged > args.PreviousDataVersion)
                {
                    aircraftJson.IsTisb = aircraftSnapshot.IsTisb;
                }
                if (firstTimeSeen || aircraftSnapshot.LatitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Latitude = Round.Coordinate(aircraftSnapshot.Latitude);
                }
                if (firstTimeSeen || aircraftSnapshot.LongitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Longitude = Round.Coordinate(aircraftSnapshot.Longitude);
                }
                if (firstTimeSeen || aircraftSnapshot.OnGroundChanged > args.PreviousDataVersion)
                {
                    aircraftJson.OnGround = aircraftSnapshot.OnGround;
                }
                if (firstTimeSeen || aircraftSnapshot.PositionIsMlatChanged > args.PreviousDataVersion)
                {
                    aircraftJson.PositionIsMlat = aircraftSnapshot.PositionIsMlat;
                }
                if (firstTimeSeen || aircraftSnapshot.SignalLevelChanged > args.PreviousDataVersion)
                {
                    aircraftJson.HasSignalLevel = aircraftSnapshot.SignalLevel != null; aircraftJson.SignalLevel = aircraftSnapshot.SignalLevel;
                }
                if (firstTimeSeen || aircraftSnapshot.SpeedTypeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.SpeedType = (int)aircraftSnapshot.SpeedType;
                }
                if (firstTimeSeen || aircraftSnapshot.SquawkChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Squawk = String.Format("{0:0000}", aircraftSnapshot.Squawk);
                }
                if (firstTimeSeen || aircraftSnapshot.TargetAltitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.TargetAltitude = aircraftSnapshot.TargetAltitude;
                }
                if (firstTimeSeen || aircraftSnapshot.TargetTrackChanged > args.PreviousDataVersion)
                {
                    aircraftJson.TargetTrack = aircraftSnapshot.TargetTrack;
                }
                if (firstTimeSeen || aircraftSnapshot.TrackChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Track = Round.Track(aircraftSnapshot.Track);
                }
                if (firstTimeSeen || aircraftSnapshot.TrackIsHeadingChanged > args.PreviousDataVersion)
                {
                    aircraftJson.TrackIsHeading = aircraftSnapshot.TrackIsHeading;
                }
                if (firstTimeSeen || aircraftSnapshot.TransponderTypeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.TransponderType = (int)aircraftSnapshot.TransponderType;
                }
                if (firstTimeSeen || aircraftSnapshot.VerticalRateChanged > args.PreviousDataVersion)
                {
                    aircraftJson.VerticalRate = aircraftSnapshot.VerticalRate;
                }
                if (firstTimeSeen || aircraftSnapshot.VerticalRateTypeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.VerticalRateType = (int)aircraftSnapshot.VerticalRateType;
                }

                if (args.OnlyIncludeMessageFields)
                {
                    if (aircraftJson.Latitude != null || aircraftJson.Longitude != null || aircraftJson.PositionIsMlat != null)
                    {
                        if (aircraftJson.Latitude == null)
                        {
                            aircraftJson.Latitude = Round.Coordinate(aircraftSnapshot.Latitude);
                        }
                        if (aircraftJson.Longitude == null)
                        {
                            aircraftJson.Longitude = Round.Coordinate(aircraftSnapshot.Longitude);
                        }
                        if (aircraftJson.PositionIsMlat == null)
                        {
                            aircraftJson.PositionIsMlat = aircraftSnapshot.PositionIsMlat;
                        }
                    }
                    if (aircraftJson.Altitude != null || aircraftJson.GeometricAltitude != null || aircraftJson.AltitudeType != null)
                    {
                        if (aircraftJson.Altitude == null)
                        {
                            aircraftJson.Altitude = aircraftSnapshot.Altitude;
                        }
                        if (aircraftJson.AltitudeType == null)
                        {
                            aircraftJson.AltitudeType = (int)aircraftSnapshot.AltitudeType;
                        }
                        if (aircraftJson.GeometricAltitude == null)
                        {
                            aircraftJson.GeometricAltitude = aircraftSnapshot.GeometricAltitude;
                        }
                    }
                }
                else if (!args.OnlyIncludeMessageFields)
                {
                    if (firstTimeSeen || aircraftSnapshot.ConstructionNumberChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.ConstructionNumber = aircraftSnapshot.ConstructionNumber;
                    }
                    if (firstTimeSeen || aircraftSnapshot.CountMessagesReceivedChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.CountMessagesReceived = aircraftSnapshot.CountMessagesReceived;
                    }
                    if (firstTimeSeen || aircraftSnapshot.DestinationChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Destination = aircraftSnapshot.Destination;
                    }
                    if (firstTimeSeen || aircraftSnapshot.EnginePlacementChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.EnginePlacement = (int)aircraftSnapshot.EnginePlacement;
                    }
                    if (firstTimeSeen || aircraftSnapshot.EngineTypeChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.EngineType = (int)aircraftSnapshot.EngineType;
                    }
                    if (firstTimeSeen || aircraftSnapshot.FirstSeenChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.FirstSeen = aircraftSnapshot.FirstSeen;
                    }
                    if (firstTimeSeen || aircraftSnapshot.FlightsCountChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.FlightsCount = aircraftSnapshot.FlightsCount;
                    }
                    if (firstTimeSeen || aircraftSnapshot.Icao24CountryChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Icao24Country = aircraftSnapshot.Icao24Country;
                    }
                    if (firstTimeSeen || aircraftSnapshot.Icao24InvalidChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Icao24Invalid = aircraftSnapshot.Icao24Invalid;
                    }
                    if (firstTimeSeen || aircraftSnapshot.IsInterestingChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.IsInteresting = aircraftSnapshot.IsInteresting;
                    }
                    if (firstTimeSeen || aircraftSnapshot.IsMilitaryChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.IsMilitary = aircraftSnapshot.IsMilitary;
                    }
                    if (firstTimeSeen || aircraftSnapshot.ManufacturerChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Manufacturer = aircraftSnapshot.Manufacturer;
                    }
                    if (firstTimeSeen || aircraftSnapshot.ModelChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Model = aircraftSnapshot.Model;
                    }
                    if (firstTimeSeen || aircraftSnapshot.NumberOfEnginesChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.NumberOfEngines = aircraftSnapshot.NumberOfEngines;
                    }
                    if (firstTimeSeen || aircraftSnapshot.OperatorChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Operator = aircraftSnapshot.Operator;
                    }
                    if (firstTimeSeen || aircraftSnapshot.OperatorIcaoChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.OperatorIcao = aircraftSnapshot.OperatorIcao;
                    }
                    if (firstTimeSeen || aircraftSnapshot.OriginChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Origin = aircraftSnapshot.Origin;
                    }
                    if (firstTimeSeen || aircraftSnapshot.PictureFileNameChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.HasPicture = !String.IsNullOrEmpty(aircraftSnapshot.PictureFileName);
                    }
                    if (firstTimeSeen || aircraftSnapshot.PictureHeightChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.PictureHeight = aircraftSnapshot.PictureHeight == 0 ? (int?)null : aircraftSnapshot.PictureHeight;
                    }
                    if (firstTimeSeen || aircraftSnapshot.PictureWidthChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.PictureWidth = aircraftSnapshot.PictureWidth == 0 ? (int?)null : aircraftSnapshot.PictureWidth;
                    }
                    if (firstTimeSeen || aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.PositionTime = aircraftSnapshot.PositionTime == null ? (long?)null : JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value);
                    }
                    if (firstTimeSeen || aircraftSnapshot.ReceiverIdChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.ReceiverId = aircraftSnapshot.ReceiverId;
                    }
                    if (firstTimeSeen || aircraftSnapshot.RegistrationChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Registration = aircraftSnapshot.Registration;
                    }
                    if (firstTimeSeen || aircraftSnapshot.SpeciesChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Species = (int)aircraftSnapshot.Species;
                    }
                    if (firstTimeSeen || aircraftSnapshot.TypeChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.Type = aircraftSnapshot.Type;
                    }
                    if (firstTimeSeen || aircraftSnapshot.UserTagChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.UserTag = aircraftSnapshot.UserTag;
                    }
                    if (firstTimeSeen || aircraftSnapshot.WakeTurbulenceCategoryChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.WakeTurbulenceCategory = (int)aircraftSnapshot.WakeTurbulenceCategory;
                    }
                    if (firstTimeSeen || aircraftSnapshot.YearBuiltChanged > args.PreviousDataVersion)
                    {
                        aircraftJson.YearBuilt = aircraftSnapshot.YearBuilt;
                    }

                    if (aircraftSnapshot.Stopovers.Count > 0 && (firstTimeSeen || aircraftSnapshot.StopoversChanged > args.PreviousDataVersion))
                    {
                        aircraftJson.Stopovers = new List <string>();
                        aircraftJson.Stopovers.AddRange(aircraftSnapshot.Stopovers);
                    }

                    aircraftJson.SecondsTracked  = (long)((now - aircraftSnapshot.FirstSeen).TotalSeconds);
                    aircraftJson.PositionIsStale = aircraftSnapshot.LastSatcomUpdate == DateTime.MinValue &&        // Never flag satcom aircraft as having a stale position
                                                   aircraftSnapshot.PositionTime != null &&
                                                   aircraftSnapshot.PositionTime < positionTimeoutThreshold ? true : (bool?)null;
                }

                if (args.TrailType != TrailType.None)
                {
                    var hasTrail     = false;
                    var isShort      = false;
                    var showAltitude = false;
                    var showSpeed    = false;
                    switch (args.TrailType)
                    {
                    case TrailType.Short:           isShort = true; hasTrail = aircraftSnapshot.ShortCoordinates.Count > 0; break;

                    case TrailType.ShortAltitude:   showAltitude = true; aircraftJson.TrailType = "a"; goto case TrailType.Short;

                    case TrailType.ShortSpeed:      showSpeed = true; aircraftJson.TrailType = "s"; goto case TrailType.Short;

                    case TrailType.Full:            hasTrail = aircraftSnapshot.FullCoordinates.Count > 0; break;

                    case TrailType.FullAltitude:    showAltitude = true; aircraftJson.TrailType = "a"; goto case TrailType.Full;

                    case TrailType.FullSpeed:       showSpeed = true; aircraftJson.TrailType = "s"; goto case TrailType.Full;
                    }
                    if (hasTrail)
                    {
                        BuildCoordinatesList(isShort, firstTimeSeen, aircraftJson, aircraftSnapshot, args, showAltitude, showSpeed);
                    }
                }

                aircraftListJson.Aircraft.Add(aircraftJson);
            }
        }
        /// <summary>
        /// Returns a filtered list of aircraft and at the same time calculates the distances from the browser location to each aircraft.
        /// </summary>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        /// <returns></returns>
        /// <remarks>Distance calculations can be expensive, hence the reason why we try to minimise the number of times that they are performed.</remarks>
        private List <IAircraft> FilterAircraft(List <IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, Dictionary <int, double?> distances)
        {
            List <IAircraft> result = new List <IAircraft>();

            foreach (var aircraft in aircraftListSnapshot)
            {
                if (PassesFilter(aircraft, args, distances))
                {
                    result.Add(aircraft);
                }
            }

            return(result);
        }
        /// <summary>
        /// Returns a fully-formed <see cref="AircraftListJson"/> from the aircraft list passed across.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public AircraftListJson Build(AircraftListJsonBuilderArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            RefreshConfigurationSettings();

            var feedId = args.SourceFeedId == -1 ? _DefaultAircraftListFeedId : args.SourceFeedId;

            IAircraftList aircraftList = null;

            if (args.IsFlightSimulatorList)
            {
                aircraftList = args.AircraftList;
            }
            else
            {
                var selectedFeed = _FeedManager.GetByUniqueId(feedId, ignoreInvisibleFeeds: true);
                if (selectedFeed == null)
                {
                    feedId       = _DefaultAircraftListFeedId;
                    selectedFeed = _FeedManager.GetByUniqueId(feedId, ignoreInvisibleFeeds: true);
                }
                aircraftList = selectedFeed == null ? null : selectedFeed.AircraftList;
            }
            if (aircraftList == null)
            {
                aircraftList = _EmptyAircraftList;
                feedId       = args.SourceFeedId;
            }

            var result = new AircraftListJson()
            {
                FlagHeight              = 20,
                FlagWidth               = 85,
                ShowFlags               = _ShowFlags && !args.IsFlightSimulatorList,
                ShowPictures            = _ShowPictures && (!args.IsInternetClient || _ShowPicturesToInternetClients) && !args.IsFlightSimulatorList,
                ShowSilhouettes         = _ShowSilhouettes && !args.IsFlightSimulatorList,
                ShortTrailLengthSeconds = _ShortTrailLength,
                Source       = (int)aircraftList.Source,
                SourceFeedId = feedId,
            };

            if (!args.FeedsNotRequired)
            {
                foreach (var feed in _FeedManager.VisibleFeeds)
                {
                    result.Feeds.Add(new FeedJson()
                    {
                        UniqueId     = feed.UniqueId,
                        Name         = feed.Name,
                        HasPolarPlot = feed.AircraftList != null && feed.AircraftList.PolarPlotter != null
                    });
                }
            }

            long timestamp, dataVersion;
            var  aircraft = aircraftList.TakeSnapshot(out timestamp, out dataVersion);

            result.AvailableAircraft = aircraft.Count;

            if (args.IgnoreUnchanged)
            {
                aircraft = aircraft.Where(r => r.DataVersion > args.PreviousDataVersion).ToList();
            }

            result.LastDataVersion = dataVersion.ToString();
            result.ServerTime      = JavascriptHelper.ToJavascriptTicks(timestamp);

            Dictionary <int, double?> distances = new Dictionary <int, double?>();

            aircraft = FilterAircraft(aircraft, args, distances);
            SortAircraft(aircraft, args, distances);
            CopyAircraft(result, aircraft, args, distances);

            return(result);
        }
Esempio n. 8
0
        /// <summary>
        /// Builds the full or short coordinates list and attaches it to the aircraft JSON object.
        /// </summary>
        /// <param name="shortCoordinates"></param>
        /// <param name="firstTimeSeen"></param>
        /// <param name="aircraftJson"></param>
        /// <param name="aircraftSnapshot"></param>
        /// <param name="args"></param>
        private void BuildCoordinatesList(bool shortCoordinates, bool firstTimeSeen, AircraftJson aircraftJson, IAircraft aircraftSnapshot, AircraftListJsonBuilderArgs args)
        {
            aircraftJson.ResetTrail = firstTimeSeen || args.ResendTrails || aircraftSnapshot.FirstCoordinateChanged > args.PreviousDataVersion;
            List <double?> list = new List <double?>();

            Coordinate lastCoordinate = null;

            foreach (var coordindate in shortCoordinates ? aircraftSnapshot.ShortCoordinates : aircraftSnapshot.FullCoordinates)
            {
                if (aircraftJson.ResetTrail || coordindate.DataVersion > args.PreviousDataVersion)
                {
                    list.Add(Round.Coordinate(coordindate.Latitude));
                    list.Add(Round.Coordinate(coordindate.Longitude));
                    if (shortCoordinates)
                    {
                        list.Add(JavascriptHelper.ToJavascriptTicks(coordindate.Tick));
                    }
                    else
                    {
                        list.Add(Round.Track(coordindate.Heading));
                    }
                }

                lastCoordinate = coordindate;
            }

            if (aircraftSnapshot.Latitude != null && aircraftSnapshot.Longitude != null &&
                (lastCoordinate.Latitude != aircraftSnapshot.Latitude || lastCoordinate.Longitude != aircraftSnapshot.Longitude) &&
                aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion)
            {
                list.Add(Round.Coordinate(aircraftSnapshot.Latitude));
                list.Add(Round.Coordinate(aircraftSnapshot.Longitude));
                if (shortCoordinates)
                {
                    list.Add(JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value));
                }
                else
                {
                    list.Add(Round.Track(aircraftSnapshot.Track));
                }
            }

            if (list.Count != 0)
            {
                if (shortCoordinates)
                {
                    aircraftJson.ShortCoordinates = list;
                }
                else
                {
                    aircraftJson.FullCoordinates = list;
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Copies the aircraft from the snapshot to the JSON object.
        /// </summary>
        /// <param name="aircraftListJson"></param>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        private void CopyAircraft(AircraftListJson aircraftListJson, List <IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, Dictionary <int, double?> distances)
        {
            var now = _Provider.UtcNow;

            foreach (var aircraftSnapshot in aircraftListSnapshot)
            {
                double?distance;
                if (!distances.TryGetValue(aircraftSnapshot.UniqueId, out distance))
                {
                    distance = null;
                }

                var aircraftJson = new AircraftJson()
                {
                    BearingFromHere  = GreatCircleMaths.Bearing(args.BrowserLatitude, args.BrowserLongitude, aircraftSnapshot.Latitude, aircraftSnapshot.Longitude, null, false, true),
                    DistanceFromHere = distance == null ? (double?)null : Math.Round(distance.Value, 2),
                    UniqueId         = aircraftSnapshot.UniqueId,
                };
                if (aircraftJson.BearingFromHere != null)
                {
                    aircraftJson.BearingFromHere = Math.Round(aircraftJson.BearingFromHere.Value, 1);
                }

                bool firstTimeSeen = !args.PreviousAircraft.Contains(aircraftSnapshot.UniqueId);

                if (firstTimeSeen || aircraftSnapshot.AltitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Altitude = aircraftSnapshot.Altitude;
                }
                if (firstTimeSeen || aircraftSnapshot.CallsignChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Callsign = aircraftSnapshot.Callsign;
                }
                if (firstTimeSeen || aircraftSnapshot.CallsignIsSuspectChanged > args.PreviousDataVersion)
                {
                    aircraftJson.CallsignIsSuspect = aircraftSnapshot.CallsignIsSuspect;
                }
                if (firstTimeSeen || aircraftSnapshot.ConstructionNumberChanged > args.PreviousDataVersion)
                {
                    aircraftJson.ConstructionNumber = aircraftSnapshot.ConstructionNumber;
                }
                if (firstTimeSeen || aircraftSnapshot.CountMessagesReceivedChanged > args.PreviousDataVersion)
                {
                    aircraftJson.CountMessagesReceived = aircraftSnapshot.CountMessagesReceived;
                }
                if (firstTimeSeen || aircraftSnapshot.DestinationChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Destination = aircraftSnapshot.Destination;
                }
                if (firstTimeSeen || aircraftSnapshot.GroundSpeedChanged > args.PreviousDataVersion)
                {
                    aircraftJson.GroundSpeed = Round.GroundSpeed(aircraftSnapshot.GroundSpeed);
                }
                if (firstTimeSeen || aircraftSnapshot.EmergencyChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Emergency = aircraftSnapshot.Emergency;
                }
                if (firstTimeSeen || aircraftSnapshot.EngineTypeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.EngineType = (int)aircraftSnapshot.EngineType;
                }
                if (firstTimeSeen || aircraftSnapshot.FirstSeenChanged > args.PreviousDataVersion)
                {
                    aircraftJson.FirstSeen = aircraftSnapshot.FirstSeen;
                }
                if (firstTimeSeen || aircraftSnapshot.FlightsCountChanged > args.PreviousDataVersion)
                {
                    aircraftJson.FlightsCount = aircraftSnapshot.FlightsCount;
                }
                if (firstTimeSeen || aircraftSnapshot.PictureFileNameChanged > args.PreviousDataVersion)
                {
                    aircraftJson.HasPicture = !String.IsNullOrEmpty(aircraftSnapshot.PictureFileName);
                }
                if (firstTimeSeen || aircraftSnapshot.Icao24Changed > args.PreviousDataVersion)
                {
                    aircraftJson.Icao24 = aircraftSnapshot.Icao24;
                }
                if (firstTimeSeen || aircraftSnapshot.Icao24CountryChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Icao24Country = aircraftSnapshot.Icao24Country;
                }
                if (firstTimeSeen || aircraftSnapshot.Icao24InvalidChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Icao24Invalid = aircraftSnapshot.Icao24Invalid;
                }
                if (firstTimeSeen || aircraftSnapshot.IsMilitaryChanged > args.PreviousDataVersion)
                {
                    aircraftJson.IsMilitary = aircraftSnapshot.IsMilitary;
                }
                if (firstTimeSeen || aircraftSnapshot.IsInterestingChanged > args.PreviousDataVersion)
                {
                    aircraftJson.IsInteresting = aircraftSnapshot.IsInteresting;
                }
                if (firstTimeSeen || aircraftSnapshot.LatitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Latitude = Round.Coordinate(aircraftSnapshot.Latitude);
                }
                if (firstTimeSeen || aircraftSnapshot.LongitudeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Longitude = Round.Coordinate(aircraftSnapshot.Longitude);
                }
                if (firstTimeSeen || aircraftSnapshot.ModelChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Model = aircraftSnapshot.Model;
                }
                if (firstTimeSeen || aircraftSnapshot.NumberOfEnginesChanged > args.PreviousDataVersion)
                {
                    aircraftJson.NumberOfEngines = aircraftSnapshot.NumberOfEngines;
                }
                if (firstTimeSeen || aircraftSnapshot.OnGroundChanged > args.PreviousDataVersion)
                {
                    aircraftJson.OnGround = aircraftSnapshot.OnGround;
                }
                if (firstTimeSeen || aircraftSnapshot.OperatorChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Operator = aircraftSnapshot.Operator;
                }
                if (firstTimeSeen || aircraftSnapshot.OperatorIcaoChanged > args.PreviousDataVersion)
                {
                    aircraftJson.OperatorIcao = aircraftSnapshot.OperatorIcao;
                }
                if (firstTimeSeen || aircraftSnapshot.OriginChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Origin = aircraftSnapshot.Origin;
                }
                if (firstTimeSeen || aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.PositionTime = aircraftSnapshot.PositionTime == null ? (long?)null : JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value);
                }
                if (firstTimeSeen || aircraftSnapshot.RegistrationChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Registration = aircraftSnapshot.Registration;
                }
                if (firstTimeSeen || aircraftSnapshot.SpeciesChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Species = (int)aircraftSnapshot.Species;
                }
                if (firstTimeSeen || aircraftSnapshot.SpeedTypeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.SpeedType = (int)aircraftSnapshot.SpeedType;
                }
                if (firstTimeSeen || aircraftSnapshot.SquawkChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Squawk = String.Format("{0:0000}", aircraftSnapshot.Squawk);
                }
                if (firstTimeSeen || aircraftSnapshot.TrackChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Track = Round.Track(aircraftSnapshot.Track);
                }
                if (firstTimeSeen || aircraftSnapshot.TypeChanged > args.PreviousDataVersion)
                {
                    aircraftJson.Type = aircraftSnapshot.Type;
                }
                if (firstTimeSeen || aircraftSnapshot.UserTagChanged > args.PreviousDataVersion)
                {
                    aircraftJson.UserTag = aircraftSnapshot.UserTag;
                }
                if (firstTimeSeen || aircraftSnapshot.VerticalRateChanged > args.PreviousDataVersion)
                {
                    aircraftJson.VerticalRate = aircraftSnapshot.VerticalRate;
                }
                if (firstTimeSeen || aircraftSnapshot.WakeTurbulenceCategoryChanged > args.PreviousDataVersion)
                {
                    aircraftJson.WakeTurbulenceCategory = (int)aircraftSnapshot.WakeTurbulenceCategory;
                }

                if (aircraftSnapshot.Stopovers.Count > 0 && (firstTimeSeen || aircraftSnapshot.StopoversChanged > args.PreviousDataVersion))
                {
                    aircraftJson.Stopovers = new List <string>();
                    aircraftJson.Stopovers.AddRange(aircraftSnapshot.Stopovers);
                }

                aircraftJson.SecondsTracked = (long)((now - aircraftSnapshot.FirstSeen).TotalSeconds);

                if (args.ShowShortTrail)
                {
                    if (aircraftSnapshot.ShortCoordinates.Count > 0)
                    {
                        BuildCoordinatesList(true, firstTimeSeen, aircraftJson, aircraftSnapshot, args);
                    }
                }
                else
                {
                    if (aircraftSnapshot.FullCoordinates.Count > 0)
                    {
                        BuildCoordinatesList(false, firstTimeSeen, aircraftJson, aircraftSnapshot, args);
                    }
                }

                aircraftListJson.Aircraft.Add(aircraftJson);
            }
        }
        /// <summary>
        /// Copies the aircraft from the snapshot to the JSON object.
        /// </summary>
        /// <param name="aircraftListJson"></param>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        private void CopyAircraft(AircraftListJson aircraftListJson, List<IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, Dictionary<int, double?> distances)
        {
            var now = _Provider.UtcNow;

            foreach(var aircraftSnapshot in aircraftListSnapshot) {
                double? distance;
                if(!distances.TryGetValue(aircraftSnapshot.UniqueId, out distance)) distance = null;

                var aircraftJson = new AircraftJson() {
                    BearingFromHere = GreatCircleMaths.Bearing(args.BrowserLatitude, args.BrowserLongitude, aircraftSnapshot.Latitude, aircraftSnapshot.Longitude, null, false, true),
                    DistanceFromHere = distance == null ? (double?)null : Math.Round(distance.Value, 2),
                    UniqueId = aircraftSnapshot.UniqueId,
                };
                if(aircraftJson.BearingFromHere != null) aircraftJson.BearingFromHere = Math.Round(aircraftJson.BearingFromHere.Value, 1);

                bool firstTimeSeen = !args.PreviousAircraft.Contains(aircraftSnapshot.UniqueId);

                if(firstTimeSeen || aircraftSnapshot.AltitudeChanged > args.PreviousDataVersion)                aircraftJson.Altitude = aircraftSnapshot.Altitude;
                if(firstTimeSeen || aircraftSnapshot.CallsignChanged > args.PreviousDataVersion)                aircraftJson.Callsign = aircraftSnapshot.Callsign;
                if(firstTimeSeen || aircraftSnapshot.CallsignIsSuspectChanged > args.PreviousDataVersion)       aircraftJson.CallsignIsSuspect = aircraftSnapshot.CallsignIsSuspect;
                if(firstTimeSeen || aircraftSnapshot.ConstructionNumberChanged > args.PreviousDataVersion)      aircraftJson.ConstructionNumber = aircraftSnapshot.ConstructionNumber;
                if(firstTimeSeen || aircraftSnapshot.CountMessagesReceivedChanged > args.PreviousDataVersion)   aircraftJson.CountMessagesReceived = aircraftSnapshot.CountMessagesReceived;
                if(firstTimeSeen || aircraftSnapshot.DestinationChanged > args.PreviousDataVersion)             aircraftJson.Destination = aircraftSnapshot.Destination;
                if(firstTimeSeen || aircraftSnapshot.GroundSpeedChanged > args.PreviousDataVersion)             aircraftJson.GroundSpeed = Round.GroundSpeed(aircraftSnapshot.GroundSpeed);
                if(firstTimeSeen || aircraftSnapshot.EmergencyChanged > args.PreviousDataVersion)               aircraftJson.Emergency = aircraftSnapshot.Emergency;
                if(firstTimeSeen || aircraftSnapshot.EngineTypeChanged > args.PreviousDataVersion)              aircraftJson.EngineType = (int)aircraftSnapshot.EngineType;
                if(firstTimeSeen || aircraftSnapshot.FirstSeenChanged > args.PreviousDataVersion)               aircraftJson.FirstSeen = aircraftSnapshot.FirstSeen;
                if(firstTimeSeen || aircraftSnapshot.FlightsCountChanged > args.PreviousDataVersion)            aircraftJson.FlightsCount = aircraftSnapshot.FlightsCount;
                if(firstTimeSeen || aircraftSnapshot.PictureFileNameChanged > args.PreviousDataVersion)         aircraftJson.HasPicture = !String.IsNullOrEmpty(aircraftSnapshot.PictureFileName);
                if(firstTimeSeen || aircraftSnapshot.Icao24Changed > args.PreviousDataVersion)                  aircraftJson.Icao24 = aircraftSnapshot.Icao24;
                if(firstTimeSeen || aircraftSnapshot.Icao24CountryChanged > args.PreviousDataVersion)           aircraftJson.Icao24Country = aircraftSnapshot.Icao24Country;
                if(firstTimeSeen || aircraftSnapshot.Icao24InvalidChanged > args.PreviousDataVersion)           aircraftJson.Icao24Invalid = aircraftSnapshot.Icao24Invalid;
                if(firstTimeSeen || aircraftSnapshot.IsMilitaryChanged > args.PreviousDataVersion)              aircraftJson.IsMilitary = aircraftSnapshot.IsMilitary;
                if(firstTimeSeen || aircraftSnapshot.IsInterestingChanged > args.PreviousDataVersion)           aircraftJson.IsInteresting = aircraftSnapshot.IsInteresting;
                if(firstTimeSeen || aircraftSnapshot.LatitudeChanged > args.PreviousDataVersion)                aircraftJson.Latitude = Round.Coordinate(aircraftSnapshot.Latitude);
                if(firstTimeSeen || aircraftSnapshot.LongitudeChanged > args.PreviousDataVersion)               aircraftJson.Longitude = Round.Coordinate(aircraftSnapshot.Longitude);
                if(firstTimeSeen || aircraftSnapshot.ModelChanged > args.PreviousDataVersion)                   aircraftJson.Model = aircraftSnapshot.Model;
                if(firstTimeSeen || aircraftSnapshot.NumberOfEnginesChanged > args.PreviousDataVersion)         aircraftJson.NumberOfEngines = aircraftSnapshot.NumberOfEngines;
                if(firstTimeSeen || aircraftSnapshot.OnGroundChanged > args.PreviousDataVersion)                aircraftJson.OnGround = aircraftSnapshot.OnGround;
                if(firstTimeSeen || aircraftSnapshot.OperatorChanged > args.PreviousDataVersion)                aircraftJson.Operator = aircraftSnapshot.Operator;
                if(firstTimeSeen || aircraftSnapshot.OperatorIcaoChanged > args.PreviousDataVersion)            aircraftJson.OperatorIcao = aircraftSnapshot.OperatorIcao;
                if(firstTimeSeen || aircraftSnapshot.OriginChanged > args.PreviousDataVersion)                  aircraftJson.Origin = aircraftSnapshot.Origin;
                if(firstTimeSeen || aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion)            aircraftJson.PositionTime = aircraftSnapshot.PositionTime == null ? (long?)null : JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value);
                if(firstTimeSeen || aircraftSnapshot.RegistrationChanged > args.PreviousDataVersion)            aircraftJson.Registration = aircraftSnapshot.Registration;
                if(firstTimeSeen || aircraftSnapshot.SpeciesChanged > args.PreviousDataVersion)                 aircraftJson.Species = (int)aircraftSnapshot.Species;
                if(firstTimeSeen || aircraftSnapshot.SpeedTypeChanged > args.PreviousDataVersion)               aircraftJson.SpeedType = (int)aircraftSnapshot.SpeedType;
                if(firstTimeSeen || aircraftSnapshot.SquawkChanged > args.PreviousDataVersion)                  aircraftJson.Squawk = String.Format("{0:0000}", aircraftSnapshot.Squawk);
                if(firstTimeSeen || aircraftSnapshot.TrackChanged > args.PreviousDataVersion)                   aircraftJson.Track = Round.Track(aircraftSnapshot.Track);
                if(firstTimeSeen || aircraftSnapshot.TypeChanged > args.PreviousDataVersion)                    aircraftJson.Type = aircraftSnapshot.Type;
                if(firstTimeSeen || aircraftSnapshot.UserTagChanged > args.PreviousDataVersion)                 aircraftJson.UserTag = aircraftSnapshot.UserTag;
                if(firstTimeSeen || aircraftSnapshot.VerticalRateChanged > args.PreviousDataVersion)            aircraftJson.VerticalRate = aircraftSnapshot.VerticalRate;
                if(firstTimeSeen || aircraftSnapshot.WakeTurbulenceCategoryChanged > args.PreviousDataVersion)  aircraftJson.WakeTurbulenceCategory = (int)aircraftSnapshot.WakeTurbulenceCategory;

                if(aircraftSnapshot.Stopovers.Count > 0 && (firstTimeSeen || aircraftSnapshot.StopoversChanged > args.PreviousDataVersion)) {
                    aircraftJson.Stopovers = new List<string>();
                    aircraftJson.Stopovers.AddRange(aircraftSnapshot.Stopovers);
                }

                aircraftJson.SecondsTracked = (long)((now - aircraftSnapshot.FirstSeen).TotalSeconds);

                if(args.ShowShortTrail) {
                    if(aircraftSnapshot.ShortCoordinates.Count > 0) {
                        BuildCoordinatesList(true, firstTimeSeen, aircraftJson, aircraftSnapshot, args);
                    }
                } else {
                    if(aircraftSnapshot.FullCoordinates.Count > 0) {
                        BuildCoordinatesList(false, firstTimeSeen, aircraftJson, aircraftSnapshot, args);
                    }
                }

                aircraftListJson.Aircraft.Add(aircraftJson);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Returns a filtered list of aircraft and at the same time calculates the distances from the browser location to each aircraft.
        /// </summary>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        /// <returns></returns>
        /// <remarks>Distance calculations can be expensive, hence the reason why we try to minimise the number of times that they are performed.</remarks>
        private List <IAircraft> FilterAircraft(List <IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, ref Dictionary <int, double?> distances)
        {
            List <IAircraft> result = new List <IAircraft>();

            foreach (var aircraft in aircraftListSnapshot)
            {
                if (!PassesFilter(aircraft, args.Filter))
                {
                    continue;
                }

                var distance = args.IsFlightSimulatorList ? null : GreatCircleMaths.Distance(args.BrowserLatitude, args.BrowserLongitude, aircraft.Latitude, aircraft.Longitude);
                if (args.Filter != null)
                {
                    if (args.Filter.DistanceLower != null && (distance == null || distance < args.Filter.DistanceLower))
                    {
                        continue;
                    }
                    if (args.Filter.DistanceUpper != null && (distance == null || distance > args.Filter.DistanceUpper))
                    {
                        continue;
                    }
                }

                result.Add(aircraft);
                distances.Add(aircraft.UniqueId, distance);
            }

            return(result);
        }
        /// <summary>
        /// Creates an object that holds all of the aircraft list arguments that were extracted from the request.
        /// </summary>
        /// <param name="args"></param>
        /// <param name="aircraftList"></param>
        /// <param name="isFlightSimulator"></param>
        /// <returns></returns>
        private AircraftListJsonBuilderArgs ConstructBuildArgs(RequestReceivedEventArgs args, IAircraftList aircraftList, bool isFlightSimulator)
        {
            var result = new AircraftListJsonBuilderArgs() {
                AircraftList =          aircraftList,
                BrowserLatitude =       QueryNDouble(args, "lat"),
                BrowserLongitude =      QueryNDouble(args, "lng"),
                Filter =                isFlightSimulator ? null : ConstructFilter(args),
                IsFlightSimulatorList = isFlightSimulator,
                IsInternetClient =      args.IsInternetRequest,
                PreviousDataVersion =   QueryLong(args, "ldv", -1),
                ResendTrails =          QueryString(args, "refreshTrails", false) == "1",
                ShowShortTrail =        QueryString(args, "trFmt", true) == "S",
            };

            for(int sortColumnCount = 0;sortColumnCount < 2;++sortColumnCount) {
                var sortColumn = QueryString(args, String.Format("sortBy{0}", sortColumnCount + 1), true);
                var sortOrder = QueryString(args, String.Format("sortOrder{0}", sortColumnCount + 1), true);
                if(String.IsNullOrEmpty(sortColumn) || String.IsNullOrEmpty(sortOrder)) break;
                result.SortBy.Add(new KeyValuePair<string,bool>(sortColumn, sortOrder == "ASC"));
            }
            if(result.SortBy.Count == 0) result.SortBy.Add(new KeyValuePair<string,bool>(AircraftComparerColumn.FirstSeen, false));

            var previousAircraftIds = args.Request.Headers["X-VirtualRadarServer-AircraftIds"];
            if(!String.IsNullOrEmpty(previousAircraftIds)) {
                var decodedPreviousAircraftIds = HttpUtility.UrlDecode(previousAircraftIds);
                foreach(var chunk in decodedPreviousAircraftIds.Split(',')) {
                    int id;
                    if(int.TryParse(chunk, out id)) result.PreviousAircraft.Add(id);
                }
            }

            return result;
        }
        /// <summary>
        /// Returns a fully-formed <see cref="AircraftListJson"/> from the aircraft list passed across.
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public AircraftListJson Build(AircraftListJsonBuilderArgs args)
        {
            if(args == null) throw new ArgumentNullException("aircraftList");
            if(args.AircraftList == null) throw new InvalidOperationException("The AircraftList must be supplied");

            var result = new AircraftListJson() {
                FlagHeight = 20,
                FlagWidth = 85,
                ShowFlags = _ShowFlags && !args.IsFlightSimulatorList,
                ShowPictures = _ShowPictures && (!args.IsInternetClient || _ShowPicturesToInternetClients) && !args.IsFlightSimulatorList,
                ShowSilhouettes = _ShowSilhouettes && !args.IsFlightSimulatorList,
                ShortTrailLengthSeconds = _ShortTrailLength,
                Source = (int)args.AircraftList.Source,
            };

            long timestamp, dataVersion;
            var aircraft = args.AircraftList.TakeSnapshot(out timestamp, out dataVersion);
            result.AvailableAircraft = aircraft.Count;
            result.LastDataVersion = dataVersion.ToString();
            result.ServerTime = JavascriptHelper.ToJavascriptTicks(timestamp);

            Dictionary<int, double?> distances = new Dictionary<int,double?>();
            aircraft = FilterAircraft(aircraft, args, ref distances);
            SortAircraft(aircraft, args, distances);
            CopyAircraft(result, aircraft, args, distances);

            return result;
        }
        /// <summary>
        /// Sorts the aircraft list using the parameters in the args object.
        /// </summary>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>]
        /// <param name="distances"></param>
        private void SortAircraft(List<IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, Dictionary<int, double?> distances)
        {
            IAircraftComparer comparer = Factory.Singleton.Resolve<IAircraftComparer>();
            comparer.BrowserLocation = args.BrowserLatitude == null || args.BrowserLongitude == null ? null : new Coordinate((float)args.BrowserLatitude, (float)args.BrowserLongitude);
            foreach(var sortBy in args.SortBy) {
                comparer.SortBy.Add(sortBy);
            }
            foreach(var distance in distances) {
                comparer.PrecalculatedDistances.Add(distance.Key, distance.Value);
            }

            aircraftListSnapshot.Sort(comparer);
        }
        /// <summary>
        /// Returns a filtered list of aircraft and at the same time calculates the distances from the browser location to each aircraft.
        /// </summary>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        /// <returns></returns>
        /// <remarks>Distance calculations can be expensive, hence the reason why we try to minimise the number of times that they are performed.</remarks>
        private List<IAircraft> FilterAircraft(List<IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, ref Dictionary<int, double?> distances)
        {
            List<IAircraft> result = new List<IAircraft>();

            foreach(var aircraft in aircraftListSnapshot) {
                if(!PassesFilter(aircraft, args.Filter)) continue;

                var distance = args.IsFlightSimulatorList ? null : GreatCircleMaths.Distance(args.BrowserLatitude, args.BrowserLongitude, aircraft.Latitude, aircraft.Longitude);
                if(args.Filter != null) {
                    if(args.Filter.DistanceLower != null && (distance == null || distance < args.Filter.DistanceLower)) continue;
                    if(args.Filter.DistanceUpper != null && (distance == null || distance > args.Filter.DistanceUpper)) continue;
                }

                result.Add(aircraft);
                distances.Add(aircraft.UniqueId, distance);
            }

            return result;
        }
Esempio n. 16
0
        /// <summary>
        /// Returns true if the aircraft passes the filter criteria passed across.
        /// </summary>
        /// <param name="aircraft"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        /// <returns></returns>
        private bool PassesFilter(IAircraft aircraft, AircraftListJsonBuilderArgs args, Dictionary <int, double?> distances)
        {
            var  filter = args.Filter;
            bool result = filter == null;

            var distance = args.IsFlightSimulatorList ? null : GreatCircleMaths.Distance(args.BrowserLatitude, args.BrowserLongitude, aircraft.Latitude, aircraft.Longitude);

            if (!result)
            {
                result = true;
                if (result && filter.Altitude != null)
                {
                    result = filter.Altitude.Passes(aircraft.Altitude);
                }
                if (result && filter.Callsign != null)
                {
                    result = filter.Callsign.Passes(aircraft.Callsign);
                }
                if (result && filter.EngineType != null)
                {
                    result = filter.EngineType.Passes(aircraft.EngineType);
                }
                if (result && filter.Icao24 != null)
                {
                    result = filter.Icao24.Passes(aircraft.Icao24);
                }
                if (result && filter.Icao24Country != null)
                {
                    result = filter.Icao24Country.Passes(aircraft.Icao24Country);
                }
                if (result && filter.IsInteresting != null)
                {
                    result = filter.IsInteresting.Passes(aircraft.IsInteresting);
                }
                if (result && filter.IsMilitary != null)
                {
                    result = filter.IsMilitary.Passes(aircraft.IsMilitary);
                }
                if (result && filter.MustTransmitPosition != null)
                {
                    result = filter.MustTransmitPosition.Passes(aircraft.Latitude != null && aircraft.Longitude != null);
                }
                if (result && filter.Operator != null)
                {
                    result = filter.Operator.Passes(aircraft.Operator);
                }
                if (result && filter.OperatorIcao != null)
                {
                    result = filter.OperatorIcao.Passes(aircraft.OperatorIcao);
                }
                if (result && filter.PositionWithin != null)
                {
                    result = args.SelectedAircraftId == aircraft.UniqueId || IsWithinBounds(aircraft.Latitude, aircraft.Longitude, filter.PositionWithin);
                }
                if (result && filter.Registration != null)
                {
                    result = filter.Registration.Passes(aircraft.Registration);
                }
                if (result && filter.Species != null)
                {
                    result = filter.Species.Passes(aircraft.Species);
                }
                if (result && filter.Squawk != null)
                {
                    result = filter.Squawk.Passes(aircraft.Squawk);
                }
                if (result && filter.Type != null)
                {
                    result = filter.Type.Passes(aircraft.Type);
                }
                if (result && filter.UserTag != null)
                {
                    result = filter.UserTag.Passes(aircraft.UserTag);
                }
                if (result && filter.WakeTurbulenceCategory != null)
                {
                    result = filter.WakeTurbulenceCategory.Passes(aircraft.WakeTurbulenceCategory);
                }

                if (result && filter.Airport != null)
                {
                    result = PassesAirportFilter(filter.Airport, aircraft);
                }

                if (result && filter.Distance != null)
                {
                    if (distance == null && filter.Distance.IsValid)
                    {
                        result = false;
                    }
                    else
                    {
                        result = filter.Distance.Passes(distance);
                    }
                }
            }

            if (result)
            {
                distances.Add(aircraft.UniqueId, distance);
            }

            return(result);
        }
Esempio n. 17
0
        /// <summary>
        /// Creates an object that holds all of the aircraft list arguments that were extracted from the request.
        /// </summary>
        /// <param name="args"></param>
        /// <param name="feedId"></param>
        /// <param name="aircraftList"></param>
        /// <param name="isFlightSimulator"></param>
        /// <returns></returns>
        private AircraftListJsonBuilderArgs ConstructBuildArgs(RequestReceivedEventArgs args, int feedId, IAircraftList aircraftList, bool isFlightSimulator)
        {
            var result = new AircraftListJsonBuilderArgs()
            {
                AircraftList          = aircraftList,
                BrowserLatitude       = QueryNDouble(args, "lat"),
                BrowserLongitude      = QueryNDouble(args, "lng"),
                Filter                = isFlightSimulator ? null : ConstructFilter(args),
                IsFlightSimulatorList = isFlightSimulator,
                IsInternetClient      = args.IsInternetRequest,
                PreviousDataVersion   = QueryLong(args, "ldv", -1),
                ServerTimeTicks       = QueryLong(args, "stm", -1),
                ResendTrails          = QueryString(args, "refreshTrails", false) == "1",
                SelectedAircraftId    = QueryInt(args, "selAc", -1),
                SourceFeedId          = feedId,
            };

            var trFmt = QueryString(args, "trFmt", true);

            if (!String.IsNullOrEmpty(trFmt))
            {
                switch (trFmt)
                {
                case "F":       result.TrailType = TrailType.Full; break;

                case "FA":      result.TrailType = TrailType.FullAltitude; break;

                case "FS":      result.TrailType = TrailType.FullSpeed; break;

                case "S":       result.TrailType = TrailType.Short; break;

                case "SA":      result.TrailType = TrailType.ShortAltitude; break;

                case "SS":      result.TrailType = TrailType.ShortSpeed; break;
                }
            }

            for (int sortColumnCount = 0; sortColumnCount < 2; ++sortColumnCount)
            {
                var sortColumn = QueryString(args, String.Format("sortBy{0}", sortColumnCount + 1), true);
                var sortOrder  = QueryString(args, String.Format("sortOrder{0}", sortColumnCount + 1), true);
                if (String.IsNullOrEmpty(sortColumn) || String.IsNullOrEmpty(sortOrder))
                {
                    break;
                }
                result.SortBy.Add(new KeyValuePair <string, bool>(sortColumn, sortOrder == "ASC"));
            }
            if (result.SortBy.Count == 0)
            {
                result.SortBy.Add(new KeyValuePair <string, bool>(AircraftComparerColumn.FirstSeen, false));
            }

            if ((args.Request.HttpMethod ?? "").ToUpper() == "POST")
            {
                ExtractPreviousAircraftIdsFromPostBody(args.Request, result.PreviousAircraft);
            }
            else
            {
                ExtractPreviousAircraftIdsFromHeader(args.Request, result.PreviousAircraft);
            }

            return(result);
        }
        /// <summary>
        /// Builds the full or short coordinates list and attaches it to the aircraft JSON object.
        /// </summary>
        /// <param name="shortCoordinates"></param>
        /// <param name="firstTimeSeen"></param>
        /// <param name="aircraftJson"></param>
        /// <param name="aircraftSnapshot"></param>
        /// <param name="args"></param>
        private void BuildCoordinatesList(bool shortCoordinates, bool firstTimeSeen, AircraftJson aircraftJson, IAircraft aircraftSnapshot, AircraftListJsonBuilderArgs args)
        {
            aircraftJson.ResetTrail = firstTimeSeen || args.ResendTrails || aircraftSnapshot.FirstCoordinateChanged > args.PreviousDataVersion;
            List<double?> list = new List<double?>();

            Coordinate lastCoordinate = null;
            foreach(var coordindate in shortCoordinates ? aircraftSnapshot.ShortCoordinates : aircraftSnapshot.FullCoordinates) {
                if(aircraftJson.ResetTrail || coordindate.DataVersion > args.PreviousDataVersion) {
                    list.Add(Round.Coordinate(coordindate.Latitude));
                    list.Add(Round.Coordinate(coordindate.Longitude));
                    if(shortCoordinates) list.Add(JavascriptHelper.ToJavascriptTicks(coordindate.Tick));
                    else                 list.Add(Round.Track(coordindate.Heading));
                }

                lastCoordinate = coordindate;
            }

            if(aircraftSnapshot.Latitude != null && aircraftSnapshot.Longitude != null &&
               (lastCoordinate.Latitude != aircraftSnapshot.Latitude || lastCoordinate.Longitude != aircraftSnapshot.Longitude) &&
               aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion) {
                list.Add(Round.Coordinate(aircraftSnapshot.Latitude));
                list.Add(Round.Coordinate(aircraftSnapshot.Longitude));
                if(shortCoordinates) list.Add(JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value));
                else                 list.Add(Round.Track(aircraftSnapshot.Track));
            }

            if(list.Count != 0) {
                if(shortCoordinates) aircraftJson.ShortCoordinates = list;
                else                 aircraftJson.FullCoordinates = list;
            }
        }