From 5a9d27e196718dfc9d04bbe95fb2e02c9438f575 Mon Sep 17 00:00:00 2001 From: Jason Dove <1695733+jasongdove@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:24:11 +0000 Subject: [PATCH] make yaml playout count an expression (#2102) --- CHANGELOG.md | 8 ++++++ .../Scheduling/PlaylistEnumerator.cs | 2 ++ .../Handlers/YamlPlayoutCountHandler.cs | 25 ++++++++++++++++++- .../Handlers/YamlPlayoutSkipItemsHandler.cs | 8 ++++-- .../Models/YamlPlayoutCountInstruction.cs | 2 +- 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d916d52f..4b7b04863 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,6 +54,14 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - `count / 2` will start in the middle of the content - `random` will start at a random point in the content - `2` (similar to before this change) will skip the first two items in the content +- YAML playout: make `count` an expression + - The following parameters can be used: + - `count`: the total number of items in the content + - `random`: a random number between zero and (count - 1) + - For example: + - `count / 2` will play half of the items in the content + - `random % 4 + 1` will play between 1 and 4 items + - `2` (similar to before this change) will play exactly two items ### Changed - Allow `Other Video` libraries and `Image` libraries to use the same folders diff --git a/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs b/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs index 0b405c241..50679c947 100644 --- a/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs +++ b/ErsatzTV.Core/Scheduling/PlaylistEnumerator.cs @@ -46,6 +46,8 @@ public class PlaylistEnumerator : IMediaCollectionEnumerator public int Count => throw new NotSupportedException("Count isn't used for playlist enumeration"); + public int CountForRandom => _allMediaItemIds.Count; + public Option MinimumDuration { get; private set; } public void MoveNext() diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs index ac393203a..1aeab4cd2 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutCountHandler.cs @@ -28,7 +28,30 @@ public class YamlPlayoutCountHandler(EnumeratorCache enumeratorCache) : YamlPlay foreach (IMediaCollectionEnumerator enumerator in maybeEnumerator) { - for (var i = 0; i < count.Count; i++) + var random = new Random(context.Playout.Seed + context.InstructionIndex); + int enumeratorCount = enumerator is PlaylistEnumerator playlistEnumerator + ? playlistEnumerator.CountForRandom + : enumerator.Count; + var expression = new NCalc.Expression(count.Count); + expression.EvaluateParameter += (name, e) => + { + e.Result = name switch + { + "count" => enumeratorCount, + "random" => random.Next() % enumeratorCount, + _ => e.Result + }; + }; + + object expressionResult = expression.Evaluate(); + int countValue = expressionResult switch + { + double doubleResult => (int)Math.Floor(doubleResult), + int intResult => intResult, + _ => 0 + }; + + for (var i = 0; i < countValue; i++) { foreach (MediaItem mediaItem in enumerator.Current) { diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutSkipItemsHandler.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutSkipItemsHandler.cs index ad44ea69b..623779c5c 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutSkipItemsHandler.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Handlers/YamlPlayoutSkipItemsHandler.cs @@ -27,13 +27,17 @@ public class YamlPlayoutSkipItemsHandler(EnumeratorCache enumeratorCache) : IYam foreach (IMediaCollectionEnumerator enumerator in maybeEnumerator) { + var random = new Random(context.Playout.Seed + context.InstructionIndex); + int enumeratorCount = enumerator is PlaylistEnumerator playlistEnumerator + ? playlistEnumerator.CountForRandom + : enumerator.Count; var expression = new NCalc.Expression(skipItems.SkipItems); expression.EvaluateParameter += (name, e) => { e.Result = name switch { - "count" => enumerator.Count, - "random" => new Random().Next() % enumerator.Count, + "count" => enumeratorCount, + "random" => random.Next() % enumeratorCount, _ => e.Result }; }; diff --git a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutCountInstruction.cs b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutCountInstruction.cs index 1aeb40460..23ed6f49e 100644 --- a/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutCountInstruction.cs +++ b/ErsatzTV.Core/Scheduling/YamlScheduling/Models/YamlPlayoutCountInstruction.cs @@ -2,5 +2,5 @@ namespace ErsatzTV.Core.Scheduling.YamlScheduling.Models; public class YamlPlayoutCountInstruction : YamlPlayoutInstruction { - public int Count { get; set; } + public string Count { get; set; } }