mirror of https://github.com/ErsatzTV/ErsatzTV.git
13 changed files with 1841 additions and 6 deletions
@ -0,0 +1,100 @@ |
|||||||
|
using System; |
||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using ErsatzTV.Core.Scheduling; |
||||||
|
using FluentAssertions; |
||||||
|
using NUnit.Framework; |
||||||
|
using static LanguageExt.Prelude; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Tests.Scheduling |
||||||
|
{ |
||||||
|
public class CustomOrderContentTests |
||||||
|
{ |
||||||
|
[Test] |
||||||
|
public void MediaItems_Should_Sort_By_CustomOrder() |
||||||
|
{ |
||||||
|
Collection collection = CreateCollection(10); |
||||||
|
List<MediaItem> contents = Episodes(10); |
||||||
|
var state = new CollectionEnumeratorState(); |
||||||
|
|
||||||
|
var customOrderContent = new CustomOrderCollectionEnumerator(collection, contents, state); |
||||||
|
|
||||||
|
for (var i = 10; i >= 1; i--) |
||||||
|
{ |
||||||
|
customOrderContent.Current.IsSome.Should().BeTrue(); |
||||||
|
customOrderContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); |
||||||
|
customOrderContent.MoveNext(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void State_Index_Should_Increment() |
||||||
|
{ |
||||||
|
Collection collection = CreateCollection(10); |
||||||
|
List<MediaItem> contents = Episodes(10); |
||||||
|
var state = new CollectionEnumeratorState(); |
||||||
|
|
||||||
|
var customOrderContent = new CustomOrderCollectionEnumerator(collection, contents, state); |
||||||
|
|
||||||
|
for (var i = 0; i < 10; i++) |
||||||
|
{ |
||||||
|
customOrderContent.State.Index.Should().Be(i % 10); |
||||||
|
customOrderContent.MoveNext(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
[Test] |
||||||
|
public void State_Should_Impact_Iterator_Start() |
||||||
|
{ |
||||||
|
Collection collection = CreateCollection(10); |
||||||
|
List<MediaItem> contents = Episodes(10); |
||||||
|
var state = new CollectionEnumeratorState { Index = 5 }; |
||||||
|
|
||||||
|
var customOrderContent = new CustomOrderCollectionEnumerator(collection, contents, state); |
||||||
|
|
||||||
|
for (var i = 5; i >= 1; i--) |
||||||
|
{ |
||||||
|
customOrderContent.Current.IsSome.Should().BeTrue(); |
||||||
|
customOrderContent.Current.Map(x => x.Id).IfNone(-1).Should().Be(i); |
||||||
|
customOrderContent.State.Index.Should().Be(5 - i + 5); // 5 through 10
|
||||||
|
customOrderContent.MoveNext(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private static Collection CreateCollection(int episodeCount) |
||||||
|
{ |
||||||
|
var collection = new Collection { CollectionItems = new List<CollectionItem>() }; |
||||||
|
|
||||||
|
for (var i = 1; i <= episodeCount; i++) |
||||||
|
{ |
||||||
|
collection.CollectionItems.Add( |
||||||
|
new CollectionItem |
||||||
|
{ |
||||||
|
MediaItemId = i, |
||||||
|
// reverse order
|
||||||
|
CustomIndex = episodeCount - i |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
return collection; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static List<MediaItem> Episodes(int count) => |
||||||
|
Range(1, count).Map( |
||||||
|
i => (MediaItem) new Episode |
||||||
|
{ |
||||||
|
Id = i, |
||||||
|
EpisodeMetadata = new List<EpisodeMetadata> |
||||||
|
{ |
||||||
|
new() |
||||||
|
{ |
||||||
|
ReleaseDate = new DateTime(2020, 1, i) |
||||||
|
} |
||||||
|
} |
||||||
|
}) |
||||||
|
.Reverse() |
||||||
|
.ToList(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,38 @@ |
|||||||
|
using System.Collections.Generic; |
||||||
|
using System.Linq; |
||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using ErsatzTV.Core.Interfaces.Scheduling; |
||||||
|
using LanguageExt; |
||||||
|
using static LanguageExt.Prelude; |
||||||
|
|
||||||
|
namespace ErsatzTV.Core.Scheduling |
||||||
|
{ |
||||||
|
public class CustomOrderCollectionEnumerator : IMediaCollectionEnumerator |
||||||
|
{ |
||||||
|
private readonly IList<MediaItem> _sortedMediaItems; |
||||||
|
|
||||||
|
public CustomOrderCollectionEnumerator( |
||||||
|
Collection collection, |
||||||
|
List<MediaItem> mediaItems, |
||||||
|
CollectionEnumeratorState state) |
||||||
|
{ |
||||||
|
// TODO: this will break if we allow shows and seasons
|
||||||
|
_sortedMediaItems = collection.CollectionItems |
||||||
|
.OrderBy(ci => ci.CustomIndex) |
||||||
|
.Map(ci => mediaItems.First(mi => mi.Id == ci.MediaItemId)) |
||||||
|
.ToList(); |
||||||
|
|
||||||
|
State = new CollectionEnumeratorState { Seed = state.Seed }; |
||||||
|
while (State.Index < state.Index) |
||||||
|
{ |
||||||
|
MoveNext(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public CollectionEnumeratorState State { get; } |
||||||
|
|
||||||
|
public Option<MediaItem> Current => _sortedMediaItems.Any() ? _sortedMediaItems[State.Index] : None; |
||||||
|
|
||||||
|
public void MoveNext() => State.Index = (State.Index + 1) % _sortedMediaItems.Count; |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,11 @@ |
|||||||
|
using ErsatzTV.Core.Domain; |
||||||
|
using Microsoft.EntityFrameworkCore; |
||||||
|
using Microsoft.EntityFrameworkCore.Metadata.Builders; |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Data.Configurations |
||||||
|
{ |
||||||
|
public class CollectionItemConfiguration : IEntityTypeConfiguration<CollectionItem> |
||||||
|
{ |
||||||
|
public void Configure(EntityTypeBuilder<CollectionItem> builder) => builder.ToTable("CollectionItem"); |
||||||
|
} |
||||||
|
} |
||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,19 @@ |
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations; |
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Migrations |
||||||
|
{ |
||||||
|
public partial class Add_CollectionItem_CustomIndex : Migration |
||||||
|
{ |
||||||
|
protected override void Up(MigrationBuilder migrationBuilder) => |
||||||
|
migrationBuilder.AddColumn<int>( |
||||||
|
"CustomIndex", |
||||||
|
"CollectionItem", |
||||||
|
"INTEGER", |
||||||
|
nullable: true); |
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder) => |
||||||
|
migrationBuilder.DropColumn( |
||||||
|
"CustomIndex", |
||||||
|
"CollectionItem"); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue