Converted foreach->for throughout. Also flattened the RelayDatabase to exclude part hashing.
[AntennaRange.git] / RelayExtensions.cs
blob:a/RelayExtensions.cs -> blob:b/RelayExtensions.cs
--- a/RelayExtensions.cs
+++ b/RelayExtensions.cs
@@ -2,7 +2,7 @@
 //
 // Extensions.cs
 //
-// Copyright © 2014, toadicus
+// Copyright © 2014-2015, toadicus
 // All rights reserved.
 //
 // Redistribution and use in source and binary forms, with or without modification,
@@ -28,8 +28,7 @@
 
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using ToadicusTools;
+using ToadicusTools.Extensions;
 
 namespace AntennaRange
 {
@@ -39,6 +38,50 @@
 	public static class RelayExtensions
 	{
 		/// <summary>
+		/// Returns the distance between two IAntennaRelays.
+		/// </summary>
+		/// <param name="relayOne">Relay one.</param>
+		/// <param name="relayTwo">Relay two.</param>
+		public static double DistanceTo(this IAntennaRelay relayOne, IAntennaRelay relayTwo)
+		{
+			return relayOne.vessel.DistanceTo(relayTwo.vessel);
+		}
+
+		/// <summary>
+		/// Returns the distance from this IAntennaRelay to the given CelestialBody
+		/// </summary>
+		/// <param name="relay">Relay.</param>
+		/// <param name="body">Body.</param>
+		public static double SqrDistanceTo(this IAntennaRelay relay, CelestialBody body)
+		{
+			double range = relay.vessel.DistanceTo(body) - body.Radius;
+
+			return range * range;
+		}
+
+		/// <summary>
+		/// Returns the distance between two IAntennaRelays.
+		/// </summary>
+		/// <param name="relayOne">Relay one.</param>
+		/// <param name="relayTwo">Relay two.</param>
+		public static double SqrDistanceTo(this IAntennaRelay relayOne, IAntennaRelay relayTwo)
+		{
+			return relayOne.vessel.sqrDistanceTo(relayTwo.vessel);
+		}
+
+		/// <summary>
+		/// Returns the distance from this IAntennaRelay to the given CelestialBody
+		/// </summary>
+		/// <param name="relay">Relay.</param>
+		/// <param name="body">Body.</param>
+		public static double DistanceTo(this IAntennaRelay relay, CelestialBody body)
+		{
+			double range = relay.vessel.DistanceTo(body) - body.Radius;
+
+			return range;
+		}
+
+		/// <summary>
 		/// Returns the distance between this IAntennaRelay and a Vessel
 		/// </summary>
 		/// <param name="relay">This <see cref="IAntennaRelay"/></param>
@@ -73,7 +116,7 @@
 		/// </summary>
 		/// <param name="relay">This <see cref="IAntennaRelay"/></param>
 		/// <param name="vessel">A <see cref="Vessel"/></param>
-		public static double sqrDistanceTo(this AntennaRelay relay, Vessel vessel)
+		public static double SqrDistanceTo(this AntennaRelay relay, Vessel vessel)
 		{
 			return relay.vessel.sqrDistanceTo(vessel);
 		}
@@ -83,9 +126,11 @@
 		/// </summary>
 		/// <param name="relay">This <see cref="IAntennaRelay"/></param>
 		/// <param name="body">A <see cref="CelestialBody"/></param>
-		public static double sqrDistanceTo(this AntennaRelay relay, CelestialBody body)
-		{
-			return relay.vessel.sqrDistanceTo(body);
+		public static double SqrDistanceTo(this AntennaRelay relay, CelestialBody body)
+		{
+			double dist = (relay.vessel.GetWorldPos3D() - body.position).magnitude - body.Radius;
+
+			return dist * dist;
 		}
 
 		/// <summary>
@@ -93,9 +138,82 @@
 		/// </summary>
 		/// <param name="relayOne">This <see cref="IAntennaRelay"/></param>
 		/// <param name="relayTwo">Another <see cref="IAntennaRelay"/></param>
-		public static double sqrDistanceTo(this AntennaRelay relayOne, IAntennaRelay relayTwo)
+		public static double SqrDistanceTo(this AntennaRelay relayOne, IAntennaRelay relayTwo)
 		{
 			return relayOne.vessel.sqrDistanceTo(relayTwo.vessel);
+		}
+
+		/// <summary>
+		/// Returns the square of the maximum link range between two relays.
+		/// </summary>
+		/// <returns>The maximum link range between two relays.</returns>
+		/// <param name="relayOne">Relay one.</param>
+		/// <param name="relayTwo">Relay two.</param>
+		public static double MaxLinkSqrDistanceTo(this AntennaRelay relayOne, IAntennaRelay relayTwo)
+		{
+			if (ARConfiguration.UseAdditiveRanges)
+			{
+				return relayOne.maxTransmitDistance * relayTwo.maxTransmitDistance;
+			}
+			else
+			{
+				return relayOne.maxTransmitDistance * relayOne.maxTransmitDistance;
+			}
+		}
+
+		/// <summary>
+		/// Returns the square of the maximum link range between a relay and Kerbin.
+		/// </summary>
+		/// <returns>The maximum link range between a relay and Kerbin.</returns>
+		/// <param name="relayOne">Relay one.</param>
+		/// <param name="body">A CelestialBody (must be Kerbin).</param>
+		public static double MaxLinkSqrDistanceTo(this AntennaRelay relayOne, CelestialBody body)
+		{
+			if (body != AntennaRelay.Kerbin)
+			{
+				return 0d;
+			}
+
+			if (ARConfiguration.UseAdditiveRanges)
+			{
+				return relayOne.maxTransmitDistance * ARConfiguration.KerbinRelayRange;
+			}
+			else
+			{
+				return relayOne.maxTransmitDistance * relayOne.maxTransmitDistance;
+			}
+		}
+
+		/// <summary>
+		/// Determines if relayOne is in range of the specified relayTwo.
+		/// </summary>
+		/// <returns><c>true</c> if relayOne is in range of the specifie relayTwo; otherwise, <c>false</c>.</returns>
+		/// <param name="relayOne">Relay one.</param>
+		/// <param name="relayTwo">Relay two.</param>
+		public static bool IsInRangeOf(this AntennaRelay relayOne, IAntennaRelay relayTwo)
+		{
+			if (relayOne == null || relayTwo == null)
+			{
+				return false;
+			}
+
+			return relayOne.SqrDistanceTo(relayTwo) <= relayOne.MaxLinkSqrDistanceTo(relayTwo);
+		}
+
+		/// <summary>
+		/// Determines if relayOne is in range of the specified body.
+		/// </summary>
+		/// <returns><c>true</c> if relayOne is in range of the specified body; otherwise, <c>false</c>.</returns>
+		/// <param name="relayOne">Relay one.</param>
+		/// <param name="body">Body.</param>
+		public static bool IsInRangeOf(this AntennaRelay relayOne, CelestialBody body)
+		{
+			if (relayOne == null || body == null)
+			{
+				return false;
+			}
+
+			return relayOne.SqrDistanceTo(body) <= relayOne.MaxLinkSqrDistanceTo(body);
 		}
 
 		/// <summary>
@@ -141,10 +259,11 @@
 			for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
 			{
 				relay = vesselRelays[rIdx];
-				if (relay.CanTransmit())
+				if (relay.LinkStatus > ConnectionStatus.None)
 				{
 					canTransmit = true;
-					if (relay.transmitDistance <= relay.nominalTransmitDistance)
+
+					if (relay.LinkStatus == ConnectionStatus.Optimal)
 					{
 						return ConnectionStatus.Optimal;
 					}
@@ -167,25 +286,85 @@
 		/// <param name="vessel">This <see cref="Vessel"/></param>
 		public static IAntennaRelay GetBestRelay(this Vessel vessel)
 		{
-			IAntennaRelay bestRelay = null;
-			double bestScore = double.PositiveInfinity;
-			double relayScore = double.NaN;
-
-			IList<IAntennaRelay> vesselRelays = RelayDatabase.Instance[vessel];
-			IAntennaRelay relay;
-			for (int rIdx = 0; rIdx < vesselRelays.Count; rIdx++)
-			{
-				relay = vesselRelays[rIdx];
-				relayScore = relay.transmitDistance / relay.maxTransmitDistance;
-
-				if (relayScore < bestScore)
-				{
-					bestScore = relayScore;
-					bestRelay = relay;
-				}
-			}
-
-			return bestRelay;
+			return RelayDatabase.Instance.GetBestVesselRelay(vessel);
+		}
+
+		/// <summary>
+		/// Logs a message on behalf of this relay
+		/// </summary>
+		public static void Log(this AntennaRelay relay, string format, params object[] args)
+		{
+			ToadicusTools.Logging.PostLogMessage(string.Format("[{0}] {1}", relay.ToString(), format), args);
+		}
+
+		/// <summary>
+		/// Logs a message on behalf of this relay
+		/// </summary>
+		public static void Log(this AntennaRelay relay, string msg)
+		{
+			ToadicusTools.Logging.PostLogMessage("[{0}] {1}", relay.ToString(), msg);
+		}
+
+		/// <summary>
+		/// Logs a warning message on behalf of this relay
+		/// </summary>
+		public static void LogWarning(this AntennaRelay relay, string format, params object[] args)
+		{
+			ToadicusTools.Logging.PostWarningMessage(string.Format("[{0}] {1}", relay.ToString(), format), args);
+		}
+
+		/// <summary>
+		/// Logs a warning message on behalf of this relay
+		/// </summary>
+		public static void LogWarning(this AntennaRelay relay, string msg)
+		{
+			ToadicusTools.Logging.PostWarningMessage("[{0}] {1}", relay.ToString(), msg);
+		}
+
+		/// <summary>
+		/// Logs an error message on behalf of this relay
+		/// </summary>
+		public static void LogError(this AntennaRelay relay, string format, params object[] args)
+		{
+			ToadicusTools.Logging.PostErrorMessage(string.Format("[{0}] {1}", relay.ToString(), format), args);
+		}
+
+		/// <summary>
+		/// Logs an error message on behalf of this relay
+		/// </summary>
+		public static void LogError(this AntennaRelay relay, string msg)
+		{
+			ToadicusTools.Logging.PostErrorMessage("[{0}] {1}", relay.ToString(), msg);
+		}
+
+		/// <summary>
+		/// Logs a debug-only message on behalf of this relay
+		/// </summary>
+		[System.Diagnostics.Conditional("DEBUG")]
+		public static void LogDebug(this AntennaRelay relay, string format, params object[] args)
+		{
+			using (var sb = ToadicusTools.Text.PooledStringBuilder.Get())
+			{
+				sb.AppendFormat("[{0}] ", relay == null ? "NULL" : relay.ToString());
+				sb.AppendFormat(format, args);
+
+				ToadicusTools.Logging.PostDebugMessage(sb.ToString());
+			}
+		}
+
+		/// <summary>
+		/// Logs a debug-only message on behalf of this relay
+		/// </summary>
+		[System.Diagnostics.Conditional("DEBUG")]
+		public static void LogDebug(this AntennaRelay relay, string msg)
+		{
+			using (var sb = ToadicusTools.Text.PooledStringBuilder.Get())
+			{
+				sb.AppendFormat("[{0}] ", relay == null ? "NULL" : relay.ToString());
+				sb.Append(msg);
+
+				ToadicusTools.Logging.PostDebugMessage(sb.ToString());
+			}
 		}
 	}