fix building playouts when fill with group mode is used with graphics elements (#2799)
This commit is contained in:
@@ -41,6 +41,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Respect `z_index` (draw order) on all graphics element types
|
||||
- Fix bug with `z_index` sorting
|
||||
- Restore default UI font that was erroneously removed in v26.1.1
|
||||
- Classic schedules: fix building playouts when `Fill With Group Mode` schedule items also have graphics elements
|
||||
- Use configured searching log level on startup, instead of the default log level of `Information`
|
||||
- MySql: fix searching for shows and seasons in schedule items editor
|
||||
- Fix 500 errors when serving XMLTV due to concurrent file reads and writes
|
||||
|
||||
@@ -76,6 +76,8 @@ public class FakeMediaCollectionRepository : IMediaCollectionRepository
|
||||
public Task<bool> IsCustomPlaybackOrder(int collectionId) => false.AsTask();
|
||||
public Task<Option<string>> GetNameFromKey(CollectionKey emptyCollection, CancellationToken cancellationToken) => Option<string>.None.AsTask();
|
||||
|
||||
public List<CollectionWithItems> GroupIntoFakeCollections(List<MediaItem> items, string fakeKey = null) =>
|
||||
throw new NotSupportedException();
|
||||
public List<CollectionWithItems> GroupIntoFakeCollections(List<MediaItem> items, string fakeKey = null)
|
||||
{
|
||||
return [new CollectionWithItems(1, 0, fakeKey, items, true, PlaybackOrder.Shuffle, false)];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,103 @@ namespace ErsatzTV.Core.Tests.Scheduling.ClassicScheduling;
|
||||
[TestFixture]
|
||||
public class NewPlayoutTests : PlayoutBuilderTestBase
|
||||
{
|
||||
[Test]
|
||||
public async Task FillWithGroupMode_Should_Not_Fail()
|
||||
{
|
||||
var collection = new Collection
|
||||
{
|
||||
Id = 1,
|
||||
Name = "Multiple Items",
|
||||
MediaItems =
|
||||
[
|
||||
TestMovie(1, TimeSpan.FromHours(1), new DateTime(2020, 1, 1)),
|
||||
TestMovie(2, TimeSpan.FromHours(1), new DateTime(2020, 2, 1))
|
||||
]
|
||||
};
|
||||
|
||||
var fakeRepository = new FakeMediaCollectionRepository(
|
||||
Map((collection.Id, collection.MediaItems.ToList())));
|
||||
|
||||
var items = new List<ProgramScheduleItem>
|
||||
{
|
||||
new ProgramScheduleItemMultiple
|
||||
{
|
||||
Id = 1,
|
||||
Index = 1,
|
||||
//Collection = collection,
|
||||
CollectionId = collection.Id,
|
||||
StartTime = null,
|
||||
PlaybackOrder = PlaybackOrder.Chronological,
|
||||
MultipleMode = MultipleMode.Count,
|
||||
Count = "2",
|
||||
FillWithGroupMode = FillWithGroupMode.FillWithShuffledGroups,
|
||||
ProgramScheduleItemGraphicsElements = []
|
||||
}
|
||||
};
|
||||
|
||||
// having a graphics element reference the schedule item triggers the bug
|
||||
items[0].ProgramScheduleItemGraphicsElements.Add(new ProgramScheduleItemGraphicsElement
|
||||
{
|
||||
GraphicsElementId = 1,
|
||||
ProgramScheduleItem = items[0],
|
||||
ProgramScheduleItemId = items[0].Id
|
||||
});
|
||||
|
||||
var playout = new Playout
|
||||
{
|
||||
ProgramSchedule = new ProgramSchedule
|
||||
{
|
||||
Items = items
|
||||
},
|
||||
Channel = new Channel(Guid.Empty) { Id = 1, Name = "Test Channel" },
|
||||
ProgramScheduleAnchors = [],
|
||||
Items = [],
|
||||
ProgramScheduleAlternates = [],
|
||||
FillGroupIndices = []
|
||||
};
|
||||
|
||||
var referenceData =
|
||||
new PlayoutReferenceData(
|
||||
playout.Channel,
|
||||
Option<Deco>.None,
|
||||
[],
|
||||
[],
|
||||
playout.ProgramSchedule,
|
||||
[],
|
||||
[],
|
||||
TimeSpan.Zero);
|
||||
|
||||
IConfigElementRepository configRepo = Substitute.For<IConfigElementRepository>();
|
||||
var televisionRepo = new FakeTelevisionRepository();
|
||||
IArtistRepository artistRepo = Substitute.For<IArtistRepository>();
|
||||
IMultiEpisodeShuffleCollectionEnumeratorFactory factory =
|
||||
Substitute.For<IMultiEpisodeShuffleCollectionEnumeratorFactory>();
|
||||
IRerunHelper rerunHelper = Substitute.For<IRerunHelper>();
|
||||
var builder = new PlayoutBuilder(
|
||||
configRepo,
|
||||
fakeRepository,
|
||||
televisionRepo,
|
||||
artistRepo,
|
||||
factory,
|
||||
new MockFileSystem(),
|
||||
rerunHelper,
|
||||
Logger);
|
||||
|
||||
DateTimeOffset start = HoursAfterMidnight(0);
|
||||
DateTimeOffset finish = start + TimeSpan.FromHours(6);
|
||||
|
||||
Either<BaseError, PlayoutBuildResult> buildResult = await builder.Build(
|
||||
playout,
|
||||
referenceData,
|
||||
PlayoutBuildResult.Empty,
|
||||
PlayoutBuildMode.Reset,
|
||||
start,
|
||||
finish,
|
||||
CancellationToken);
|
||||
|
||||
buildResult.IsRight.ShouldBeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task OnlyZeroDurationItem_Should_Abort()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
using ErsatzTV.Core.Domain;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace ErsatzTV.Core.Extensions;
|
||||
|
||||
public static class ProgramScheduleItemExtensions
|
||||
{
|
||||
public static ProgramScheduleItem DeepCopy(this ProgramScheduleItem item)
|
||||
{
|
||||
if (item == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var settings = new JsonSerializerSettings
|
||||
{
|
||||
// program schedule item => graphics element => (same) program schedule item should be ignored
|
||||
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
string json = JsonConvert.SerializeObject(item, settings);
|
||||
return (ProgramScheduleItem)JsonConvert.DeserializeObject(json, item.GetType(), settings);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO.Abstractions;
|
||||
using System.Reflection;
|
||||
using ErsatzTV.Core.Domain;
|
||||
using ErsatzTV.Core.Domain.Filler;
|
||||
using ErsatzTV.Core.Errors;
|
||||
@@ -673,13 +672,6 @@ public class PlayoutBuilder : IPlayoutBuilder
|
||||
.Filter(c => c.ShowId > 0 || c.ArtistId > 0 || !string.IsNullOrWhiteSpace(c.Key))
|
||||
.ToList();
|
||||
List<ProgramScheduleItem> fakeScheduleItems = [];
|
||||
|
||||
// this will be used to clone a schedule item
|
||||
MethodInfo generic = typeof(JsonConvert).GetMethods()
|
||||
.FirstOrDefault(x => x.Name.Equals("DeserializeObject", StringComparison.OrdinalIgnoreCase) &&
|
||||
x.IsGenericMethod &&
|
||||
x.GetParameters().Length == 1)?.MakeGenericMethod(scheduleItem.GetType());
|
||||
|
||||
foreach (CollectionWithItems fakeCollection in fakeCollections)
|
||||
{
|
||||
CollectionKey key = (fakeCollection.ShowId, fakeCollection.ArtistId, fakeCollection.Key) switch
|
||||
@@ -709,8 +701,7 @@ public class PlayoutBuilder : IPlayoutBuilder
|
||||
continue;
|
||||
}
|
||||
|
||||
string serialized = JsonConvert.SerializeObject(scheduleItem);
|
||||
var copyScheduleItem = generic.Invoke(this, [serialized]) as ProgramScheduleItem;
|
||||
var copyScheduleItem = scheduleItem.DeepCopy();
|
||||
copyScheduleItem.CollectionType = key.CollectionType;
|
||||
copyScheduleItem.MediaItemId = key.MediaItemId;
|
||||
copyScheduleItem.FakeCollectionKey = key.FakeCollectionKey;
|
||||
|
||||
Reference in New Issue
Block a user