feat(69): auto-tune channel-number allocator

Refs #69
This commit is contained in:
2026-07-16 22:16:43 +02:00
parent 9605f9ea65
commit 456c2c7c84
2 changed files with 58 additions and 0 deletions
@@ -0,0 +1,27 @@
using System.Globalization;
namespace ErsatzTV.Application.Channels;
public static class AutoTuneNumberAllocator
{
// Allocate `count` sequential integer channel numbers starting at `startingNumber`,
// skipping any number already present in `existingNumbers`. Channel.Number is a string,
// so numbers are returned as invariant-culture strings.
public static List<string> Allocate(int startingNumber, int count, ISet<string> existingNumbers)
{
var result = new List<string>(count);
int next = startingNumber;
while (result.Count < count)
{
string candidate = next.ToString(CultureInfo.InvariantCulture);
if (!existingNumbers.Contains(candidate))
{
result.Add(candidate);
}
next++;
}
return result;
}
}
@@ -0,0 +1,31 @@
using System.Collections.Generic;
using ErsatzTV.Application.Channels;
using NUnit.Framework;
using Shouldly;
namespace ErsatzTV.Tests.Application.Channels;
[TestFixture]
public class AutoTuneNumberAllocatorTests
{
[Test]
public void Allocate_Skips_Taken_Numbers()
{
var existing = new HashSet<string> { "500", "502" };
List<string> result = AutoTuneNumberAllocator.Allocate(500, 3, existing);
result.ShouldBe(new List<string> { "501", "503", "504" });
}
[Test]
public void Allocate_From_Empty_Is_Sequential()
{
List<string> result = AutoTuneNumberAllocator.Allocate(1, 3, new HashSet<string>());
result.ShouldBe(new List<string> { "1", "2", "3" });
}
[Test]
public void Allocate_Zero_Count_Is_Empty()
{
AutoTuneNumberAllocator.Allocate(500, 0, new HashSet<string>()).ShouldBeEmpty();
}
}