public void TestBasicFunctionality() { var q = new PriorityQueue<int>(); Assert.AreEqual(0, q.Count); Assert.AreEqual(0, q.Capacity); Assert.Throws<InvalidOperationException>(() => q.Peek()); Assert.Throws<InvalidOperationException>(() => q.Dequeue()); q.Enqueue(5); q.Enqueue(2); q.Enqueue(4); Assert.AreEqual(3, q.Count); Assert.IsTrue(q.Capacity >= 3); Assert.IsTrue(q.Contains(2)); Assert.IsFalse(q.Contains(3)); Assert.AreEqual(3, q.ToArray().Length); CollectionAssert.AreEqual(q.ToArray(), q); Assert.AreEqual(2, q.Peek()); Assert.AreEqual(2, q.Dequeue()); Assert.AreEqual(4, q.Dequeue()); Assert.AreEqual(5, q.Dequeue()); }
public void Clear() { var pq = new PriorityQueue<int>(new int[] { 1, 2, 3 }); int temp; Assert.AreEqual(3, pq.Count); Assert.IsTrue(pq.Peek(out temp)); pq.Clear(); Assert.AreEqual(0, pq.Count); Assert.IsFalse(pq.Peek(out temp)); }
public void PriorityQueuePeekQueueNoChangeInCount() { var q = new PriorityQueue<int>(); q.Enqueue(AnyInt); var count = q.Count; q.Peek(); Assert.Equal(count, q.Count); }
public void Peek() { var pq = new PriorityQueue<int>(new int[] {1, 2, 3}); int temp; Assert.IsTrue(pq.Peek(out temp)); Assert.AreEqual(1, temp); Assert.AreEqual(1, pq.Dequeue()); Assert.IsTrue(pq.Peek(out temp)); Assert.AreEqual(2, temp); }
public void PriorityQueueClearEmptiesTheQueue() { var q = new PriorityQueue<int>(); q.Enqueue(AnyInt); q.Enqueue(AnyInt); q.Clear(); Assert.Equal(0, q.Count); Assert.Throws<InvalidOperationException>(() => q.Peek()); }
static void DijkstraAlgorithm(Dictionary<Node, List<Connection>> graph, Node source) { PriorityQueue<Node> queue = new PriorityQueue<Node>(); foreach (var node in graph) { if (source.ID != node.Key.ID) { node.Key.DijkstraDistance = double.PositiveInfinity; queue.Enqueue(node.Key); } } source.DijkstraDistance = 0.0d; queue.Enqueue(source); while (queue.Count != 0) { Node currentNode = queue.Peek(); if (currentNode.DijkstraDistance == double.PositiveInfinity) { break; } foreach (var neighbour in graph[currentNode]) { double potDistance = currentNode.DijkstraDistance + neighbour.Distance; if (potDistance < neighbour.Node.DijkstraDistance) { neighbour.Node.DijkstraDistance = potDistance; } } queue.Dequeue(); } }
public void TestPeek1() { var queue = new PriorityQueue<string> { "string", "anotherString" }; var poll = queue.Peek(); Assert.AreEqual(2, queue.Count); Assert.AreEqual("anotherString", poll); Assert.IsTrue(queue.Contains("anotherString")); }
public void DequeueTestString([PexAssumeUnderTest]List<string> elementList) { PriorityQueue<string> actual = new PriorityQueue<string>(elementList); string dequeuedElem = actual.Dequeue(); elementList.Sort(); PexAssert.AreEqual(elementList[0], dequeuedElem); if (elementList.Count > 1) PexAssert.AreEqual(elementList[1], actual.Peek()); PexAssert.AreEqual(elementList.Count - 1, actual.Count); }
public void PriorityQueuePeekEmptyQueueThrowsException() { var q = new PriorityQueue<int>(); Assert.Equal(0, q.Count); Assert.Throws<InvalidOperationException>(() => q.Peek()); }
public void TestPeek2() { var queue = new PriorityQueue<string>(); var poll = queue.Peek(); Assert.IsNull(poll); }
public void TestPeek() { PriorityQueue<int, int> q = new PriorityQueue<int, int>(); q.Enqueue(2, 2); q.Enqueue(1, 1); Assert.AreEqual(1, q.Peek()); Assert.AreEqual(2, q.Count); }
public void PriorityQueueAddElementsPeekReturnsHighestPriorityMessage() { var q = new PriorityQueue<int>(); q.Enqueue(0); q.Enqueue(4); q.Enqueue(2); q.Enqueue(3); q.Enqueue(1); var dequeued = q.Peek(); Assert.Equal(dequeued, 0); }
protected virtual void ReInsert(Node node, Int32 level) { MinimumBoundingBox nodeBox = node.CalculateMinimumBoundingBox(); PriorityQueue<NodeEntry, Single> distances = new PriorityQueue<NodeEntry, Single>(), reInsertions = new PriorityQueue<NodeEntry, Single>(); foreach (NodeEntry entry in node.NodeEntries) distances.Enqueue(entry, GetCenterDistance(nodeBox, entry.MinimumBoundingBox) * -1); for (int i = 0; i < Constants.NODES_FOR_REINSERT; i++) reInsertions.Enqueue(distances.Peek().Value, distances.Dequeue().Priority * -1); foreach (PriorityQueueItem<NodeEntry, Single> entry in reInsertions) node.RemoveNodeEntry(entry.Value); AdjustTree(node, level); while(reInsertions.Count > 0) Insert(reInsertions.Dequeue().Value, level); }
/// <summary> /// Returns all nodes in this quadrant that are fully contained within the given bounds. /// The nodes are returned in order of descending priority. /// </summary> /// <param name="bounds">The bounds that contains the nodes you want returned.</param> /// <returns>A lazy list of nodes along with the new potential of this quadrant.</returns> internal IEnumerable <Tuple <QuadNode, double> > GetNodesInside(Rect bounds) { double w = _bounds.Width / 2; double h = _bounds.Height / 2; // assumption that the Rect struct is almost as fast as doing the operations // manually since Rect is a value type. Rect topLeft = new Rect(_bounds.Left, _bounds.Top, w, h); Rect topRight = new Rect(_bounds.Left + w, _bounds.Top, w, h); Rect bottomLeft = new Rect(_bounds.Left, _bounds.Top + h, w, h); Rect bottomRight = new Rect(_bounds.Left + w, _bounds.Top + h, w, h); // Create a priority queue based on the potential of our nodes and our quads. var queue = new PriorityQueue <IEnumerator <Tuple <QuadNode, double> >, double>(true); if (_nodes != null) { queue.Enqueue(_nodes.GetNodesInside(bounds).GetEnumerator(), _nodes.Next.Priority); } if (_topLeft != null && topLeft.Intersects(bounds)) { queue.Enqueue(_topLeft.GetNodesInside(bounds).GetEnumerator(), _topLeft._potential); } if (_topRight != null && topRight.Intersects(bounds)) { queue.Enqueue(_topRight.GetNodesInside(bounds).GetEnumerator(), _topRight._potential); } if (_bottomLeft != null && bottomLeft.Intersects(bounds)) { queue.Enqueue(_bottomLeft.GetNodesInside(bounds).GetEnumerator(), _bottomLeft._potential); } if (_bottomRight != null && bottomRight.Intersects(bounds)) { queue.Enqueue(_bottomRight.GetNodesInside(bounds).GetEnumerator(), _bottomRight._potential); } // Then just loop through the queue. while (queue.Count > 0) { // Grab the enumerator with the highest potential. var enumerator = queue.Dequeue().Key; if (enumerator.MoveNext()) { // Get the current node and its new potential from the enumerator. var current = enumerator.Current; var node = current.Item1; var potential = current.Item2; // Determine our new potential. var newPotential = queue.Count > 0 ? !potential.IsNaN() ? Math.Max(potential, queue.Peek().Value) : queue.Peek().Value : potential; // It might be the case that the actual intersecting node has less priority than our remaining potential. if (newPotential > node.Priority) { // Store it for later in a container containing only it with no further potential. var store = Enumerable.Repeat(Tuple.Create(node, double.NaN), 1).GetEnumerator(); // Enqueue the container at the correct position. queue.Enqueue(store, node.Priority); } else { // Return it to our parent along with our new potential. yield return(Tuple.Create(node, newPotential)); } // If this enumerator has some more potential then re-enqueue it. if (!potential.IsNaN()) { queue.Enqueue(enumerator, potential); } } } }
public void MaxValuesHavePriorityTest() { PriorityQueue<int> actual = new PriorityQueue<int>(Strategy.Max) { 6, 1, 8, 9, 2, 3, 7 }; Assert.AreEqual(9, actual.Peek()); }
public void PeekTest() { PriorityQueue<int> actual = new PriorityQueue<int> { 12, 6, 3, 1, 0, 8 }; Assert.AreEqual(0, actual.Peek()); }
public void MaxValuesHavePriorityTest([PexAssumeUnderTest]List<int> elemList) { PexAssume.IsTrue(elemList.Count > 0); PriorityQueue<int> actual = new PriorityQueue<int>(elemList, Strategy.Max); elemList.Sort(); Assert.AreEqual(elemList[elemList.Count - 1], actual.Peek()); }
/// <summary> /// Single-source multiple-target version of Dijkstra's shortest path algorithm that returns shortest paths to a specified number of targets. /// </summary> /// <param name="source">Source vertex to start searching from.</param> /// <param name="targets">Target vertices to find shortest paths to.</param> /// <param name="count">Number of targets to find.</param> /// <returns>Mapping of all shortest paths from the source to all vertices up to <paramref name="count"/> targets.</returns> /// <remarks> /// The graph attached to <paramref name="source"/> should not contain any negative cycles. /// </remarks> public static IDictionary<IVertex, Path> ShortestPaths(IVertex source, ICollection<IVertex> targets, int count) { if (source == null) throw new ArgumentNullException("source"); if (targets == null) throw new ArgumentNullException("targets"); if (count < 1) throw new ArgumentOutOfRangeException("count"); // Create a priority queue where target vertices are prioritized by shortest path weight, starting with the source. PriorityQueue<IVertex, int> queue = new PriorityQueue<IVertex, int>(); IDictionary<IVertex, IEdge/*?*/> edges = new Dictionary<IVertex, IEdge/*?*/>(); // Initialize the source with a path of 0 length. queue[source] = 0; edges[source] = null; // Keep track of the explored vertices with known minimal length. IDictionary<IVertex, Path> shortestPaths = new Dictionary<IVertex, Path>(); // The number of explored targets. int targetsFound = 0; // Keep track of the upper bound on the distance to the closest 'count' nodes. // See "A Heuristic for Dijkstra's Algorithm" for details. PriorityQueue<IVertex, int> bounds = new PriorityQueue<IVertex, int>(true); foreach (IVertex target in targets) { bounds.Enqueue(target, int.MaxValue); if (bounds.Count == count) break; } // Traverse the queue. while (queue.Count > 0) { // Get the next closest vertex and copy it to the list of shortest paths. KeyValuePair<IVertex, int> item = queue.Dequeue(); source = item.Key; // We've found the shortest path to this vertex. IEdge/*?*/ shortest = edges[source]; if (shortest == null) shortestPaths[source] = new Path(source); else shortestPaths[source] = shortestPaths[shortest.Source] + shortest; // If we've explored the requested number of targets then break early. if (targets.Contains(source)) if (++targetsFound >= count) break; // Relax all outgoing edges from this vertex. foreach (IEdge edge in source.Edges) { // If we haven't explored the target yet. IVertex target = edge.Target; if (!shortestPaths.ContainsKey(target)) { // Calculate the new cost via this edge. int newCost = item.Value + edge.Cost; // Only relax the edge if the cost is an improvement (i.e. less than) the shortest paths seen so far. // See "A Heuristic for Dijkstra's Algorithm" for details. if (newCost < bounds.Peek().Value) { // Compare the new path with the current paths. int currentCost; if (!queue.TryGetValue(target, out currentCost) || newCost < currentCost) { // If no current path exists or the new path is shorter, then update the shortest path in the queue. queue[target] = newCost; edges[target] = edge; // If the target is a final target then update the cost in the list of upper bounds. if (targets.Contains(target)) { bounds[target] = newCost; // We only need to keep track of the closest 'count' targets. if (bounds.Count > count) bounds.Dequeue(); } } } } } } return shortestPaths; }
static void Main(string[] args) { string input; string result; List<Node> closed = new List<Node>(); PriorityQueue<Node> open = new PriorityQueue<Node>(); Console.WriteLine("enter initial string set: "); input = Console.ReadLine(); Console.WriteLine("Enter desired string set: "); result = Console.ReadLine(); Node start = new Node(input); Node goal = new Node(result); start.G = 0; //set G to amount of nodes traversed aka priority start.SetH(goal); //set the h value based on the goal node's value Node current = start; open.Enqueue(current); //add current node into open list while (open.Peek() != goal) { //generate children based on items in open list (current) List<Node> Children = getChildren(current, closed, open); current = open.Dequeue(); //pop current node closed.Add(current); //add current node into closed list //Console.WriteLine(current.GameString); foreach (Node child in Children) { //child.SetH(goal); open.Enqueue(child); } if (current.Equals(goal)) { Console.WriteLine("found path:"); Node last = current; List<Node> list = new List<Node>(); while (last.Parent != null) { list.Add(last); last = last.Parent; } list.Add(last); list.Reverse(); foreach (Node n in list) Console.WriteLine(n.ToString()); break; } if (open.isEmpty()) { Console.WriteLine("failed to find path"); break; } if (Children == null) { current = open.Dequeue(); //set first element of open list to current and pop continue; } } Console.ReadKey(true); }
public void SimpleTest() { var queue = new PriorityQueue<int, int>(); Assert.IsFalse(queue.HasItems); queue.Enqueue(1, 10); queue.Enqueue(3, 30); queue.Enqueue(5, 50); queue.Enqueue(4, 40); queue.Enqueue(2, 20); Assert.IsTrue(queue.HasItems); Assert.AreEqual(50, queue.Peek()); Assert.AreEqual(50, queue.Peek()); Assert.AreEqual(50, queue.Dequeue()); Assert.AreEqual(40, queue.Peek()); Assert.AreEqual(40, queue.Dequeue()); Assert.IsTrue(queue.HasItems); Assert.AreEqual(30, queue.Peek()); Assert.AreEqual(30, queue.Peek()); Assert.AreEqual(30, queue.Peek()); Assert.AreEqual(30, queue.Dequeue()); Assert.IsTrue(queue.HasItems); Assert.AreEqual(20, queue.Peek()); Assert.AreEqual(20, queue.Dequeue()); Assert.AreEqual(10, queue.Peek()); Assert.AreEqual(10, queue.Peek()); Assert.AreEqual(10, queue.Peek()); Assert.AreEqual(10, queue.Peek()); Assert.AreEqual(10, queue.Peek()); Assert.IsTrue(queue.HasItems); Assert.AreEqual(10, queue.Peek()); Assert.AreEqual(10, queue.Dequeue()); Assert.IsFalse(queue.HasItems); }
public void PeekShouldThrowWhenEmpty() { var queue = new PriorityQueue<int, int>(); queue.Peek(); }
public void PeekTest(int[] newElements) { try { PriorityQueue<int> actual = new PriorityQueue<int>(newElements); //get the minimum element int minVal = Int32.MaxValue; for (int i = 0; i < newElements.Length; i++) minVal = minVal > newElements[i] ? newElements[i] : minVal; PexAssert.AreEqual(minVal, actual.Peek()); PexGoal.Reached("normal"); } catch (InvalidOperationException) { PexGoal.Reached("exception"); throw; } }
void UpdateGraphWithDistancesFromNode(Node source) { PriorityQueue<Node> unVisitedNodes = new PriorityQueue<Node>(Nodes); // Time to create a min heap - O(n) // Does this update the value of 'source' in Nodes ? source.Distance = 0; while (!unVisitedNodes.Empty()) // O(n) { Node current = unVisitedNodes.Peek(); if (current.Distance == Constants.INFINITY) { break; } foreach (Node neighbor in current.Neighbors) // O(nm) { if (unVisitedNodes.Contains(neighbor)) { int tentative = 0; Edge edge = FindEdge(current, neighbor); // O(nml) tentative = current.Distance + edge.Cost; if (tentative < neighbor.Distance) { neighbor.Distance = tentative; neighbor.Previous = current; } } } unVisitedNodes.Dequeue(); } }
public void PeekNoItemsInTheQueueTest() { PriorityQueue<int> actual = new PriorityQueue<int>(); actual.Peek(); }
/// <summary> /// Calculates a path from start to end. When no path can be found in /// reasonable time the search is aborted and an incomplete path is returned. /// When refresh is not set to true a cached path is returned where possible. /// </summary> /// <param name="start">start position in 2d map space</param> /// <param name="end">end position in 2d map space</param> /// <param name="refresh">force to recalculate the path</param> /// <returns></returns> public Path CalculatePath(Unit unit, HexPoint start, HexPoint end, bool refresh = false) { // swap points to calculate the path backwards (from end to start) HexPoint temp = end; end = start; start = temp; // Check whether the requested path is already known PathRequest request = new PathRequest(unit,start, end); if (!refresh && knownPaths.ContainsKey(request)) { return knownPaths[request].Copy(); } // priority queue of nodes that yet have to be explored sorted in // ascending order by node costs (F) PriorityQueue<PathNode> open = new PriorityQueue<PathNode>(); // list of nodes that have already been explored LinkedList<IGridCell> closed = new LinkedList<IGridCell>(); // start is to be explored first PathNode startNode = new PathNode(unit,null, map[start], end); open.Enqueue(startNode); int steps = 0; PathNode current; do { // abort if calculation is too expensive if (++steps > stepLimit) return null; // examine the cheapest node among the yet to be explored current = open.Dequeue(); // Finish? if (current.Cell.Matches(end)) { // paths which lead to the requested goal are cached for reuse Path path = new Path(current); if (knownPaths.ContainsKey(request)) { knownPaths[request] = path.Copy(); } else { knownPaths.Add(request, path.Copy()); } return path; } // Explore all neighbours of the current cell ICollection<IGridCell> neighbours = map.GetNeighbourCells(current.Cell); foreach (IGridCell cell in neighbours) { // discard nodes that are not of interest if (closed.Contains(cell) || (cell.Matches(end) == false && !cell.IsWalkable(unit))) { continue; } // successor is one of current's neighbours PathNode successor = new PathNode(unit,current, cell, end); PathNode contained = open.Find(successor); if (contained != null && successor.F >= contained.F) { // This cell is already in the open list represented by // another node that is cheaper continue; } else if (contained != null && successor.F < contained.F) { // This cell is already in the open list but on a more expensive // path -> "integrate" the node into the current path contained.Predecessor = current; contained.Update(); open.Update(contained); } else { // The cell is not in the open list and therefore still has to // be explored open.Enqueue(successor); } } // add current to the list of the already explored nodes closed.AddLast(current.Cell); } while (open.Peek() != null); return null; }
public void DequeueTest() { PriorityQueue<int> actual = new PriorityQueue<int> { 12, 6, 3, 1, 0, 8 }; Assert.AreEqual(0, actual.Dequeue()); Assert.AreEqual(1, actual.Peek()); Assert.AreEqual(5, actual.Count); }
internal IEnumerable <Tuple <QuadNode, double> > GetNodesInside(Rect bounds) { double w = _bounds.Width / 2.0; double h = _bounds.Height / 2.0; Rect topLeft = new Rect(_bounds.Left, _bounds.Top, w, h); Rect topRight = new Rect(_bounds.Left + w, _bounds.Top, w, h); Rect bottomLeft = new Rect(_bounds.Left, _bounds.Top + h, w, h); Rect bottomRight = new Rect(_bounds.Left + w, _bounds.Top + h, w, h); PriorityQueue <IEnumerator <Tuple <QuadNode, double> >, double> queue = new PriorityQueue <IEnumerator <Tuple <QuadNode, double> >, double>(invert: true); if (_nodes != null) { queue.Enqueue(_nodes.GetNodesInside(bounds).GetEnumerator(), _nodes.Next.Priority); } if (_topLeft != null && topLeft.Intersects(bounds)) { queue.Enqueue(_topLeft.GetNodesInside(bounds).GetEnumerator(), _topLeft._potential); } if (_topRight != null && topRight.Intersects(bounds)) { queue.Enqueue(_topRight.GetNodesInside(bounds).GetEnumerator(), _topRight._potential); } if (_bottomLeft != null && bottomLeft.Intersects(bounds)) { queue.Enqueue(_bottomLeft.GetNodesInside(bounds).GetEnumerator(), _bottomLeft._potential); } if (_bottomRight != null && bottomRight.Intersects(bounds)) { queue.Enqueue(_bottomRight.GetNodesInside(bounds).GetEnumerator(), _bottomRight._potential); } while (queue.Count > 0) { IEnumerator <Tuple <QuadNode, double> > enumerator = queue.Dequeue().Key; if (enumerator.MoveNext()) { Tuple <QuadNode, double> current = enumerator.Current; QuadNode node = current.Item1; double potential = current.Item2; double newPotential = (queue.Count <= 0) ? potential : ((!potential.IsNaN()) ? Math.Max(potential, queue.Peek().Value) : queue.Peek().Value); if (newPotential > node.Priority) { IEnumerator <Tuple <QuadNode, double> > enumerator2 = Enumerable.Repeat(Tuple.Create(node, double.NaN), 1).GetEnumerator(); queue.Enqueue(enumerator2, node.Priority); } else { yield return(Tuple.Create(node, newPotential)); } if (!potential.IsNaN()) { queue.Enqueue(enumerator, potential); } } } }
public void Peek_on_empty() { var sut = new PriorityQueue<string>(); Assert.Throws<ArgumentOutOfRangeException>(() => sut.Peek()); }
public void Peek_on_non_empty() { var sut = new PriorityQueue<string>(); sut.Enqueue("a", 1); Assert.AreEqual("a", sut.Peek()); }
private static void Dijkstra(Dictionary<Node, List<Edge>> map, Node source) { PriorityQueue<Node> queue = new PriorityQueue<Node>(); foreach (KeyValuePair<Node, List<Edge>> pair in map) { if (pair.Key.Index != source.Index) { queue.Enqueue(pair.Key); pair.Key.DijkstraDistance = int.MaxValue; } } source.DijkstraDistance = 0; queue.Enqueue(source); Node currentNode; while (queue.Count != 0) { currentNode = queue.Peek(); if (currentNode.DijkstraDistance == int.MaxValue) { break; } foreach (Edge edge in map[currentNode]) { int potDistance = currentNode.DijkstraDistance + edge.Distance; if (potDistance < edge.Node.DijkstraDistance) { edge.Node.DijkstraDistance = potDistance; Node nextNode = new Node(edge.Node.Index); nextNode.DijkstraDistance = potDistance; queue.Enqueue(nextNode); } } queue.Dequeue(); } }
/// <summary> /// A discrete event simulation of combat over time. /// </summary> private void SimulateCombat(PriorityQueue<Spell> queue) { int threadID = System.Threading.Thread.CurrentThread.ManagedThreadId; float timer = 0; float timelimit = Options.Duration; //in seconds float latency = (Options.Latency / 1000); //in milliseconds DateTime start = DateTime.Now; Debug.WriteLine("-------------------"); Debug.WriteLine(String.Format("thread:[{0}] | time: {1:0.00} - simulation starts [timelimit: {2:0.00}]", threadID, timer, timelimit)); //Trace.TraceInformation("Combat simulation started!"); //Trace.Flush(); while (queue.Count != 0) { //get the spell at the front of the queue Spell spell = queue.Dequeue(); //this will be the next event that must occur in the combat timeline //so align the simulation timer to match the scheduledtime of the event timer = (spell.ScheduledTime); //events that are scheduled to occur after the simulation has ended are irrelevant if (timer >= timelimit) { timer = timelimit; queue.Clear(); continue; } #region if this is a dot spell, check that its ready if (spell.IsTicking) { //perform the tick Debug.WriteLine(String.Format("thread:[{0}] | time: {1:0.00} - {2} ticks for {3:0} damage", threadID, timer, spell.Name, spell.TickHitDamage())); //schedule the next tick spell.ScheduledTime += spell.TickTime(); //add it back to the queue queue.Enqueue(spell); //and skip to the next iteration continue; } #endregion //get the cast time or the GCD for this ability float casttime = spell.ExecuteTime() > 0 ? spell.ExecuteTime() : spell.GlobalCooldown(); //check if there is enough time left to cast this spell if ((timer + casttime + latency) < timelimit) { //TODO: recalculate stats to account for all combat effects (e.g. +spell, +haste, +spi, +crit bonuses etc) //spell.Stats = updatedStats; //or //spell.Execute(updatedStats); //the spell lands on the target, so calculate damage and trigger any related effects spell.Execute(); //prioritise - i.e. the next 'event' in the timeline //(think of this as the time when the spell can be recast [for direct damage spells] or the next tick [for dots]). spell.ScheduledTime += spell.GetTimeDelay(); timer += latency; //append to the events history //Events.Add(spell); if (spell.ScheduledTime < timelimit) { //this spell can be re-cast before the simulation ends, so add it back to the queue queue.Enqueue(spell); } else { //the simulation will end before this spell can be re-cast, so we wont bother adding it to the queue Debug.WriteLine(String.Format("thread:[{0}] | time: {1:0.00} - removing {2} - the simulation ends before it can be re-casted", threadID, timer, spell.Name)); } } else { //There is still some simulation time left, but not enough to cast the current spell. //This means that the simulation is almost finished. //However, there might be enough time to cast the next spell in the queue ... if (queue.Count > 0) { Spell next = queue.Peek(); Debug.WriteLine(String.Format("thread:[{0}] | time: {1:0.00} - not enough time to cast {2} [{3:0.00}s cast, {4:0.00}s lat] - trying next spell: {5}", threadID, timer, spell.Name, spell.ExecuteTime(), latency, next.Name)); } else { Debug.WriteLine(String.Format("thread:[{0}] | time: {1:0.00} - not enough time to cast {2} - [this was the last spell in the queue]", threadID, timer, spell.Name)); } } } Debug.WriteLine(String.Format("thread:[{0}] | time: {1:0.00} - simulation ends [no spells left in the queue]", threadID, timer)); DateTime stop = DateTime.Now; Debug.WriteLine(String.Format("thread:[{0}] | simulation time: {1} seconds", threadID, (stop - start).Seconds)); //Trace.TraceInformation("Combat simulation finished!"); //Trace.Flush(); }