diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighLighter.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighLighter.cs index 67e4c4b..c065d9c 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighLighter.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/client/tool/PathHighLighter.cs @@ -88,7 +88,6 @@ namespace CriticalPathAnalyzer.Client.Tool { public static void RemoveHighLighting() { if (_clusters == null) { - CriticalPathAnalyzerClient.LoggerInstance.Warn("Ignoring remove highlighting, clusters is null"); return; } diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs index 919dca3..a189fe9 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/CriticalPathAnalyzerServer.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using CriticalPathAnalyzer.Server.Network; +using CriticalPathAnalyzer.Server.Tool; using CriticalPathAnalyzer.Shared.Packets.S2C; using EccsLogicWorldAPI.Server.Injectors; using EccsLogicWorldAPI.Shared.PacketWrapper; diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ClusterNode.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ClusterNode.cs new file mode 100644 index 0000000..42bbafb --- /dev/null +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ClusterNode.cs @@ -0,0 +1,12 @@ +using System.Collections.Generic; +using LogicWorld.Server.Circuitry; + +namespace CriticalPathAnalyzer.Server.Tool { + public class ClusterNode { + public int Index; // "identifier" + public List Clusters; // bidirectionally connected clusters without delay + public int Time; // what point in time has been this cluster last updated + public Dictionary NextNodes; // next cluster StateID / delay between them + public int? PrevNodeStateId; // the last cluster that updated this one + } +} \ No newline at end of file diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/ServerPathTracer.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs similarity index 80% rename from CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/ServerPathTracer.cs rename to CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs index d83791e..5e3cb3d 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/ServerPathTracer.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/server/tool/ServerPathTracer.cs @@ -9,7 +9,7 @@ using LogicAPI.Server.Components; using LogicAPI.Services; using LogicWorld.Server.Circuitry; -namespace CriticalPathAnalyzer.Server { +namespace CriticalPathAnalyzer.Server.Tool { public class ServerPathTracer { // Reflection/Delegate access helpers: private static readonly Func GetCluster; @@ -44,8 +44,6 @@ namespace CriticalPathAnalyzer.Server { ) { response = null; - var clusterTime = new Dictionary(); - CriticalPathAnalyzerServer.LoggerInstance.Info("Trace start"); // Validate, that the peg is actually existing: @@ -54,23 +52,41 @@ namespace CriticalPathAnalyzer.Server { return false; } + var clusterNodes = new List(); + var nodeQueue = new Queue(); + // An input peg, only has a single cluster. // An output peg however can be connected to multiple clusters. // It only makes sense to then select all these clusters as primary cluster. var collectedClusters = new HashSet(); CollectMainClusters(start, collectedClusters); - CriticalPathAnalyzerServer.LoggerInstance.Info("collected main clusters"); + CriticalPathAnalyzerServer.LoggerInstance.Info($"collected {collectedClusters.Count} main clusters"); - // Collect clusters that get powered by the original cluster by fast buffers - var collectedDrains = new HashSet(); + // Collect clusters that get powered by the original cluster using relays or fast buffers + var oneWayConnectedClusters = new HashSet(); + var twoWayConnectedClusters = new HashSet(); foreach (Cluster cluster in collectedClusters) { - GetLinkedClusters(cluster, collectedDrains, GetFollowers); + GetLinkedClusters(cluster, oneWayConnectedClusters, twoWayConnectedClusters, GetFollowers); } - collectedClusters.UnionWith(collectedDrains); + CriticalPathAnalyzerServer.LoggerInstance.Info( + $"collected {oneWayConnectedClusters.Count} one way linked clusters"); + CriticalPathAnalyzerServer.LoggerInstance.Info( + $"collected {twoWayConnectedClusters.Count} two way linked clusters"); + + // collectedClusters.UnionWith(oneWayConnectedClusters); + collectedClusters.UnionWith(twoWayConnectedClusters); - CriticalPathAnalyzerServer.LoggerInstance.Info("collected linked clusters"); + CriticalPathAnalyzerServer.LoggerInstance.Info($"union {collectedClusters.Count} clusters"); + + clusterNodes.Add(new ClusterNode() { + Index = clusterNodes.Count, + Clusters = collectedClusters.ToList(), + Time = 0, + PrevNodeStateId = null, + NextNodes = new Dictionary(), + }); var perimeterComponents = new HashSet(); var collectedNextClusters = new HashSet(); @@ -165,7 +181,8 @@ namespace CriticalPathAnalyzer.Server { private static void GetLinkedClusters( Cluster startingPoint, - HashSet collectedClusters, + HashSet oneWayConnectedClusters, + HashSet twoWayConnectedClusters, Func> linkedLinkerGetter ) { var clustersToProcess = new Queue(); @@ -175,17 +192,26 @@ namespace CriticalPathAnalyzer.Server { clustersToProcess.Enqueue(startingLinker); // While the starting cluster is no source, the algorithm needs to skip it when encountered. - // collectedClusters.Add(startingPoint); while (clustersToProcess.TryDequeue(out ClusterLinker linkerToCheck)) { List listOfLinkedLinkers = linkedLinkerGetter(linkerToCheck); // Is never null. foreach (ClusterLinker linkedLinker in listOfLinkedLinkers) { Cluster clusterOfLinkedLinker = linkedLinker.ClusterBeingLinked; // Should never be null. - if (collectedClusters.Add(clusterOfLinkedLinker)) { - // Element was not yet present in the array, so keep looking into it! - clustersToProcess.Enqueue(linkedLinker); + List listOfBackLinkers = linkedLinkerGetter(linkedLinker); // Is never null. + if (listOfBackLinkers.Contains(linkerToCheck)) { + // bidirectional - a relay + if (twoWayConnectedClusters.Add(clusterOfLinkedLinker)) { + // Element was not yet present in the array, so keep looking into it! + clustersToProcess.Enqueue(linkedLinker); + } + } else { + // unidirectional - a fast buffer + oneWayConnectedClusters.Add(clusterOfLinkedLinker); + // stop propagation } } } + + twoWayConnectedClusters.Remove(startingPoint); } private static ClusterDetails CollectClusterInformation(Cluster cluster) { diff --git a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs index 7d6dd2e..1a4a053 100644 --- a/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs +++ b/CriticalPathAnalyzer/CriticalPathAnalyzer/src/shared/packets/s2c/AnalyzePathResponse.cs @@ -16,7 +16,7 @@ namespace CriticalPathAnalyzer.Shared.Packets.S2C { [MessagePackObject] public sealed class ClusterDetails { [Key(0)] public List Pegs; - [Key(1)] public List ConnectingComponents; - [Key(2)] public List LinkingComponents; + [Key(1)] public List ConnectingComponents; // Sockets + [Key(2)] public List LinkingComponents; // Relays, fast buffers } } \ No newline at end of file