From cc9d04acd7a1d091a7dbeaeafb2301d8c4a8e998 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 14 Aug 2024 15:10:33 +0200 Subject: [PATCH] Adds normalized kademlia positions --- .../OverwatchSupport/CodexTranscriptWriter.cs | 3 +- .../KademliaPositionFinder.cs | 68 +++++++++++++++++++ .../OverwatchSupport/ModelExtensions.cs | 1 + 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 ProjectPlugins/CodexPlugin/OverwatchSupport/KademliaPositionFinder.cs diff --git a/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs b/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs index 8fe2549..f836fa3 100644 --- a/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs +++ b/ProjectPlugins/CodexPlugin/OverwatchSupport/CodexTranscriptWriter.cs @@ -13,6 +13,7 @@ namespace CodexPlugin.OverwatchSupport private readonly ITranscriptWriter writer; private readonly CodexLogConverter converter; private readonly IdentityMap identityMap = new IdentityMap(); + private readonly KademliaPositionFinder positionFinder = new KademliaPositionFinder(); public CodexTranscriptWriter(ILog log, ITranscriptWriter transcriptWriter) { @@ -76,7 +77,7 @@ namespace CodexPlugin.OverwatchSupport { return new OverwatchCodexHeader { - Nodes = identityMap.Get() + Nodes = positionFinder.DeterminePositions(identityMap.Get()) }; } diff --git a/ProjectPlugins/CodexPlugin/OverwatchSupport/KademliaPositionFinder.cs b/ProjectPlugins/CodexPlugin/OverwatchSupport/KademliaPositionFinder.cs new file mode 100644 index 0000000..7e80341 --- /dev/null +++ b/ProjectPlugins/CodexPlugin/OverwatchSupport/KademliaPositionFinder.cs @@ -0,0 +1,68 @@ +using System.Numerics; +using Utils; +using YamlDotNet.Core.Tokens; + +namespace CodexPlugin.OverwatchSupport +{ + public class KademliaPositionFinder + { + public CodexNodeIdentity[] DeterminePositions(CodexNodeIdentity[] identities) + { + var zero = identities.First(); + var distances = CalculateDistances(zero, identities); + + var maxDistance = distances.Values.Max(); + CalculateNormalizedPositions(distances, maxDistance); + + return identities; + } + + private Dictionary CalculateDistances(CodexNodeIdentity zero, CodexNodeIdentity[] identities) + { + var result = new Dictionary(); + foreach (var id in identities.Skip(1)) + { + result.Add(id, GetDistance(zero.NodeId, id.NodeId)); + } + return result; + } + + private BigInteger GetDistance(string id1, string id2) + { + var one = BigInteger.Parse(id1, System.Globalization.NumberStyles.HexNumber).ToByteArray(); + var two = BigInteger.Parse(id2, System.Globalization.NumberStyles.HexNumber).ToByteArray(); + + var x = Xor(one, two); + return new BigInteger(x, isUnsigned: true); + } + + private byte[] Xor(byte[] one, byte[] two) + { + if (one.Length != two.Length) throw new Exception("Not equal length"); + + var result = new byte[one.Length]; + for (int i = 0; i < one.Length; i++) + { + uint a = one[i]; + uint b = two[i]; + uint c = (a ^ b); + result[i] = (byte)c; + } + return result; + } + + private void CalculateNormalizedPositions(Dictionary distances, BigInteger maxDistance) + { + foreach (var pair in distances) + { + pair.Key.KademliaNormalizedPosition = DeterminePosition(pair.Value, maxDistance); + } + } + + private float DeterminePosition(BigInteger value, BigInteger maxDistance) + { + var f = (value * 10000) / maxDistance; + return ((float)f) / 10000.0f; + } + } +} diff --git a/ProjectPlugins/CodexPlugin/OverwatchSupport/ModelExtensions.cs b/ProjectPlugins/CodexPlugin/OverwatchSupport/ModelExtensions.cs index 9503cb9..eba43e8 100644 --- a/ProjectPlugins/CodexPlugin/OverwatchSupport/ModelExtensions.cs +++ b/ProjectPlugins/CodexPlugin/OverwatchSupport/ModelExtensions.cs @@ -52,6 +52,7 @@ namespace CodexPlugin.OverwatchSupport public string Name { get; set; } = string.Empty; public string PeerId { get; set; } = string.Empty; public string NodeId { get; set; } = string.Empty; + public float KademliaNormalizedPosition { get; set; } = 0.0f; } #region Scenario Generated Events