Begin searching nodes

master
D4VID 7 months ago
parent ccc75c9f1e
commit df5cc73e90

@ -88,7 +88,6 @@ namespace CriticalPathAnalyzer.Client.Tool {
public static void RemoveHighLighting() { public static void RemoveHighLighting() {
if (_clusters == null) { if (_clusters == null) {
CriticalPathAnalyzerClient.LoggerInstance.Warn("Ignoring remove highlighting, clusters is null");
return; return;
} }

@ -2,6 +2,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using CriticalPathAnalyzer.Server.Network; using CriticalPathAnalyzer.Server.Network;
using CriticalPathAnalyzer.Server.Tool;
using CriticalPathAnalyzer.Shared.Packets.S2C; using CriticalPathAnalyzer.Shared.Packets.S2C;
using EccsLogicWorldAPI.Server.Injectors; using EccsLogicWorldAPI.Server.Injectors;
using EccsLogicWorldAPI.Shared.PacketWrapper; using EccsLogicWorldAPI.Shared.PacketWrapper;

@ -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<Cluster> Clusters; // bidirectionally connected clusters without delay
public int Time; // what point in time has been this cluster last updated
public Dictionary<int, int> NextNodes; // next cluster StateID / delay between them
public int? PrevNodeStateId; // the last cluster that updated this one
}
}

@ -9,7 +9,7 @@ using LogicAPI.Server.Components;
using LogicAPI.Services; using LogicAPI.Services;
using LogicWorld.Server.Circuitry; using LogicWorld.Server.Circuitry;
namespace CriticalPathAnalyzer.Server { namespace CriticalPathAnalyzer.Server.Tool {
public class ServerPathTracer { public class ServerPathTracer {
// Reflection/Delegate access helpers: // Reflection/Delegate access helpers:
private static readonly Func<InputPeg, Cluster> GetCluster; private static readonly Func<InputPeg, Cluster> GetCluster;
@ -44,8 +44,6 @@ namespace CriticalPathAnalyzer.Server {
) { ) {
response = null; response = null;
var clusterTime = new Dictionary<Cluster, int>();
CriticalPathAnalyzerServer.LoggerInstance.Info("Trace start"); CriticalPathAnalyzerServer.LoggerInstance.Info("Trace start");
// Validate, that the peg is actually existing: // Validate, that the peg is actually existing:
@ -54,23 +52,41 @@ namespace CriticalPathAnalyzer.Server {
return false; return false;
} }
var clusterNodes = new List<ClusterNode>();
var nodeQueue = new Queue<ClusterNode>();
// An input peg, only has a single cluster. // An input peg, only has a single cluster.
// An output peg however can be connected to multiple clusters. // An output peg however can be connected to multiple clusters.
// It only makes sense to then select all these clusters as primary cluster. // It only makes sense to then select all these clusters as primary cluster.
var collectedClusters = new HashSet<Cluster>(); var collectedClusters = new HashSet<Cluster>();
CollectMainClusters(start, collectedClusters); 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 // Collect clusters that get powered by the original cluster using relays or fast buffers
var collectedDrains = new HashSet<Cluster>(); var oneWayConnectedClusters = new HashSet<Cluster>();
var twoWayConnectedClusters = new HashSet<Cluster>();
foreach (Cluster cluster in collectedClusters) { 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<int, int>(),
});
var perimeterComponents = new HashSet<ComponentAddress>(); var perimeterComponents = new HashSet<ComponentAddress>();
var collectedNextClusters = new HashSet<Cluster>(); var collectedNextClusters = new HashSet<Cluster>();
@ -165,7 +181,8 @@ namespace CriticalPathAnalyzer.Server {
private static void GetLinkedClusters( private static void GetLinkedClusters(
Cluster startingPoint, Cluster startingPoint,
HashSet<Cluster> collectedClusters, HashSet<Cluster> oneWayConnectedClusters,
HashSet<Cluster> twoWayConnectedClusters,
Func<ClusterLinker, List<ClusterLinker>> linkedLinkerGetter Func<ClusterLinker, List<ClusterLinker>> linkedLinkerGetter
) { ) {
var clustersToProcess = new Queue<ClusterLinker>(); var clustersToProcess = new Queue<ClusterLinker>();
@ -175,17 +192,26 @@ namespace CriticalPathAnalyzer.Server {
clustersToProcess.Enqueue(startingLinker); clustersToProcess.Enqueue(startingLinker);
// While the starting cluster is no source, the algorithm needs to skip it when encountered. // While the starting cluster is no source, the algorithm needs to skip it when encountered.
// collectedClusters.Add(startingPoint);
while (clustersToProcess.TryDequeue(out ClusterLinker linkerToCheck)) { while (clustersToProcess.TryDequeue(out ClusterLinker linkerToCheck)) {
List<ClusterLinker> listOfLinkedLinkers = linkedLinkerGetter(linkerToCheck); // Is never null. List<ClusterLinker> listOfLinkedLinkers = linkedLinkerGetter(linkerToCheck); // Is never null.
foreach (ClusterLinker linkedLinker in listOfLinkedLinkers) { foreach (ClusterLinker linkedLinker in listOfLinkedLinkers) {
Cluster clusterOfLinkedLinker = linkedLinker.ClusterBeingLinked; // Should never be null. Cluster clusterOfLinkedLinker = linkedLinker.ClusterBeingLinked; // Should never be null.
if (collectedClusters.Add(clusterOfLinkedLinker)) { List<ClusterLinker> listOfBackLinkers = linkedLinkerGetter(linkedLinker); // Is never null.
// Element was not yet present in the array, so keep looking into it! if (listOfBackLinkers.Contains(linkerToCheck)) {
clustersToProcess.Enqueue(linkedLinker); // 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) { private static ClusterDetails CollectClusterInformation(Cluster cluster) {

@ -16,7 +16,7 @@ namespace CriticalPathAnalyzer.Shared.Packets.S2C {
[MessagePackObject] [MessagePackObject]
public sealed class ClusterDetails { public sealed class ClusterDetails {
[Key(0)] public List<PegAddress> Pegs; [Key(0)] public List<PegAddress> Pegs;
[Key(1)] public List<ComponentAddress> ConnectingComponents; [Key(1)] public List<ComponentAddress> ConnectingComponents; // Sockets
[Key(2)] public List<ComponentAddress> LinkingComponents; [Key(2)] public List<ComponentAddress> LinkingComponents; // Relays, fast buffers
} }
} }
Loading…
Cancel
Save