예제 #1
0
        public static void UpdateAirfields()
        {
            Logger.Debug("Updateing Airfields based on Game State");
            var airfields = Constants.Airfields; // These are airfields that have already had their navigation graphs setup

            var gameAirfields = GameQuerier.GetAirfields().Result;

            foreach (var gameAirfield in gameAirfields)
            {
                Logger.Debug($"Processing {gameAirfield.Name}");
                var airfield = airfields.FirstOrDefault(a => a.Name.Equals(gameAirfield.Name));

                if (airfield != null)
                {
                    // The following three fields are the ones that are dynamic and can change during a game session.
                    // Although wind is very unlikely to change enough to influence active runway settings.
                    airfield.Coalition   = gameAirfield.Coalition;
                    airfield.WindHeading = airfield.WindHeading == -1 ? Properties.Settings.Default.WindHeading : gameAirfield.WindHeading;
                    airfield.WindSpeed   = airfield.WindSpeed;
                    Logger.Trace($"Updated {gameAirfield.Name}");
                }
                else
                {
                    airfields.Add(gameAirfield);
                    Logger.Trace($"Added {gameAirfield.Name}");
                }
            }
        }
예제 #2
0
        public static async Task <string> Process(IRadioCall radioCall)
        {
            var sender = radioCall.Sender;

            var contact = await GameQuerier.GetBogeyDope(sender.Coalition, sender.Group, sender.Flight, sender.Plane);

            return(contact != null?BuildResponse(sender, contact) : "Picture is clean.");
        }
        private async Task <bool> IsPlayerDeleted()
        {
            _previousId = _sender.Id;
            await GameQuerier.PopulatePilotData(_sender);

            // If the caller does not exist any more or the ID has been reused for a different object then cancel the check.
            if (_sender.Id != null && _sender.Id == _previousId)
            {
                return(false);
            }
            _sender.Id = "DELETED";
            Logger.Debug(
                $"{_previousId} - {_sender.Callsign}: Stopping Approach Progress Check. CallerId changed, New: {_sender.Id} , Old: {_previousId}.");
            Stop();
            return(true);
        }
예제 #4
0
        private static async Task <string> NamedAirbase(IRadioCall radioCall)
        {
            string response;
            var    braData = await GameQuerier.GetBearingToNamedAirbase(radioCall.Sender.Position,
                                                                        radioCall.Sender.Group, radioCall.Sender.Flight, radioCall.Sender.Plane, radioCall.AirbaseName);

            if (braData != null)
            {
                var bearing =
                    Regex.Replace(Geospatial.TrueToMagnetic(radioCall.Sender.Position, braData["bearing"]).ToString("000"),
                                  "\\d{1}", " $0");
                var range = braData["range"];
                response = $"{AirbasePronouncer.PronounceAirbase(radioCall.AirbaseName)} bearing {bearing}, {range} miles";
            }
            else
            {
                response = $"I Could not find {AirbasePronouncer.PronounceAirbase(radioCall.AirbaseName)}.";
            }

            return(response);
        }
예제 #5
0
        private static async Task <string> NearestAirbase(IRadioCall radioCall)
        {
            string response;
            var    braData = await GameQuerier.GetBearingToNearestFriendlyAirbase(radioCall.Sender.Position,
                                                                                  radioCall.Sender.Group, radioCall.Sender.Flight, radioCall.Sender.Plane, (int)radioCall.Sender.Coalition);

            if (braData != null)
            {
                var bearing =
                    Regex.Replace(Geospatial.TrueToMagnetic(radioCall.Sender.Position, (int)braData["bearing"]).ToString("000"),
                                  "\\d{1}", " $0");
                var range = braData["range"];
                response = $"{AirbasePronouncer.PronounceAirbase((string) braData["name"])} bearing {bearing}, {(int) range} miles";
            }
            else
            {
                response = "I Could not find any friendly airbases.";
            }

            return(response);
        }
예제 #6
0
        public static async Task <string> Process(BearingToFriendlyPlayerRadioCall radioCall)
        {
            string response;

            if (radioCall.FriendlyPlayer == null)
            {
                return("I could not understand the friendly's callsign");
            }

            var contact = await GameQuerier.GetFriendlyPlayer(radioCall.Sender.Group, radioCall.Sender.Flight, radioCall.Sender.Plane,
                                                              radioCall.FriendlyPlayer.Group, radioCall.FriendlyPlayer.Flight, radioCall.FriendlyPlayer.Plane);

            if (contact != null)
            {
                var bearing  = Regex.Replace(Geospatial.TrueToMagnetic(radioCall.Sender.Position, contact.Bearing).ToString("000"), "\\d{1}", " $0");
                var range    = contact.Range.ToString();
                var altitude = (int)contact.Altitude;
                int angels;
                if (altitude < 1000)
                {
                    angels = 1;
                }
                else
                {
                    angels = (altitude % 1000 >= 500 ? altitude + 1000 - altitude % 1000 : altitude - altitude % 1000) / 1000;
                }

                response = $"Bra, {bearing}, {range}, angels {angels}.";
            }
            else
            {
                response = $"I cannot find {radioCall.Sender.Group} {radioCall.Sender.Flight} {radioCall.Sender.Plane}.";
            }

            return(response);
        }
        private async Task CheckAsync()
        {
            try
            {
                Logger.Debug($"Peforming Taxi Progress check for {_sender.Id}");
                var previousId = _sender.Id;
                await GameQuerier.PopulatePilotData(_sender);

                // If the caller does not exist any more or the ID has been reused for a different object then cancel the check.
                if (_sender.Id == null || _sender.Id != previousId)
                {
                    _sender.Id = "DELETED";
                    Logger.Debug(
                        $"Stopping Taxi Progress Check. CallerId changed, New: {_sender.Id} , Old: {previousId}.");
                    Stop();
                    return;
                }

                var closestPoint = _taxiPoints.OrderBy(taxiPoint => taxiPoint.DistanceTo(_sender.Position.Coordinate))
                                   .First();

                // If the player is more than 5 miles from the closest TaxiPoint they they are long gone and should not longer
                // be monitored
                if (closestPoint.DistanceTo(_sender.Position.Coordinate) > 5)
                {
                    Stop();
                    return;
                }

                // If this is true then we don't need to say the same commands again etc.
                if (_currentTaxiPoint == closestPoint)
                {
                    return;
                }

                // We want to get rid of all the previous TaxiPoints in the list. We do this instead of just getting rid of the first in case
                // somehow the pilot manage to skip a TaxiPoint by going fast enough that they passed it before the check.
                var index = _taxiPoints.IndexOf(_currentTaxiPoint);

                if (index > 1)
                {
                    Logger.Trace($" {_sender.Id} skipped at least one taxi point");
                }

                for (var i = _taxiPoints.Count - 1; i >= 0; i--)
                {
                    if (i > index)
                    {
                        continue;
                    }
                    Logger.Trace($"Removing {_taxiPoints[i].Name} from route of {_sender.Id}");
                    _taxiPoints.RemoveAt(i);
                }

                _currentTaxiPoint = closestPoint;
                Logger.Debug($"New closest TaxiPoint to {_sender.Id} is {_currentTaxiPoint.Name}");

                if (_currentTaxiPoint is Runway)
                {
                    using (var activity = Constants.ActivitySource.StartActivity("TaxiProgressChecker.SendTaxiInstruction", ActivityKind.Consumer))
                    {
                        if (_taxiPoints.Count == 1)
                        {
                            Logger.Debug(
                                $"Stopping Taxi Progress Check. {_sender.Id} has reached the end of the taxi route at {_currentTaxiPoint.Name}");
                            activity?.AddTag("Response", "RunwayTakeOff");
                            await SendMessage($"Take-off {_currentTaxiPoint.Name} at your discretion");
                        }
                        else
                        {
                            activity?.AddTag("Response", "RunwayCrossing");
                            // If we have reached this bit in the code then the current taxi point is a runway that is not the terminus of the route
                            // so tell the player they are good to cross.
                            await SendMessage($"cross {_currentTaxiPoint.Name} at your discretion");
                        }
                    }
                }
                else if (_taxiPoints.Count == 1)
                {
                    Logger.Error(
                        $"{_currentTaxiPoint.Name} is the last point in the taxi path but is not a runway");
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error checking taxi progress");
            }
        }
예제 #8
0
 private async Task UpdatePlayerData()
 {
     _previousId = _sender.Id;
     await GameQuerier.PopulatePilotData(_sender);
 }
        private async Task CheckAsync()
        {
            try
            {
                Logger.Debug($"{_sender.Id} - {_sender.Callsign}: Peforming Warning Radius check");

                if (WarningStates.ContainsKey(_sender.Id) == false)
                {
                    WarningStates.TryAdd(_sender.Id, new List <string>());
                }

                _previousId = _sender.Id;
                await GameQuerier.PopulatePilotData(_sender);

                // If the caller does not exist any more or the ID has been reused for a different object
                // then cancel the check.
                if (_sender.Id == null || _sender.Id != _previousId)
                {
                    _sender.Id = "DELETED";
                    Logger.Debug(
                        $"{_sender.Id} - {_sender.Callsign}: Stopping Warning Radius Check. CallerId changed, New: {_sender.Id} , Old: {_previousId}.");
                    Stop();
                    return;
                }

                var contact =
                    await GameQuerier.GetBogeyDope(_sender.Coalition, _sender.Group, _sender.Flight, _sender.Plane);

                if (contact == null)
                {
                    Logger.Debug($"{_sender.Id} - {_sender.Callsign}: No contacts found");
                    return;
                }

                if (contact.Range > _distance)
                {
                    Logger.Debug($"{_sender.Id} - {_sender.Callsign}: Contact {contact.Id} is more than {_distance} miles ({contact.Range})");
                    return;
                }

                if (WarningStates[_sender.Id].Contains(contact.Id))
                {
                    Logger.Debug($"{_sender.Id} - {_sender.Callsign}: Contact {contact.Id} already reported");
                    return;
                }

                Logger.Debug($"{_sender.Id} - {_sender.Callsign}: New contact {contact.Id} at {contact.Range} miles");

                using (var activity =
                           Constants.ActivitySource.StartActivity("WarningRadiusChecker.SendWarning", ActivityKind.Consumer))
                {
                    var response = $"{_sender.Callsign}, {_awacs}, Threat, {BogeyDope.BuildResponse(_sender, contact)}";
                    Logger.Debug($"{_sender.Id} - {_sender.Callsign}: Response: {response}");

                    var ssmlResponse =
                        $"<speak version=\"1.0\" xmlns=\"https://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name =\"{_voice}\">{response}</voice></speak>";

                    // Try twice for timeout reasons
                    var audioData = await Speaker.CreateResponse(ssmlResponse);

                    if (audioData == null)
                    {
                        Logger.Debug($"{_sender.Id} - {_sender.Callsign}:| First Synthesis failed, trying again");
                        audioData = await Task.Run(() => Speaker.CreateResponse(ssmlResponse));
                    }

                    if (audioData != null)
                    {
                        Logger.Info($"{_sender.Id} - {_sender.Callsign}: Outgoing Transmission: {response}");
                        _responseQueue.Enqueue(audioData);
                        WarningStates[_sender.Id].Add(contact.Id);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error(ex, $"{_sender.Id} - {_sender.Callsign}: Error checking warning radius");
            }
        }