diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a54a88..18db580 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -149,6 +149,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
- Better VC-4 support for IcdConsole
- JSON refactoring for simpler deserialization
+## [8.8.0] - 2020-01-23
+### Added
+ - Added an overload to PriorityQueue for determing the de-duplication behaviour
+
## [8.7.2] - 2019-10-29
### Changed
- Fixed a bug with PriorityQueue de-duplication where a new command would be inserted in the wrong position
diff --git a/ICD.Common.Utils/Collections/PriorityQueue.cs b/ICD.Common.Utils/Collections/PriorityQueue.cs
index 34ab00d..2143ae7 100644
--- a/ICD.Common.Utils/Collections/PriorityQueue.cs
+++ b/ICD.Common.Utils/Collections/PriorityQueue.cs
@@ -79,6 +79,20 @@ namespace ICD.Common.Utils.Collections
m_Count++;
}
+ ///
+ /// Adds the item to the queue with the given priority at the given index.
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public void Enqueue([CanBeNull] T item, int priority, int position)
+ {
+ m_PriorityToQueue.GetOrAddNew(priority, ()=> new List())
+ .Insert(position, item);
+ m_Count++;
+ }
+
///
/// Enqueues the item at the beginning of the queue.
///
@@ -121,6 +135,27 @@ namespace ICD.Common.Utils.Collections
if (remove == null)
throw new ArgumentNullException("remove");
+ EnqueueRemove(item, remove, priority, false);
+ }
+
+ ///
+ /// Removes any items in the queue matching the predicate.
+ /// Appends the given item at the end of the given priority level.
+ /// This is useful for reducing duplication, or replacing items with something more pertinent.
+ ///
+ ///
+ ///
+ ///
+ ///
+ [PublicAPI]
+ public void EnqueueRemove([CanBeNull] T item, [NotNull] Func remove, int priority, bool deDuplicateToEndOfQueue)
+ {
+ if (remove == null)
+ throw new ArgumentNullException("remove");
+
+ int lowestMatchingPriority = int.MaxValue;
+ int? firstMatchingIndex = null;
+
foreach (KeyValuePair> kvp in m_PriorityToQueue.ToArray())
{
int[] removeIndices =
@@ -129,6 +164,12 @@ namespace ICD.Common.Utils.Collections
.Reverse()
.ToArray();
+ if (removeIndices.Any() && kvp.Key < lowestMatchingPriority )
+ {
+ lowestMatchingPriority = kvp.Key;
+ firstMatchingIndex = removeIndices.Last();
+ }
+
foreach (int removeIndex in removeIndices)
{
kvp.Value.RemoveAt(removeIndex);
@@ -139,7 +180,16 @@ namespace ICD.Common.Utils.Collections
m_PriorityToQueue.Remove(kvp.Key);
}
- Enqueue(item, priority);
+
+ if(deDuplicateToEndOfQueue)
+ Enqueue(item, priority);
+ else
+ {
+ if(firstMatchingIndex == null)
+ Enqueue(item, lowestMatchingPriority);
+ else
+ Enqueue(item, lowestMatchingPriority, firstMatchingIndex.Value);
+ }
}
///
diff --git a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs
index 7bcb3df..33db000 100644
--- a/ICD.Common.Utils/Extensions/DictionaryExtensions.cs
+++ b/ICD.Common.Utils/Extensions/DictionaryExtensions.cs
@@ -144,15 +144,15 @@ namespace ICD.Common.Utils.Extensions
///
[PublicAPI]
public static TValue GetOrAddNew([NotNull] this IDictionary extends,
- [NotNull] TKey key)
+ [NotNull] TKey key)
where TValue : new()
{
if (extends == null)
throw new ArgumentNullException("extends");
-// ReSharper disable CompareNonConstrainedGenericWithNull
+ // ReSharper disable CompareNonConstrainedGenericWithNull
if (key == null)
-// ReSharper restore CompareNonConstrainedGenericWithNull
+ // ReSharper restore CompareNonConstrainedGenericWithNull
throw new ArgumentNullException("key");
return extends.GetOrAddNew(key, () => ReflectionUtils.CreateInstance());
@@ -169,15 +169,15 @@ namespace ICD.Common.Utils.Extensions
///
[PublicAPI]
public static TValue GetOrAddNew([NotNull] this IDictionary extends,
- [NotNull] TKey key,
- [NotNull] Func valueFunc)
+ [NotNull] TKey key,
+ [NotNull] Func valueFunc)
{
if (extends == null)
throw new ArgumentNullException("extends");
-// ReSharper disable CompareNonConstrainedGenericWithNull
+ // ReSharper disable CompareNonConstrainedGenericWithNull
if (key == null)
-// ReSharper restore CompareNonConstrainedGenericWithNull
+ // ReSharper restore CompareNonConstrainedGenericWithNull
throw new ArgumentNullException("key");
if (valueFunc == null)