diff --git a/CHANGELOG.md b/CHANGELOG.md index e3028c9..317472c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Added DtNodeQueue UnitTest [@ikpil](https://github.com/ikpil) - Added RcSortedQueue UnitTest [@ikpil](https://github.com/ikpil) +- Added IComparable interface to RcAtomicLong [@ikpil](https://github.com/ikpil) ### Fixed ### Changed - Update Microsoft.NET.Test.Sdk 17.8.0 to 17.9.0 - +- Enhanced ToString method of DtNode to provide more detailed information. + ### Removed ### Special Thanks diff --git a/src/DotRecast.Core/Collections/RcSortedQueue.cs b/src/DotRecast.Core/Collections/RcSortedQueue.cs index 3d35193..60cc406 100644 --- a/src/DotRecast.Core/Collections/RcSortedQueue.cs +++ b/src/DotRecast.Core/Collections/RcSortedQueue.cs @@ -75,12 +75,18 @@ namespace DotRecast.Core.Collections public void Enqueue(T item) { + if (null == item) + return; + _items.Add(item); _dirty = true; } public bool Remove(T item) { + if (null == item) + return false; + //int idx = _items.BinarySearch(item, _comparer); // don't use this! Because reference types can be reused externally. int idx = _items.FindLastIndex(x => item.Equals(x)); if (0 > idx) diff --git a/src/DotRecast.Core/RcAtomicLong.cs b/src/DotRecast.Core/RcAtomicLong.cs index 0ea3e01..f224ffa 100644 --- a/src/DotRecast.Core/RcAtomicLong.cs +++ b/src/DotRecast.Core/RcAtomicLong.cs @@ -1,8 +1,9 @@ -using System.Threading; +using System; +using System.Threading; namespace DotRecast.Core { - public class RcAtomicLong + public class RcAtomicLong : IComparable { private long _location; @@ -15,6 +16,11 @@ namespace DotRecast.Core _location = location; } + public int CompareTo(RcAtomicLong other) + { + return Read().CompareTo(other.Read()); + } + public long IncrementAndGet() { return Interlocked.Increment(ref _location); diff --git a/src/DotRecast.Detour/DtNode.cs b/src/DotRecast.Detour/DtNode.cs index d061fe8..c1ef5cf 100644 --- a/src/DotRecast.Detour/DtNode.cs +++ b/src/DotRecast.Detour/DtNode.cs @@ -40,10 +40,19 @@ namespace DotRecast.Detour { this.index = index; } + + public static int ComparisonNodeTotal(DtNode a, DtNode b) + { + int compare = a.total.CompareTo(b.total); + if (0 != compare) + return compare; + + return a.index.CompareTo(b.index); + } public override string ToString() { - return "Node [id=" + id + "]"; + return $"Node [index={index} id={id} cost={cost} total={total}]"; } } } \ No newline at end of file diff --git a/src/DotRecast.Detour/DtNodeQueue.cs b/src/DotRecast.Detour/DtNodeQueue.cs index 15f0f3f..fd44bfe 100644 --- a/src/DotRecast.Detour/DtNodeQueue.cs +++ b/src/DotRecast.Detour/DtNodeQueue.cs @@ -28,7 +28,7 @@ namespace DotRecast.Detour public DtNodeQueue() { - m_heap = new RcSortedQueue((n1, n2) => n1.total.CompareTo(n2.total)); + m_heap = new RcSortedQueue(DtNode.ComparisonNodeTotal); } public int Count() @@ -64,7 +64,7 @@ namespace DotRecast.Detour public bool IsEmpty() { - return 0 == m_heap.Count(); + return m_heap.IsEmpty(); } } } \ No newline at end of file diff --git a/test/DotRecast.Detour.Test/DtNodeQueueTest.cs b/test/DotRecast.Detour.Test/DtNodeQueueTest.cs index bf542c7..5e6c7ad 100644 --- a/test/DotRecast.Detour.Test/DtNodeQueueTest.cs +++ b/test/DotRecast.Detour.Test/DtNodeQueueTest.cs @@ -1,5 +1,5 @@ using System.Collections.Generic; -using System.Linq; +using DotRecast.Core; using DotRecast.Core.Collections; using NUnit.Framework; @@ -7,15 +7,8 @@ namespace DotRecast.Detour.Test; public class DtNodeQueueTest { - [Test] - public void TestDtNodeQueue() + private static List ShuffledNodes(int count) { - var queue = new DtNodeQueue(); - - // check count - Assert.That(queue.Count(), Is.EqualTo(0)); - - const int count = 1000; var nodes = new List(); for (int i = 0; i < count; ++i) { @@ -23,13 +16,97 @@ public class DtNodeQueueTest node.total = i; nodes.Add(node); } - nodes.Shuffle(); - foreach (var node in nodes) + nodes.Shuffle(); + return nodes; + } + + [Test] + public void TestPushAndPop() + { + var queue = new DtNodeQueue(); + + // check count + Assert.That(queue.Count(), Is.EqualTo(0)); + + // null push + queue.Push(null); + Assert.That(queue.Count(), Is.EqualTo(0)); + + // test push + const int count = 1000; + var expectedNodes = ShuffledNodes(count); + foreach (var node in expectedNodes) { queue.Push(node); } Assert.That(queue.Count(), Is.EqualTo(count)); + + // test pop + expectedNodes.Sort(DtNode.ComparisonNodeTotal); + foreach (var node in expectedNodes) + { + Assert.That(queue.Peek(), Is.SameAs(node)); + Assert.That(queue.Pop(), Is.SameAs(node)); + } + + Assert.That(queue.Count(), Is.EqualTo(0)); } + + [Test] + public void TestClear() + { + var queue = new DtNodeQueue(); + + const int count = 555; + var expectedNodes = ShuffledNodes(count); + foreach (var node in expectedNodes) + { + queue.Push(node); + } + + Assert.That(queue.Count(), Is.EqualTo(count)); + + queue.Clear(); + Assert.That(queue.Count(), Is.EqualTo(0)); + Assert.That(queue.IsEmpty(), Is.True); + } + + [Test] + public void TestModify() + { + var queue = new DtNodeQueue(); + + const int count = 5000; + var expectedNodes = ShuffledNodes(count); + + foreach (var node in expectedNodes) + { + queue.Push(node); + } + + // check modify + queue.Modify(null); + + // change total + var r = new RcRand(); + foreach (var node in expectedNodes) + { + node.total = r.NextInt32() % (count / 50); // duplication for test + } + + // test modify + foreach (var node in expectedNodes) + { + queue.Modify(node); + } + + // check + expectedNodes.Sort(DtNode.ComparisonNodeTotal); + foreach (var node in expectedNodes) + { + Assert.That(queue.Pop(), Is.SameAs(node)); + } + } } \ No newline at end of file