public static async Task <Dictionary <string, object> > GetBearingToNearestFriendlyAirbase(Point callerPosition, string group, int flight, int plane, int coalition) { var command = @"SELECT degrees(ST_AZIMUTH(request.position, airbase.position)) as bearing, ST_DISTANCE(request.position, airbase.position) as distance, airbase.name FROM public.units AS airbase CROSS JOIN LATERAL ( SELECT requester.position, requester.coalition FROM public.units AS requester WHERE (requester.pilot ILIKE '" + $"%{group} {flight}-{plane}%" + @"' OR requester.pilot ILIKE '" + $"%{group} {flight}{plane}%" + @"' ) ) as request WHERE ( airbase.type = 'Ground+Static+Aerodrome' AND airbase.coalition = " + $"{coalition}" + @" AND airbase.name NOT ILIKE '%FARP%' ) ORDER BY distance LIMIT 1"; Dictionary <string, object> output = null; using (var connection = new NpgsqlConnection(ConnectionString())) { await connection.OpenAsync(); using (var cmd = new NpgsqlCommand(command, connection)) { DbDataReader dbDataReader = await cmd.ExecuteReaderAsync(); await dbDataReader.ReadAsync(); if (dbDataReader.HasRows) { var bearing = Geospatial.TrueToMagnetic(callerPosition, Math.Round(dbDataReader.GetDouble(0))); // West == negative numbers so convert if (bearing < 0) { bearing += 360; } var range = (int)Math.Round(dbDataReader.GetDouble(1) * 0.539957d / 1000); // Nautical Miles var name = dbDataReader.GetString(2); output = new Dictionary <string, object> { { "name", name }, { "bearing", (int)Math.Round(bearing) }, { "range", range } }; } dbDataReader.Close(); } } return(output); }
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 string BuildResponse(Player sender, Contact contact) { var bearing = Regex.Replace(Geospatial.TrueToMagnetic(sender.Position, contact.Bearing).ToString("000"), "\\d{1}", " $0"); var range = contact.Range.ToString(); var altitude = contact.Altitude.ToString("N0"); var aspect = GetAspect(contact); var name = AircraftReportingNamePronouncer.PronounceName(contact); var response = $"Bra, {bearing}, {range}, {altitude}{aspect}"; if (name != null) { response += $", type <break time=\"50\" /> {name}."; } return(response); }
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 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 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}"); }); }