From 456c2c7c8478d46efdbc2ee10be1eb88446a1cb0 Mon Sep 17 00:00:00 2001 From: Timothy Date: Thu, 16 Jul 2026 21:44:53 +0200 Subject: [PATCH] feat(69): auto-tune channel-number allocator Refs #69 --- .../Channels/AutoTuneNumberAllocator.cs | 27 ++++++++++++++++ .../Channels/AutoTuneNumberAllocatorTests.cs | 31 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 ErsatzTV.Application/Channels/AutoTuneNumberAllocator.cs create mode 100644 ErsatzTV.Tests/Application/Channels/AutoTuneNumberAllocatorTests.cs diff --git a/ErsatzTV.Application/Channels/AutoTuneNumberAllocator.cs b/ErsatzTV.Application/Channels/AutoTuneNumberAllocator.cs new file mode 100644 index 000000000..f57310fb6 --- /dev/null +++ b/ErsatzTV.Application/Channels/AutoTuneNumberAllocator.cs @@ -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 Allocate(int startingNumber, int count, ISet existingNumbers) + { + var result = new List(count); + int next = startingNumber; + while (result.Count < count) + { + string candidate = next.ToString(CultureInfo.InvariantCulture); + if (!existingNumbers.Contains(candidate)) + { + result.Add(candidate); + } + + next++; + } + + return result; + } +} diff --git a/ErsatzTV.Tests/Application/Channels/AutoTuneNumberAllocatorTests.cs b/ErsatzTV.Tests/Application/Channels/AutoTuneNumberAllocatorTests.cs new file mode 100644 index 000000000..d71c506fd --- /dev/null +++ b/ErsatzTV.Tests/Application/Channels/AutoTuneNumberAllocatorTests.cs @@ -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 { "500", "502" }; + List result = AutoTuneNumberAllocator.Allocate(500, 3, existing); + result.ShouldBe(new List { "501", "503", "504" }); + } + + [Test] + public void Allocate_From_Empty_Is_Sequential() + { + List result = AutoTuneNumberAllocator.Allocate(1, 3, new HashSet()); + result.ShouldBe(new List { "1", "2", "3" }); + } + + [Test] + public void Allocate_Zero_Count_Is_Empty() + { + AutoTuneNumberAllocator.Allocate(500, 0, new HashSet()).ShouldBeEmpty(); + } +}