|
|
|
@ -109,14 +109,16 @@ namespace CriticalPathAnalyzer.Server.Tool {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (ClusterNode node in clusterNodes) {
|
|
|
|
|
FillNodeInformation(node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Collect information about each cluster:
|
|
|
|
|
response = new AnalyzePathResponse() {
|
|
|
|
|
RequestGuid = requestGuid,
|
|
|
|
|
Clusters = clusterNodes.SelectMany(node =>
|
|
|
|
|
node.Clusters.Select(cluster => CollectClusterInformation(cluster, node.Time))).ToList(),
|
|
|
|
|
Nodes = clusterNodes.Select(FillNodeInformation).ToList(),
|
|
|
|
|
CriticalPathLength = criticalPathLength,
|
|
|
|
|
LoopingClusters = loopingNodes.SelectMany(loopingNode => loopingNode.Clusters
|
|
|
|
|
.Select(cluster => CollectClusterInformation(cluster, 0))).ToList(),
|
|
|
|
|
LoopingNodes = loopingNodes.Select(FillNodeInformation).ToList(),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
logger.Info("Trace end");
|
|
|
|
@ -133,6 +135,7 @@ namespace CriticalPathAnalyzer.Server.Tool {
|
|
|
|
|
if (iterations % 1000 == 0) {
|
|
|
|
|
CriticalPathAnalyzerServer.LoggerInstance.Info($"{iterations} propagation iterations");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ClusterNode node = clusterNodes[index];
|
|
|
|
|
foreach ((int nextNodeIndex, int delay) in node.NextNodes) {
|
|
|
|
|
clusterNodes[nextNodeIndex].Time = node.Time + delay;
|
|
|
|
@ -169,6 +172,7 @@ namespace CriticalPathAnalyzer.Server.Tool {
|
|
|
|
|
if (iterations % 1000 == 0) {
|
|
|
|
|
CriticalPathAnalyzerServer.LoggerInstance.Info($"{iterations} loop iterations");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ((int nextNodeIndex, int _) in node.NextNodes) {
|
|
|
|
|
ClusterNode nextNode = clusterNodes[nextNodeIndex];
|
|
|
|
|
nextNode.PrevNodeIndexes.Remove(node.Index);
|
|
|
|
@ -250,8 +254,12 @@ namespace CriticalPathAnalyzer.Server.Tool {
|
|
|
|
|
logger.Info($"Finished after {iterations} iterations");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static HashSet<Cluster> GetClustersConnectedThroughRelays(Cluster cluster) {
|
|
|
|
|
var clusters = new HashSet<Cluster>() {cluster};
|
|
|
|
|
private static HashSet<Cluster> GetClustersConnectedThroughRelays(Cluster origin) {
|
|
|
|
|
var clusters = new HashSet<Cluster> {origin};
|
|
|
|
|
var queue = new Queue<Cluster>();
|
|
|
|
|
queue.Enqueue(origin);
|
|
|
|
|
|
|
|
|
|
while (queue.TryDequeue(out Cluster cluster)) {
|
|
|
|
|
foreach (InputPeg inputPeg in cluster.ConnectedInputs) {
|
|
|
|
|
LogicComponent component = inputPeg.LogicComponent;
|
|
|
|
|
if (component == null) {
|
|
|
|
@ -263,11 +271,23 @@ namespace CriticalPathAnalyzer.Server.Tool {
|
|
|
|
|
// Collect all next clusters connected via a relay (from the control input side)
|
|
|
|
|
if (inputPeg.Address == component.Inputs[1].Address) {
|
|
|
|
|
// one of the sides
|
|
|
|
|
// TODO: need to recursively check for further relays
|
|
|
|
|
CollectPegClusters(component.Inputs[2].Address, clusters);
|
|
|
|
|
if (component.Inputs[2].Address.IsInputAddress(out InputAddress inputAddress)) {
|
|
|
|
|
Cluster nextCluster = GetClusterAt(inputAddress);
|
|
|
|
|
if (clusters.Add(nextCluster)) {
|
|
|
|
|
// found a new cluster, continue searching
|
|
|
|
|
queue.Enqueue(nextCluster);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (inputPeg.Address == component.Inputs[2].Address) {
|
|
|
|
|
// the other side
|
|
|
|
|
CollectPegClusters(component.Inputs[1].Address, clusters);
|
|
|
|
|
if (component.Inputs[1].Address.IsInputAddress(out InputAddress inputAddress)) {
|
|
|
|
|
Cluster nextCluster = GetClusterAt(inputAddress);
|
|
|
|
|
if (clusters.Add(nextCluster)) {
|
|
|
|
|
// found a new cluster, continue searching
|
|
|
|
|
queue.Enqueue(nextCluster);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -381,78 +401,37 @@ namespace CriticalPathAnalyzer.Server.Tool {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static ClusterDetails CollectClusterInformation(Cluster cluster, int time) {
|
|
|
|
|
var details = new ClusterDetails {
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Obtain additional information about the clusters:
|
|
|
|
|
/// Collect all their pegs and sockets.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private static Node FillNodeInformation(ClusterNode node) {
|
|
|
|
|
var clientNode = new Node() {
|
|
|
|
|
Index = node.Index,
|
|
|
|
|
NextNodes = node.NextNodes,
|
|
|
|
|
PrevNodeIndexes = node.PrevNodeIndexes,
|
|
|
|
|
Time = node.Time,
|
|
|
|
|
Pegs = new List<PegAddress>(),
|
|
|
|
|
ConnectingComponents = new List<ComponentAddress>(),
|
|
|
|
|
Color = HsvToRgb(time * 20, 1, 1),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
foreach (Cluster cluster in node.Clusters) {
|
|
|
|
|
// Two lists are never null, according to how it is created and used:
|
|
|
|
|
IReadOnlyList<InputPeg> inputPegs = cluster.ConnectedInputs;
|
|
|
|
|
IReadOnlyList<OutputPeg> outputPegs = cluster.ConnectedOutputs;
|
|
|
|
|
|
|
|
|
|
foreach (InputPeg peg in inputPegs) {
|
|
|
|
|
details.Pegs.Add(peg.Address);
|
|
|
|
|
clientNode.Pegs.Add(peg.Address);
|
|
|
|
|
if (peg.SecretLinks != null && peg.SecretLinks.Any()) {
|
|
|
|
|
// Socket
|
|
|
|
|
details.ConnectingComponents.Add(peg.Address.ComponentAddress);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach (OutputPeg peg in outputPegs) {
|
|
|
|
|
details.Pegs.Add(peg.Address);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return details;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <param name="h">0 - 360</param>
|
|
|
|
|
/// <param name="s">0.0 - 1.0</param>
|
|
|
|
|
/// <param name="v">0.0 - 1.0</param>
|
|
|
|
|
/// <returns>0xrrggbb</returns>
|
|
|
|
|
private static int HsvToRgb(int h, float s, float v) {
|
|
|
|
|
s = Math.Clamp(s, 0, 1);
|
|
|
|
|
v = Math.Clamp(v, 0, 1);
|
|
|
|
|
h = (h % 360 + 360) % 360; // Ensure hue is within 0-359 range
|
|
|
|
|
|
|
|
|
|
float c = v * s;
|
|
|
|
|
float x = c * (1 - Math.Abs((h / 60.0f) % 2 - 1));
|
|
|
|
|
float m = v - c;
|
|
|
|
|
|
|
|
|
|
float r, g, b;
|
|
|
|
|
|
|
|
|
|
if (h < 60) {
|
|
|
|
|
r = c;
|
|
|
|
|
g = x;
|
|
|
|
|
b = 0;
|
|
|
|
|
} else if (h < 120) {
|
|
|
|
|
r = x;
|
|
|
|
|
g = c;
|
|
|
|
|
b = 0;
|
|
|
|
|
} else if (h < 180) {
|
|
|
|
|
r = 0;
|
|
|
|
|
g = c;
|
|
|
|
|
b = x;
|
|
|
|
|
} else if (h < 240) {
|
|
|
|
|
r = 0;
|
|
|
|
|
g = x;
|
|
|
|
|
b = c;
|
|
|
|
|
} else if (h < 300) {
|
|
|
|
|
r = x;
|
|
|
|
|
g = 0;
|
|
|
|
|
b = c;
|
|
|
|
|
} else {
|
|
|
|
|
r = c;
|
|
|
|
|
g = 0;
|
|
|
|
|
b = x;
|
|
|
|
|
clientNode.ConnectingComponents.Add(peg.Address.ComponentAddress);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rInt = (byte) ((r + m) * 255);
|
|
|
|
|
int gInt = (byte) ((g + m) * 255);
|
|
|
|
|
int bInt = (byte) ((b + m) * 255);
|
|
|
|
|
clientNode.Pegs.AddRange(outputPegs.Select(peg => peg.Address));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (rInt << 16) | (gInt << 8) | bInt;
|
|
|
|
|
return clientNode;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|