private async Task TransmitHeadingToNextWaypoint(string comment) { var nextWayPoint = _wayPoints.First(); var wH = (int)Geospatial.BearingTo(_sender.Position.Coordinate, new Coordinate(nextWayPoint.Latitude, nextWayPoint.Longitude)); var magneticHeading = Regex.Replace(Geospatial.TrueToMagnetic(_sender.Position, wH).ToString("000"), "\\d{1}", " $0"); _lastInstruction = DateTime.Now; await SendMessage($"fly heading {magneticHeading} for {nextWayPoint.Name} {comment}"); }
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."; } })); }
private async Task CheckInbound() { await PerformCheck(async() => { Logger.Debug($"{_sender.Id} - {_sender.Callsign}: Inbound Progress Check"); var nextWayPoint = _wayPoints.First(); Logger.Debug( $"{_sender.Id} is {nextWayPoint.DistanceTo(_sender.Position.Coordinate)} KM from {nextWayPoint.Name}"); // THINK ABOUT: Change this fixed value to a relative ratio based on the distances? if (nextWayPoint.DistanceTo(_sender.Position.Coordinate) < 1) { if (nextWayPoint.Name.Contains("Entry")) { await _atcState.FireAsync(Trigger.TurnBase); } else { await _atcState.FireAsync(Trigger.StartInbound); } return; } // No point with last minute instructions when we are sending them to initial soon anyway if (nextWayPoint.DistanceTo(_sender.Position.Coordinate) < 2.5) { return; } if (_sender.Heading == null) { Logger.Debug($"{_sender.Id} - {_sender.Callsign}: heading was null"); return; } Logger.Debug($"{_sender.Id} - {_sender.Callsign}: Time between two transmissions ok"); var sH = (int)_sender.Heading; var wH = (int)Geospatial.BearingTo(_sender.Position.Coordinate, new Coordinate(nextWayPoint.Latitude, nextWayPoint.Longitude)); var headingDiff = Math.Min((wH - sH) < 0 ? wH - sH + 360 : wH - sH, (sH - wH) < 0 ? sH - wH + 360 : sH - wH); Logger.Debug( $"{_sender.Id} - {_sender.Callsign}: Headings: Waypoint {wH}, Player {sH}, diff {headingDiff}"); Logger.Debug( $"{_sender.Id} - {_sender.Callsign}: {(DateTime.Now - _lastInstruction).TotalSeconds} since last transmission"); if ((DateTime.Now - _lastInstruction).TotalMilliseconds < _transmissionInterval) { Logger.Debug( $"{_sender.Id} - {_sender.Callsign}: Time between two transmissions too low, returning"); return; } if (headingDiff <= 5) { return; } var magneticHeading = Regex.Replace(Geospatial.TrueToMagnetic(_sender.Position, wH).ToString("000"), "\\d{1}", " $0"); _lastInstruction = DateTime.Now; await SendMessage($"fly heading {magneticHeading}"); }); }