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}"); } } }
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); }
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); }
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); }
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"); } }
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"); } }