diff --git a/CHANGELOG.md b/CHANGELOG.md index 338e6126..fd04b38e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,6 +66,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Add `Expression` for mid-roll filler to allow custom logic for using or skipping chapter markers - The following parameters can be used: - `total_points`: total number of potential mid-roll points + - `matched_points`: number of mid-roll points that have already matched the expression - `total_duration`: total duration of the content, in seconds - `total_progress`: normalized position from 0 to 1 - `last_mid_filler`: seconds since last mid-roll filler diff --git a/ErsatzTV.Core.Tests/Scheduling/FillerExpressionTests.cs b/ErsatzTV.Core.Tests/Scheduling/FillerExpressionTests.cs new file mode 100644 index 00000000..f432e570 --- /dev/null +++ b/ErsatzTV.Core.Tests/Scheduling/FillerExpressionTests.cs @@ -0,0 +1,44 @@ +using ErsatzTV.Core.Domain; +using ErsatzTV.Core.Domain.Filler; +using ErsatzTV.Core.Scheduling; +using NUnit.Framework; +using Shouldly; + +namespace ErsatzTV.Core.Tests.Scheduling; + +[TestFixture] +public class FillerExpressionTests +{ + [Test] + public void Two_Points_In_30_Minute_Content() + { + // 30 min content + var playoutItem = new PlayoutItem { Start = DateTimeOffset.Now.UtcDateTime }; + playoutItem.Finish = playoutItem.Start + TimeSpan.FromMinutes(30); + + // chapters every 5 min + var chapters = new List + { + new() { ChapterId = 1, StartTime = TimeSpan.Zero, EndTime = TimeSpan.FromMinutes(5) }, + new() { ChapterId = 2, StartTime = TimeSpan.FromMinutes(5), EndTime = TimeSpan.FromMinutes(10) }, + new() { ChapterId = 3, StartTime = TimeSpan.FromMinutes(10), EndTime = TimeSpan.FromMinutes(15) }, + new() { ChapterId = 4, StartTime = TimeSpan.FromMinutes(15), EndTime = TimeSpan.FromMinutes(20) }, + new() { ChapterId = 5, StartTime = TimeSpan.FromMinutes(20), EndTime = TimeSpan.FromMinutes(25) }, + new() { ChapterId = 6, StartTime = TimeSpan.FromMinutes(25), EndTime = TimeSpan.FromMinutes(30) } + }; + + // skip first 5 min of content, wait at least 5 min between points, only match up to 2 points + var fillerPreset = new FillerPreset + { + FillerKind = FillerKind.MidRoll, + Expression = "(point > 5 * 60) and (last_mid_filler > 5 * 60) and (matched_points < 2)" + }; + + List result = FillerExpression.FilterChapters(fillerPreset, chapters, playoutItem); + + result.Count.ShouldBe(3); + result[0].EndTime.ShouldBe(TimeSpan.FromMinutes(10)); + result[1].EndTime.ShouldBe(TimeSpan.FromMinutes(20)); + result[2].EndTime.ShouldBe(TimeSpan.FromMinutes(30)); + } +} diff --git a/ErsatzTV.Core/Scheduling/FillerExpression.cs b/ErsatzTV.Core/Scheduling/FillerExpression.cs index ba420218..f39a1b61 100644 --- a/ErsatzTV.Core/Scheduling/FillerExpression.cs +++ b/ErsatzTV.Core/Scheduling/FillerExpression.cs @@ -22,6 +22,7 @@ public static class FillerExpression double lastFiller = start.TotalSeconds - 99999.0; double contentDuration = (playoutItem.FinishOffset - playoutItem.StartOffset).TotalSeconds; + var matches = 0; for (var index = 0; index < chapterPoints.Count; index++) { @@ -29,6 +30,7 @@ public static class FillerExpression var expression = new Expression(fillerPreset.Expression); int chapterNum = index + 1; double sinceLastFiller = chapterPoint.TotalSeconds - lastFiller; + int matchedPoints = matches; expression.EvaluateParameter += (name, e) => { e.Result = name switch @@ -38,6 +40,7 @@ public static class FillerExpression "total_duration" => contentDuration, "total_progress" => chapterPoint.TotalSeconds / end.TotalSeconds, "remaining_duration" => contentDuration - chapterPoint.TotalSeconds, + "matched_points" => matchedPoints, "point" => chapterPoint.TotalSeconds, "num" => chapterNum, _ => e.Result @@ -46,6 +49,7 @@ public static class FillerExpression if (expression.Evaluate() as bool? == true) { + matches += 1; lastFiller = chapterPoint.TotalSeconds; newChapters.Add(effectiveChapters[index]); } diff --git a/ErsatzTV/Pages/FillerPresetEditor.razor b/ErsatzTV/Pages/FillerPresetEditor.razor index 5144b981..2bf5442f 100644 --- a/ErsatzTV/Pages/FillerPresetEditor.razor +++ b/ErsatzTV/Pages/FillerPresetEditor.razor @@ -192,6 +192,8 @@ total_points: total number of potential mid-roll points
+ matched_points: number of mid-roll points that have already matched the expression +
total_duration: total duration of the content, in seconds
total_progress: normalized position from 0 to 1