public string ProcessRadioCall(IRadioCall radioCall)
        {
            using (var activity = Constants.ActivitySource.StartActivity("Controller.ProcessRadioCall"))
            {
                if (radioCall.Intent == "None")
                {
                    return(Task.Run(() => None(radioCall)).Result);
                }

                if (string.IsNullOrEmpty(radioCall.ReceiverName))
                {
                    return(Task.Run(() => None(radioCall)).Result);
                }

                if (radioCall.Sender == null)
                {
                    activity?.AddTag("Response", "Not Recognized");
                    return(Task.Run(() => NullSender(radioCall)).Result);
                }

                if (radioCall.Sender.Id == null)
                {
                    activity?.AddTag("Response", "Not On Scope");
                    return(Task.Run(() => UnverifiedSender(radioCall)).Result);
                }

                switch (radioCall.Intent)
                {
                case "RadioCheck":
                    return(Task.Run(() => RadioCheck(radioCall)).Result);

                case "BogeyDope":
                    return(Task.Run(() => BogeyDope(radioCall)).Result);

                case "BearingToAirbase":
                    return(Task.Run(() => BearingToAirbase(radioCall)).Result);

                case "BearingToFriendlyPlayer":
                    return(Task.Run(() => BearingToFriendlyPlayer(radioCall)).Result);

                case "SetWarningRadius":
                    return(Task.Run(() => SetWarningRadius(radioCall, Voice, Radio.TransmissionQueue)).Result);

                case "Picture":
                    return(Task.Run(() => Picture(radioCall)).Result);

                case "Declare":
                    return(Task.Run(() => Declare(radioCall)).Result);

                case "ReadyToTaxi":
                    return(Task.Run(() => ReadyToTaxi(radioCall, Voice, Radio.TransmissionQueue)).Result);

                case "InboundToAirbase":
                    return(Task.Run(() => InboundToAirbase(radioCall)).Result);

                default:
                    return(Task.Run(() => Unknown(radioCall)).Result);
                }
            }
        }
Exemplo n.º 2
0
 protected override string UnverifiedSender(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall))
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + ", I cannot find you on scope.");
 }
Exemplo n.º 3
0
 protected override string InboundToAirbase(IRadioCall radioCall, string voice, ConcurrentQueue <byte[]> responseQueue)
 {
     if (!IsAddressedToController(radioCall))
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + "approach, " + Intents.InboundToAirbase.Process(radioCall, voice, responseQueue).Result);
 }
Exemplo n.º 4
0
 protected override string BearingToFriendlyPlayer(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall) || radioCall.Sender.Coalition == Coalition.Neutral)
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + Intents.BearingToFriendlyPlayer.Process(new BearingToFriendlyPlayerRadioCall(radioCall)).Result);
 }
Exemplo n.º 5
0
 protected override string RadioCheck(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall))
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + "ground, five-by-five");
 }
Exemplo n.º 6
0
 protected override string ReadyToTaxi(IRadioCall radioCall, string voice, ConcurrentQueue <byte[]> responseQueue)
 {
     if (!IsAddressedToController(radioCall))
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + "ground, " + ReadytoTaxi.Process(radioCall, voice, responseQueue).Result);
 }
Exemplo n.º 7
0
 protected override string Picture(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall))
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + "we do not support picture calls.");
 }
Exemplo n.º 8
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.");
        }
Exemplo n.º 9
0
 protected override string SetWarningRadius(IRadioCall radioCall, string voice, ConcurrentQueue <byte[]> responseQueue)
 {
     if (!IsAddressedToController(radioCall) || radioCall.Sender.Coalition == Coalition.Neutral)
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + Intents.SetWarningRadius.Process(new SetWarningRadiusRadioCall(radioCall), voice, responseQueue).Result);
 }
Exemplo n.º 10
0
 protected override string Declare(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall) || radioCall.Sender.Coalition == Coalition.Neutral)
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + "we do not support declare calls.");
 }
Exemplo n.º 11
0
 protected override string Unknown(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall))
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + ", I could not understand your transmission");
 }
Exemplo n.º 12
0
 protected override string BogeyDope(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall) || radioCall.Sender.Coalition == Coalition.Neutral)
     {
         return(null);
     }
     return(ResponsePrefix(radioCall) + Intents.BogeyDope.Process(radioCall).Result);
 }
Exemplo n.º 13
0
 protected override string NullSender(IRadioCall radioCall)
 {
     if (!IsAddressedToController(radioCall))
     {
         return(null);
     }
     return("Last transmitter, I could not recognize your call-sign");
 }
 private void LogTransmissionToDiscord(IRadioCall radioCall, string response)
 {
     using (Constants.ActivitySource.StartActivity("LogTransmissionToDiscord"))
     {
         Logger.Debug($"{_logClientId}| Building Discord Request/Response message");
         var transmission = $"Transmission Intent: {radioCall.Intent}\n" +
                            $"Request: {radioCall.Message}\n" +
                            $"Response: {response ?? "**IGNORED**"}";
         _ = DiscordClient.LogTransmissionToDiscord(transmission, Controller.Radio, SrsClient).ConfigureAwait(false);
     }
 }
Exemplo n.º 15
0
        public static async Task <string> Process(IRadioCall radioCall)
        {
            switch (radioCall.AirbaseName)
            {
            case null:
                return("I could not recognize the airbase name");

            case "nearest":
                return(await NearestAirbase(radioCall));

            default:
                return(await NamedAirbase(radioCall));
            }
        }
Exemplo n.º 16
0
        public static async Task <string> Process(IRadioCall radioCall, string voice,
                                                  ConcurrentQueue <byte[]> responseQueue)
        {
            return(await Task.Run(() =>
            {
                try
                {
                    var airfield = Constants.Airfields.First(x => x.Name == radioCall.ReceiverName);
                    var approachRoute = new ApproachController(airfield).GetApproachRoute(radioCall.Sender.Position);

                    var initialTrueBearing = Geospatial.BearingTo(radioCall.Sender.Position.Coordinate,
                                                                  new Coordinate(approachRoute.First().Latitude, approachRoute.First().Longitude));

                    var initialMagneticBearing =
                        Regex.Replace(
                            Geospatial.TrueToMagnetic(radioCall.Sender.Position, initialTrueBearing).ToString("000"),
                            "\\d{1}", " $0");

                    var response =
                        $"fly heading {initialMagneticBearing}, descend and maintain 2,000, reduce speed 2 0 0 knots, for vectors to {approachRoute.Last().Name}, {approachRoute.First().Name}";

                    var currentPosition = new NavigationPoint
                    {
                        Name = "Current Position",
                        Latitude = radioCall.Sender.Position.Coordinate.Latitude,
                        Longitude = radioCall.Sender.Position.Coordinate.Longitude
                    };

                    approachRoute = approachRoute.Prepend(currentPosition).ToList();

                    new AtcProgressChecker(radioCall.Sender, airfield, voice, approachRoute, responseQueue)
                    .CalledInbound();

                    return response;
                }
                catch (InvalidOperationException)
                {
                    return "There are no ATC services currently available at this airfield.";
                }
                catch (NoActiveRunwaysFoundException ex)
                {
                    Logger.Error(ex, "No Active Runways found");
                    return "We could not find any active runways.";
                }
            }));
        }
Exemplo n.º 17
0
        protected override bool IsAddressedToController(IRadioCall radioCall)
        {
            Logger.Debug($"Defined Callsign is {Callsign}, Received Callsign is {radioCall.AwacsCallsign}");

            if (string.IsNullOrEmpty(radioCall.AwacsCallsign))
            {
                return(false);
            }

            if (string.IsNullOrEmpty(Callsign))
            {
                return(true);
            }

            var result = string.IsNullOrEmpty(Callsign) != true && (radioCall.ReceiverName.ToLower() == "anyface" || radioCall.ReceiverName.ToLower().Equals(Callsign.ToLower()));

            return(result);
        }
Exemplo n.º 18
0
        public static async Task <string> Process(IRadioCall radioCall, string voice, ConcurrentQueue <byte[]> responseQueue)
        {
            return(await Task.Run(() =>
            {
                var taxiInstructions = DummyInstructions;
                Airfield airfield;
                try
                {
                    airfield = Constants.Airfields.First(x => x.Name == radioCall.ReceiverName);
                }
                catch (InvalidOperationException)
                {
                    return "There are no ATC services currently available at this airfield.";
                }

                try
                {
                    if (airfield.Runways.Count == 0 || airfield.NavigationGraph.EdgeCount == 0)
                    {
                        return "There are no ATC services currently available at this airfield.";
                    }

                    taxiInstructions = new GroundController(airfield).GetTaxiInstructions(radioCall.Sender.Position);

                    Logger.Debug(
                        $"{radioCall.Sender.Id} route is {string.Join(", ", taxiInstructions.TaxiPoints.Select(t => t.Name))}");

                    var spokenInstructions = ConvertTaxiInstructionsToSsml(taxiInstructions);
                    new AtcProgressChecker(radioCall.Sender, airfield, voice, taxiInstructions.TaxiPoints,
                                           responseQueue).CalledTaxi();
                    return spokenInstructions;
                }
                catch (NoActiveRunwaysFoundException ex)
                {
                    Logger.Error(ex, "No Active Runways found");
                    return "We could not find any active runways.";
                }
                catch (TaxiPathNotFoundException ex)
                {
                    Logger.Error(ex, "No Path found");
                    return $"We could not find a path from your position to {taxiInstructions.DestinationName}.";
                }
            }));
        }
Exemplo n.º 19
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);
        }
Exemplo n.º 20
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);
        }
Exemplo n.º 21
0
        private string ResponsePrefix(IRadioCall radioCall)
        {
            string responseCallsign;

            if (string.IsNullOrEmpty(Callsign) != true)
            {
                responseCallsign = Callsign;
            }
            else if (radioCall.AwacsCallsign != null && radioCall.AwacsCallsign.ToLower().Equals("anyface"))
            {
                responseCallsign = DefaultCallsign; // Overlord is the default callsign;
            }
            else if (string.IsNullOrEmpty(Callsign) && string.IsNullOrEmpty(radioCall.AwacsCallsign))
            {
                responseCallsign = DefaultCallsign; // Overlord is the default callsign;
            }
            else
            {
                responseCallsign = radioCall.AwacsCallsign;
            }
            return($"{radioCall.Sender.Callsign}, {responseCallsign}, ");
        }
Exemplo n.º 22
0
 protected override string None(IRadioCall radioCall)
 {
     return(null);
 }
        private async Task ProcessRecognizedCall(SpeechRecognitionEventArgs e)
        {
            using (var activity = Constants.ActivitySource.StartActivity("ProcessRecognizedCall", ActivityKind.Server))
            {
                Logger.Info($"{_logClientId}| Incoming Transmission: {e.Result.Text}");
                var luisJson = Task.Run(() => LuisService.ParseIntent(e.Result.Text)).Result;
                Logger.Debug($"{_logClientId}| LUIS Response: {luisJson}");

                IRadioCall radioCall = Controller is AtcController ? new AtcRadioCall(luisJson) : new BaseRadioCall(luisJson);

                MetricsManager.Instance.RecordRadioCall(radioCall.Intent, $"{_frequency / 1000000} - Bot {_botType}");

                activity?.AddTag("Frequency", _frequency);
                activity?.AddTag("BotType", _botType);
                activity?.AddTag("Callsign", _callsign);
                activity?.AddTag("Sender", radioCall.Sender?.Callsign);
                activity?.AddTag("Intent", radioCall.Intent);
                activity?.AddTag("Request", radioCall.Message);

                var response = Controller.ProcessRadioCall(radioCall);
                activity?.AddTag("Response Text", response);

                if (!string.IsNullOrEmpty(response))
                {
                    Logger.Info($"{_logClientId}| Outgoing Transmission: {response}");

                    // Try twice to avoid transient C**k-ups resulting in a failure response
                    var audioResponse = await Task.Run(() => Speaker.CreateResponse(
                                                           $"<speak version=\"1.0\" xmlns=\"https://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name =\"{Controller.Voice}\">{response}</voice></speak>"));

                    if (audioResponse == null)
                    {
                        Logger.Debug($"{_logClientId}| First Synthesis failed, trying again");
                        audioResponse = await Task.Run(() => Speaker.CreateResponse(
                                                           $"<speak version=\"1.0\" xmlns=\"https://www.w3.org/2001/10/synthesis\" xml:lang=\"en-US\"><voice name =\"{Controller.Voice}\">{response}</voice></speak>"));
                    }

                    if (audioResponse == null)
                    {
                        activity?.AddTag("Response", "Failure");
                        activity?.AddEvent(new ActivityEvent("Synthesis Failure"));
                        Logger.Error($"{_logClientId}| Synthesis Failure");
                        using (Constants.ActivitySource.StartActivity("EnqueueResponseAudio", ActivityKind.Producer))
                        {
                            Logger.Trace($"{_logClientId}| Sending Failure Message");
                            Controller.Radio.TransmissionQueue.Enqueue(FailureMessage);
                        }
                    }
                    else
                    {
                        activity?.AddTag("Response", "Success");
                        using (Constants.ActivitySource.StartActivity("EnqueueResponseAudio", ActivityKind.Producer))
                        {
                            Controller.Radio.TransmissionQueue.Enqueue(audioResponse);
                        }
                    }
                }
                else
                {
                    activity?.AddTag("Response", "Ignored");
                    Logger.Info($"{_logClientId}| Radio Call Ignored due to null response for Radio Call Processing");
                }

                if (Controller.Radio.discordTransmissionLogChannelId > 0)
                {
                    LogTransmissionToDiscord(radioCall, response);
                }
            }
        }
 public SetWarningRadiusRadioCall(IRadioCall baseRadioCall) : base(baseRadioCall)
 {
 }
Exemplo n.º 25
0
        protected override bool IsAddressedToController(IRadioCall radioCall)
        {
            var atcRadioCall = (AtcRadioCall)radioCall;

            return(Constants.Airfields.Any(airfield => airfield.Name.Equals(atcRadioCall.AirbaseName) && atcRadioCall.ControlName != "traffic"));
        }
Exemplo n.º 26
0
 protected override bool IsAddressedToController(IRadioCall radioCall)
 {
     return(false);
 }
Exemplo n.º 27
0
 protected override string SetWarningRadius(IRadioCall radioCall, string voice, ConcurrentQueue <byte[]> responseQueue)
 {
     return($"{radioCall.Sender.Callsign}, This is an ATC frequency");
 }
Exemplo n.º 28
0
 protected override string Picture(IRadioCall radioCall)
 {
     return($"{radioCall.Sender.Callsign}, This is an ATC frequency");
 }
Exemplo n.º 29
0
 protected override string BearingToFriendlyPlayer(IRadioCall radioCall)
 {
     return($"{radioCall.Sender.Callsign}, This is an ATC frequency");
 }
Exemplo n.º 30
0
        private static string ResponsePrefix(IRadioCall radioCall)
        {
            var name = Constants.Airfields.Any(airfield => airfield.Name.Equals(radioCall.AirbaseName)) ? AirbasePronouncer.PronounceAirbase(radioCall.AirbaseName) : "ATC";

            return($"{radioCall.Sender.Callsign}, {name} ");
        }