support filling with groups of song artists (#1537)

This commit is contained in:
Jason Dove
2024-01-05 10:32:04 -06:00
committed by GitHub
parent c18be5559b
commit 6708d6b4d7
13 changed files with 9193 additions and 18 deletions
@@ -25,5 +25,6 @@ public class PlayoutProgramScheduleAnchor
public SmartCollection SmartCollection { get; set; } public SmartCollection SmartCollection { get; set; }
public int? MediaItemId { get; set; } public int? MediaItemId { get; set; }
public MediaItem MediaItem { get; set; } public MediaItem MediaItem { get; set; }
public string FakeCollectionKey { get; set; }
public CollectionEnumeratorState EnumeratorState { get; set; } public CollectionEnumeratorState EnumeratorState { get; set; }
} }
@@ -25,6 +25,7 @@ public abstract class ProgramScheduleItem
public MultiCollection MultiCollection { get; set; } public MultiCollection MultiCollection { get; set; }
public int? SmartCollectionId { get; set; } public int? SmartCollectionId { get; set; }
public SmartCollection SmartCollection { get; set; } public SmartCollection SmartCollection { get; set; }
public string FakeCollectionKey { get; set; }
public PlaybackOrder PlaybackOrder { get; set; } public PlaybackOrder PlaybackOrder { get; set; }
public int? PreRollFillerId { get; set; } public int? PreRollFillerId { get; set; }
public FillerPreset PreRollFiller { get; set; } public FillerPreset PreRollFiller { get; set; }
@@ -7,5 +7,7 @@ public enum ProgramScheduleItemCollectionType
TelevisionSeason = 2, TelevisionSeason = 2,
Artist = 3, Artist = 3,
MultiCollection = 4, MultiCollection = 4,
SmartCollection = 5 SmartCollection = 5,
FakeCollection = 100
} }
@@ -10,6 +10,7 @@ public class CollectionKey : Record<CollectionKey>
public int? MultiCollectionId { get; set; } public int? MultiCollectionId { get; set; }
public int? SmartCollectionId { get; set; } public int? SmartCollectionId { get; set; }
public int? MediaItemId { get; set; } public int? MediaItemId { get; set; }
public string FakeCollectionKey { get; set; }
public static CollectionKey ForScheduleItem(ProgramScheduleItem item) => public static CollectionKey ForScheduleItem(ProgramScheduleItem item) =>
item.CollectionType switch item.CollectionType switch
@@ -44,6 +45,11 @@ public class CollectionKey : Record<CollectionKey>
CollectionType = item.CollectionType, CollectionType = item.CollectionType,
SmartCollectionId = item.SmartCollectionId SmartCollectionId = item.SmartCollectionId
}, },
ProgramScheduleItemCollectionType.FakeCollection => new CollectionKey
{
CollectionType = item.CollectionType,
FakeCollectionKey = item.FakeCollectionKey
},
_ => throw new ArgumentOutOfRangeException(nameof(item)) _ => throw new ArgumentOutOfRangeException(nameof(item))
}; };
@@ -5,6 +5,7 @@ namespace ErsatzTV.Core.Scheduling;
public record CollectionWithItems( public record CollectionWithItems(
int ShowId, int ShowId,
int ArtistId, int ArtistId,
string Key,
List<MediaItem> MediaItems, List<MediaItem> MediaItems,
bool ScheduleAsGroup, bool ScheduleAsGroup,
PlaybackOrder PlaybackOrder, PlaybackOrder PlaybackOrder,
+28 -14
View File
@@ -438,10 +438,9 @@ public class PlayoutBuilder : IPlayoutBuilder
_artistRepository, _artistRepository,
collectionKey); collectionKey);
var fakeCollections = _mediaCollectionRepository.GroupIntoFakeCollections(mediaItems) var fakeCollections = _mediaCollectionRepository.GroupIntoFakeCollections(mediaItems)
.Filter(c => c.ShowId > 0 || c.ArtistId > 0) .Filter(c => c.ShowId > 0 || c.ArtistId > 0 || !string.IsNullOrWhiteSpace(c.Key))
.ToList(); .ToList();
List<ProgramScheduleItem> fakeScheduleItems = [] List<ProgramScheduleItem> fakeScheduleItems = [];
;
// this will be used to clone a schedule item // this will be used to clone a schedule item
MethodInfo generic = typeof(JsonConvert).GetMethods() MethodInfo generic = typeof(JsonConvert).GetMethods()
@@ -451,18 +450,36 @@ public class PlayoutBuilder : IPlayoutBuilder
foreach (CollectionWithItems fakeCollection in fakeCollections) foreach (CollectionWithItems fakeCollection in fakeCollections)
{ {
var key = new CollectionKey CollectionKey key = (fakeCollection.ShowId, fakeCollection.ArtistId, fakeCollection.Key) switch
{ {
CollectionType = fakeCollection.ShowId > 0 var (showId, _, _) when showId > 0 => new CollectionKey
? ProgramScheduleItemCollectionType.TelevisionShow {
: ProgramScheduleItemCollectionType.Artist, CollectionType = ProgramScheduleItemCollectionType.TelevisionShow,
MediaItemId = fakeCollection.ShowId > 0 ? fakeCollection.ShowId : fakeCollection.ArtistId MediaItemId = showId
},
var (_, artistId, _) when artistId > 0 => new CollectionKey
{
CollectionType = ProgramScheduleItemCollectionType.Artist,
MediaItemId = artistId
},
var (_, _, k) when k is not null => new CollectionKey
{
CollectionType = ProgramScheduleItemCollectionType.FakeCollection,
FakeCollectionKey = k
},
var (_, _, _) => null
}; };
if (key is null)
{
continue;
}
string serialized = JsonConvert.SerializeObject(scheduleItem); string serialized = JsonConvert.SerializeObject(scheduleItem);
var copyScheduleItem = generic.Invoke(this, [serialized]) as ProgramScheduleItem; var copyScheduleItem = generic.Invoke(this, [serialized]) as ProgramScheduleItem;
copyScheduleItem.CollectionType = key.CollectionType; copyScheduleItem.CollectionType = key.CollectionType;
copyScheduleItem.MediaItemId = key.MediaItemId; copyScheduleItem.MediaItemId = key.MediaItemId;
copyScheduleItem.FakeCollectionKey = key.FakeCollectionKey;
fakeScheduleItems.Add(copyScheduleItem); fakeScheduleItems.Add(copyScheduleItem);
IMediaCollectionEnumerator enumerator = await GetMediaCollectionEnumerator( IMediaCollectionEnumerator enumerator = await GetMediaCollectionEnumerator(
@@ -669,11 +686,7 @@ public class PlayoutBuilder : IPlayoutBuilder
} }
// build program schedule anchors // build program schedule anchors
playout.ProgramScheduleAnchors = BuildProgramScheduleAnchors( playout.ProgramScheduleAnchors = BuildProgramScheduleAnchors(playout, collectionEnumerators, saveAnchorDate);
playout,
activeSchedule,
collectionEnumerators,
saveAnchorDate);
// build fill group indices // build fill group indices
playout.FillGroupIndices = BuildFillGroupIndices(playout, scheduleItemsFillGroupEnumerators); playout.FillGroupIndices = BuildFillGroupIndices(playout, scheduleItemsFillGroupEnumerators);
@@ -817,7 +830,6 @@ public class PlayoutBuilder : IPlayoutBuilder
private static List<PlayoutProgramScheduleAnchor> BuildProgramScheduleAnchors( private static List<PlayoutProgramScheduleAnchor> BuildProgramScheduleAnchors(
Playout playout, Playout playout,
ProgramSchedule activeSchedule,
Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators, Dictionary<CollectionKey, IMediaCollectionEnumerator> collectionEnumerators,
bool saveAnchorDate) bool saveAnchorDate)
{ {
@@ -829,6 +841,7 @@ public class PlayoutBuilder : IPlayoutBuilder
a => a.CollectionType == collectionKey.CollectionType a => a.CollectionType == collectionKey.CollectionType
&& a.CollectionId == collectionKey.CollectionId && a.CollectionId == collectionKey.CollectionId
&& a.MediaItemId == collectionKey.MediaItemId && a.MediaItemId == collectionKey.MediaItemId
&& a.FakeCollectionKey == collectionKey.FakeCollectionKey
&& a.SmartCollectionId == collectionKey.SmartCollectionId && a.SmartCollectionId == collectionKey.SmartCollectionId
&& a.MultiCollectionId == collectionKey.MultiCollectionId && a.MultiCollectionId == collectionKey.MultiCollectionId
&& a.AnchorDate is null); && a.AnchorDate is null);
@@ -850,6 +863,7 @@ public class PlayoutBuilder : IPlayoutBuilder
MultiCollectionId = collectionKey.MultiCollectionId, MultiCollectionId = collectionKey.MultiCollectionId,
SmartCollectionId = collectionKey.SmartCollectionId, SmartCollectionId = collectionKey.SmartCollectionId,
MediaItemId = collectionKey.MediaItemId, MediaItemId = collectionKey.MediaItemId,
FakeCollectionKey = collectionKey.FakeCollectionKey,
EnumeratorState = maybeEnumeratorState[collectionKey] EnumeratorState = maybeEnumeratorState[collectionKey]
}); });
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,40 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ErsatzTV.Infrastructure.MySql.Migrations
{
/// <inheritdoc />
public partial class AddFakeCollectionGroup : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "FakeCollectionKey",
table: "ProgramScheduleItem",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.AddColumn<string>(
name: "FakeCollectionKey",
table: "PlayoutProgramScheduleAnchor",
type: "longtext",
nullable: true)
.Annotation("MySql:CharSet", "utf8mb4");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "FakeCollectionKey",
table: "ProgramScheduleItem");
migrationBuilder.DropColumn(
name: "FakeCollectionKey",
table: "PlayoutProgramScheduleAnchor");
}
}
}
@@ -16,7 +16,7 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder modelBuilder
.HasAnnotation("ProductVersion", "7.0.14") .HasAnnotation("ProductVersion", "8.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64); .HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b =>
@@ -1511,6 +1511,9 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
b.Property<int>("CollectionType") b.Property<int>("CollectionType")
.HasColumnType("int"); .HasColumnType("int");
b.Property<string>("FakeCollectionKey")
.HasColumnType("longtext");
b.Property<int?>("MediaItemId") b.Property<int?>("MediaItemId")
.HasColumnType("int"); .HasColumnType("int");
@@ -1700,6 +1703,9 @@ namespace ErsatzTV.Infrastructure.MySql.Migrations
b.Property<string>("CustomTitle") b.Property<string>("CustomTitle")
.HasColumnType("longtext"); .HasColumnType("longtext");
b.Property<string>("FakeCollectionKey")
.HasColumnType("longtext");
b.Property<int?>("FallbackFillerId") b.Property<int?>("FallbackFillerId")
.HasColumnType("int"); .HasColumnType("int");
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,38 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace ErsatzTV.Infrastructure.Sqlite.Migrations
{
/// <inheritdoc />
public partial class AddFakeCollectionGroup : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "FakeCollectionKey",
table: "ProgramScheduleItem",
type: "TEXT",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "FakeCollectionKey",
table: "PlayoutProgramScheduleAnchor",
type: "TEXT",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "FakeCollectionKey",
table: "ProgramScheduleItem");
migrationBuilder.DropColumn(
name: "FakeCollectionKey",
table: "PlayoutProgramScheduleAnchor");
}
}
}
@@ -15,7 +15,7 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
protected override void BuildModel(ModelBuilder modelBuilder) protected override void BuildModel(ModelBuilder modelBuilder)
{ {
#pragma warning disable 612, 618 #pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "7.0.14"); modelBuilder.HasAnnotation("ProductVersion", "8.0.0");
modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b =>
{ {
@@ -1509,6 +1509,9 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
b.Property<int>("CollectionType") b.Property<int>("CollectionType")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<string>("FakeCollectionKey")
.HasColumnType("TEXT");
b.Property<int?>("MediaItemId") b.Property<int?>("MediaItemId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@@ -1698,6 +1701,9 @@ namespace ErsatzTV.Infrastructure.Sqlite.Migrations
b.Property<string>("CustomTitle") b.Property<string>("CustomTitle")
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<string>("FakeCollectionKey")
.HasColumnType("TEXT");
b.Property<int?>("FallbackFillerId") b.Property<int?>("FallbackFillerId")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
@@ -190,6 +190,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
new CollectionWithItems( new CollectionWithItems(
multiCollectionItem.CollectionId, multiCollectionItem.CollectionId,
multiCollectionItem.CollectionId, multiCollectionItem.CollectionId,
null,
sortedItems, sortedItems,
multiCollectionItem.ScheduleAsGroup, multiCollectionItem.ScheduleAsGroup,
multiCollectionItem.PlaybackOrder, multiCollectionItem.PlaybackOrder,
@@ -202,6 +203,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
new CollectionWithItems( new CollectionWithItems(
multiCollectionItem.CollectionId, multiCollectionItem.CollectionId,
multiCollectionItem.CollectionId, multiCollectionItem.CollectionId,
null,
items, items,
multiCollectionItem.ScheduleAsGroup, multiCollectionItem.ScheduleAsGroup,
multiCollectionItem.PlaybackOrder, multiCollectionItem.PlaybackOrder,
@@ -217,6 +219,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
new CollectionWithItems( new CollectionWithItems(
multiCollectionSmartItem.SmartCollectionId, multiCollectionSmartItem.SmartCollectionId,
multiCollectionSmartItem.SmartCollectionId, multiCollectionSmartItem.SmartCollectionId,
null,
items, items,
multiCollectionSmartItem.ScheduleAsGroup, multiCollectionSmartItem.ScheduleAsGroup,
multiCollectionSmartItem.PlaybackOrder, multiCollectionSmartItem.PlaybackOrder,
@@ -357,6 +360,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
new CollectionWithItems( new CollectionWithItems(
showId, showId,
0, 0,
null,
list, list,
true, true,
PlaybackOrder.Chronological, PlaybackOrder.Chronological,
@@ -384,6 +388,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
new CollectionWithItems( new CollectionWithItems(
0, 0,
artistId, artistId,
null,
list, list,
true, true,
PlaybackOrder.Chronological, PlaybackOrder.Chronological,
@@ -418,12 +423,13 @@ public class MediaCollectionRepository : IMediaCollectionRepository
songArtistCollections[key] = list; songArtistCollections[key] = list;
} }
foreach ((int _, List<MediaItem> list) in songArtistCollections) foreach ((int index, List<MediaItem> list) in songArtistCollections)
{ {
result.Add( result.Add(
new CollectionWithItems( new CollectionWithItems(
id, id,
id, id,
allArtists[index],
list, list,
true, true,
PlaybackOrder.Chronological, PlaybackOrder.Chronological,
@@ -436,6 +442,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
new CollectionWithItems( new CollectionWithItems(
id, id,
id, id,
null,
items.OfType<Movie>().Cast<MediaItem>().ToList(), items.OfType<Movie>().Cast<MediaItem>().ToList(),
true, true,
PlaybackOrder.Chronological, PlaybackOrder.Chronological,
@@ -446,6 +453,7 @@ public class MediaCollectionRepository : IMediaCollectionRepository
new CollectionWithItems( new CollectionWithItems(
id, id,
id, id,
null,
items.OfType<OtherVideo>().Cast<MediaItem>().ToList(), items.OfType<OtherVideo>().Cast<MediaItem>().ToList(),
true, true,
PlaybackOrder.Chronological, PlaybackOrder.Chronological,