diff --git a/src/Infrastructure/BotSharp.Abstraction/Rules/Frontier.cs b/src/Infrastructure/BotSharp.Abstraction/Rules/Frontier.cs index 3929b36bd..74c9f89ce 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Rules/Frontier.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Rules/Frontier.cs @@ -31,11 +31,18 @@ public sealed class StackFrontier : IFrontier public void DrainTo(IFrontier other) { - // Reverse so the item that was on top is added first and - // therefore ends up at the same "priority" position in the target. - var items = _stack.ToList(); - items.Reverse(); - _stack.Clear(); + // Pop gives items in priority order (highest-weight first). + var items = new List(); + while (_stack.Count > 0) + { + items.Add(_stack.Pop()); + } + + if (other is StackFrontier) + { + items.Reverse(); + } + foreach (var item in items) { other.Add(item); @@ -58,9 +65,21 @@ public sealed class QueueFrontier : IFrontier public void DrainTo(IFrontier other) { + // Dequeue gives items in priority order (highest-weight first). + var items = new List(); while (_queue.Count > 0) { - other.Add(_queue.Dequeue()); + items.Add(_queue.Dequeue()); + } + + if (other is StackFrontier) + { + items.Reverse(); + } + + foreach (var item in items) + { + other.Add(item); } } } diff --git a/src/Infrastructure/BotSharp.Abstraction/Rules/RuleGraph.cs b/src/Infrastructure/BotSharp.Abstraction/Rules/RuleGraph.cs index 30ff4a4bf..fa7a411f3 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Rules/RuleGraph.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Rules/RuleGraph.cs @@ -121,20 +121,24 @@ public void AddEdge(RuleNode from, RuleNode to, EdgeItemPayload payload) } } - public IEnumerable<(RuleNode, RuleEdge)> GetParentNodes(RuleNode node) + public IEnumerable<(RuleNode, RuleEdge)> GetParentNodes(RuleNode node, bool ascending = false) { - return _edges.Where(e => e.To != null && e.To.Id.IsEqualTo(node.Id)) - .OrderByDescending(e => e.Weight) - .Select(e => (e.From, e)) - .ToList(); + var filtered = _edges.Where(e => e.To != null && e.To.Id.IsEqualTo(node.Id)); + var ordered = ascending + ? filtered.OrderBy(e => e.Weight) + : filtered.OrderByDescending(e => e.Weight); + + return ordered.Select(e => (e.From, e)).ToList(); } - public IEnumerable<(RuleNode, RuleEdge)> GetChildrenNodes(RuleNode node) + public IEnumerable<(RuleNode, RuleEdge)> GetChildrenNodes(RuleNode node, bool ascending = false) { - return _edges.Where(e => e.From != null && e.From.Id.IsEqualTo(node.Id)) - .OrderByDescending(e => e.Weight) - .Select(e => (e.To, e)) - .ToList(); + var filtered = _edges.Where(e => e.From != null && e.From.Id.IsEqualTo(node.Id)); + var ordered = ascending + ? filtered.OrderBy(e => e.Weight) + : filtered.OrderByDescending(e => e.Weight); + + return ordered.Select(e => (e.To, e)).ToList(); } public RuleGraphInfo GetGraphInfo() diff --git a/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs b/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs index d41eff321..4345e902e 100644 --- a/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs +++ b/src/Infrastructure/BotSharp.Core.Rules/Engines/RuleEngine.cs @@ -211,11 +211,7 @@ private async Task ExecuteGraphTraversal( ? new QueueFrontier<(RuleNode, RuleEdge)>() : new StackFrontier<(RuleNode, RuleEdge)>(); - // Seed the frontier with root's children - foreach (var child in graph.GetChildrenNodes(root)) - { - frontier.Add(child); - } + EnqueueChildren(frontier, graph, root); while (frontier.Count > 0) { @@ -345,7 +341,8 @@ private static void EnqueueChildren( RuleGraph graph, RuleNode parent) { - foreach (var child in graph.GetChildrenNodes(parent)) + var sortAscending = frontier is StackFrontier<(RuleNode, RuleEdge)>; + foreach (var child in graph.GetChildrenNodes(parent, sortAscending)) { frontier.Add(child); }