Skip to content

Commit

Permalink
Added capture of server console input for hotkeys
Browse files Browse the repository at this point in the history
  • Loading branch information
Measurity committed Oct 6, 2023
1 parent 91748dc commit ad89813
Show file tree
Hide file tree
Showing 3 changed files with 416 additions and 62 deletions.
111 changes: 111 additions & 0 deletions Nitrox.Test/Model/DataStructures/CircularBufferTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace NitroxModel.DataStructures;

[TestClass]
public class CircularBufferTest
{
[TestMethod]
public void ShouldLimitSizeToMaxSize()
{
CircularBuffer<string> buffer = new(1);
buffer.Count.Should().Be(0);
buffer.Add("1");
buffer.Count.Should().Be(1);
buffer.Add("2");
buffer.Count.Should().Be(1);

buffer = new CircularBuffer<string>(5);
buffer.Count.Should().Be(0);
buffer.Add("1");
buffer.Count.Should().Be(1);
buffer.Add("2");
buffer.Count.Should().Be(2);
buffer.Add("3");
buffer.Count.Should().Be(3);
buffer.Add("4");
buffer.Count.Should().Be(4);
buffer.Add("5");
buffer.Count.Should().Be(5);
buffer.Add("6");
buffer.Count.Should().Be(5);
}

[TestMethod]
public void ShouldOverwriteOldestItemInBufferWhenCapped()
{
CircularBuffer<string> buffer = new(3);
buffer.Add("1");
buffer[0].Should().Be("1");
buffer.Add("2");
buffer[1].Should().Be("2");
buffer.Add("3");
buffer[2].Should().Be("3");
buffer.Add("4");
buffer[0].Should().Be("4");
buffer.Add("5");
buffer[1].Should().Be("5");
buffer[2].Should().Be("3");
buffer.Add("6");
buffer[2].Should().Be("6");
}

[TestMethod]
public void ShouldDiscardAddIfCapacityReached()
{
CircularBuffer<string> buffer = new(0);
buffer.Count.Should().Be(0);
buffer.Add("1");
buffer.Count.Should().Be(0);
}

[TestMethod]
public void ShouldBeEmptyWhenCleared()
{
CircularBuffer<string> buffer = new(10);
buffer.Count.Should().Be(0);
buffer.Add("1");
buffer.Add("1");
buffer.Add("1");
buffer.Count.Should().Be(3);
buffer.Clear();
buffer.Count.Should().Be(0);
}

[TestMethod]
public void ShouldGiveLastChanged()
{
CircularBuffer<int> buffer = new(3);
buffer.LastChangedIndex.Should().Be(-1);
buffer.Add(1);
buffer.LastChangedIndex.Should().Be(0);
buffer.Add(2);
buffer.LastChangedIndex.Should().Be(1);
buffer.Add(3);
buffer.LastChangedIndex.Should().Be(2);
buffer.Add(4);
buffer.LastChangedIndex.Should().Be(0);
buffer.Add(5);
buffer.LastChangedIndex.Should().Be(1);
buffer.Add(6);
buffer.LastChangedIndex.Should().Be(2);
buffer.Add(7);
buffer.Should().ContainInOrder(7, 5, 6);
}

[TestMethod]
public void ShouldReverseOrderWithNegativeIndex()
{
CircularBuffer<int> buffer = new(6);
buffer.AddRange(1, 2, 3, 4, 5, 6);
buffer[-1].Should().Be(6);
buffer[-2].Should().Be(5);
buffer[-3].Should().Be(4);
buffer[-4].Should().Be(3);
buffer[-5].Should().Be(2);
buffer[-6].Should().Be(1);
buffer[-7].Should().Be(6);
buffer[-8].Should().Be(5);
}
}
110 changes: 110 additions & 0 deletions NitroxModel/DataStructures/CircularBuffer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
using System;
using System.Collections;
using System.Collections.Generic;

namespace NitroxModel.DataStructures;

/// <summary>
/// Given a fixed size, fills to capacity and then overwrites earliest item.
/// </summary>
public class CircularBuffer<T> : IList<T>
{
private readonly List<T> data;
private readonly int maxSize;

/// <summary>
/// Returns the index last changed. If <see cref="CircularBuffer{T}" /> is empty, returns -1.
/// </summary>
public int LastChangedIndex { get; protected set; } = -1;

/// <summary>
/// Gets the item at the index, wrapping around the buffer if out-of-range.
/// </summary>
public T this[int index]
{
// Proper modulus operator which C# doesn't have. % = remainder operator and doesn't work in reverse for negative numbers.
get => data[Math.Abs((index % data.Count + data.Count) % data.Count)];
set => throw new NotSupportedException();
}

public int Count => data.Count;
public bool IsReadOnly => false;

public CircularBuffer(int maxSize, int initialCapacity = 0)
{
if (maxSize < 0) throw new ArgumentOutOfRangeException(nameof(maxSize), "Max size must be larger than -1");

this.maxSize = maxSize;
data = new List<T>(Math.Max(0, Math.Min(initialCapacity, maxSize)));
}

public int IndexOf(T item)
{
return data.IndexOf(item);
}

public void Insert(int index, T item)
{
throw new NotImplementedException();
}

public void RemoveAt(int index)
{
data.RemoveAt(index);
}

public bool Remove(T item)
{
return data.Remove(item);
}

public void Add(T item)
{
if (maxSize == 0) return;
if (data.Count < maxSize)
{
data.Add(item);
LastChangedIndex++;
return;
}

LastChangedIndex = (LastChangedIndex + 1) % maxSize;
data[LastChangedIndex] = item;
}

public void AddRange(IEnumerable<T> items)
{
foreach (T item in items) Add(item);
}

public void AddRange(params T[] items)
{
foreach (T item in items) Add(item);
}

public void Clear()
{
data.Clear();
LastChangedIndex = 0;
}

public bool Contains(T item)
{
return data.Contains(item);
}

public void CopyTo(T[] array, int arrayIndex)
{
data.CopyTo(array, arrayIndex);
}

public IEnumerator<T> GetEnumerator()
{
return data.GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
Loading

0 comments on commit ad89813

Please sign in to comment.