properly flood with fixed start time (#294)
This commit is contained in:
@@ -458,6 +458,182 @@ namespace ErsatzTV.Core.Tests.Scheduling
|
|||||||
result.Items[5].MediaItemId.Should().Be(2);
|
result.Items[5].MediaItemId.Should().Be(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task FloodContent_Should_FloodWithFixedStartTime()
|
||||||
|
{
|
||||||
|
var floodCollection = new Collection
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Name = "Flood Items",
|
||||||
|
MediaItems = new List<MediaItem>
|
||||||
|
{
|
||||||
|
TestMovie(1, TimeSpan.FromHours(1), new DateTime(2020, 1, 1)),
|
||||||
|
TestMovie(2, TimeSpan.FromHours(1), new DateTime(2020, 2, 1))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var fixedCollection = new Collection
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Name = "Fixed Items",
|
||||||
|
MediaItems = new List<MediaItem>
|
||||||
|
{
|
||||||
|
TestMovie(3, TimeSpan.FromHours(2), new DateTime(2020, 1, 1)),
|
||||||
|
TestMovie(4, TimeSpan.FromHours(1), new DateTime(2020, 1, 2))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var fakeRepository = new FakeMediaCollectionRepository(
|
||||||
|
Map(
|
||||||
|
(floodCollection.Id, floodCollection.MediaItems.ToList()),
|
||||||
|
(fixedCollection.Id, fixedCollection.MediaItems.ToList())));
|
||||||
|
|
||||||
|
var items = new List<ProgramScheduleItem>
|
||||||
|
{
|
||||||
|
new ProgramScheduleItemFlood
|
||||||
|
{
|
||||||
|
Index = 1,
|
||||||
|
Collection = floodCollection,
|
||||||
|
CollectionId = floodCollection.Id,
|
||||||
|
StartTime = TimeSpan.FromHours(7)
|
||||||
|
},
|
||||||
|
new ProgramScheduleItemOne
|
||||||
|
{
|
||||||
|
Index = 2,
|
||||||
|
Collection = fixedCollection,
|
||||||
|
CollectionId = fixedCollection.Id,
|
||||||
|
StartTime = TimeSpan.FromHours(12)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var playout = new Playout
|
||||||
|
{
|
||||||
|
ProgramSchedule = new ProgramSchedule
|
||||||
|
{
|
||||||
|
Items = items,
|
||||||
|
MediaCollectionPlaybackOrder = PlaybackOrder.Chronological
|
||||||
|
},
|
||||||
|
Channel = new Channel(Guid.Empty) { Id = 1, Name = "Test Channel" }
|
||||||
|
};
|
||||||
|
|
||||||
|
var televisionRepo = new FakeTelevisionRepository();
|
||||||
|
var artistRepo = new Mock<IArtistRepository>();
|
||||||
|
var builder = new PlayoutBuilder(fakeRepository, televisionRepo, artistRepo.Object, _logger);
|
||||||
|
|
||||||
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
|
DateTimeOffset finish = start + TimeSpan.FromHours(24);
|
||||||
|
|
||||||
|
Playout result = await builder.BuildPlayoutItems(playout, start, finish);
|
||||||
|
|
||||||
|
result.Items.Count.Should().Be(6);
|
||||||
|
|
||||||
|
result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(7));
|
||||||
|
result.Items[0].MediaItemId.Should().Be(1);
|
||||||
|
result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(8));
|
||||||
|
result.Items[1].MediaItemId.Should().Be(2);
|
||||||
|
result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(9));
|
||||||
|
result.Items[2].MediaItemId.Should().Be(1);
|
||||||
|
result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(10));
|
||||||
|
result.Items[3].MediaItemId.Should().Be(2);
|
||||||
|
result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(11));
|
||||||
|
result.Items[4].MediaItemId.Should().Be(1);
|
||||||
|
|
||||||
|
result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12));
|
||||||
|
result.Items[5].MediaItemId.Should().Be(3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task FloodContent_Should_FloodWithFixedStartTime_FromAnchor()
|
||||||
|
{
|
||||||
|
var floodCollection = new Collection
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Name = "Flood Items",
|
||||||
|
MediaItems = new List<MediaItem>
|
||||||
|
{
|
||||||
|
TestMovie(1, TimeSpan.FromHours(1), new DateTime(2020, 1, 1)),
|
||||||
|
TestMovie(2, TimeSpan.FromHours(1), new DateTime(2020, 2, 1))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var fixedCollection = new Collection
|
||||||
|
{
|
||||||
|
Id = 2,
|
||||||
|
Name = "Fixed Items",
|
||||||
|
MediaItems = new List<MediaItem>
|
||||||
|
{
|
||||||
|
TestMovie(3, TimeSpan.FromHours(2), new DateTime(2020, 1, 1)),
|
||||||
|
TestMovie(4, TimeSpan.FromHours(1), new DateTime(2020, 1, 2))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var fakeRepository = new FakeMediaCollectionRepository(
|
||||||
|
Map(
|
||||||
|
(floodCollection.Id, floodCollection.MediaItems.ToList()),
|
||||||
|
(fixedCollection.Id, fixedCollection.MediaItems.ToList())));
|
||||||
|
|
||||||
|
var items = new List<ProgramScheduleItem>
|
||||||
|
{
|
||||||
|
new ProgramScheduleItemFlood
|
||||||
|
{
|
||||||
|
Index = 1,
|
||||||
|
Collection = floodCollection,
|
||||||
|
CollectionId = floodCollection.Id,
|
||||||
|
StartTime = TimeSpan.FromHours(7)
|
||||||
|
},
|
||||||
|
new ProgramScheduleItemOne
|
||||||
|
{
|
||||||
|
Index = 2,
|
||||||
|
Collection = fixedCollection,
|
||||||
|
CollectionId = fixedCollection.Id,
|
||||||
|
StartTime = TimeSpan.FromHours(12)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var playout = new Playout
|
||||||
|
{
|
||||||
|
ProgramSchedule = new ProgramSchedule
|
||||||
|
{
|
||||||
|
Items = items,
|
||||||
|
MediaCollectionPlaybackOrder = PlaybackOrder.Chronological
|
||||||
|
},
|
||||||
|
Channel = new Channel(Guid.Empty) { Id = 1, Name = "Test Channel" },
|
||||||
|
Anchor = new PlayoutAnchor
|
||||||
|
{
|
||||||
|
NextStart = HoursAfterMidnight(9).UtcDateTime,
|
||||||
|
NextScheduleItem = items[0],
|
||||||
|
NextScheduleItemId = 1,
|
||||||
|
InFlood = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var televisionRepo = new FakeTelevisionRepository();
|
||||||
|
var artistRepo = new Mock<IArtistRepository>();
|
||||||
|
var builder = new PlayoutBuilder(fakeRepository, televisionRepo, artistRepo.Object, _logger);
|
||||||
|
|
||||||
|
DateTimeOffset start = HoursAfterMidnight(0);
|
||||||
|
DateTimeOffset finish = start + TimeSpan.FromHours(32);
|
||||||
|
|
||||||
|
Playout result = await builder.BuildPlayoutItems(playout, start, finish);
|
||||||
|
|
||||||
|
result.Items.Count.Should().Be(5);
|
||||||
|
|
||||||
|
result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(9));
|
||||||
|
result.Items[0].MediaItemId.Should().Be(1);
|
||||||
|
result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(10));
|
||||||
|
result.Items[1].MediaItemId.Should().Be(2);
|
||||||
|
result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(11));
|
||||||
|
result.Items[2].MediaItemId.Should().Be(1);
|
||||||
|
|
||||||
|
result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(12));
|
||||||
|
result.Items[3].MediaItemId.Should().Be(3);
|
||||||
|
|
||||||
|
result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(7));
|
||||||
|
result.Items[4].MediaItemId.Should().Be(2);
|
||||||
|
|
||||||
|
result.Anchor.InFlood.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public async Task FloodContent_Should_FloodAroundFixedContent_DurationWithoutOfflineTail()
|
public async Task FloodContent_Should_FloodAroundFixedContent_DurationWithoutOfflineTail()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ namespace ErsatzTV.Core.Domain
|
|||||||
public DateTime NextStart { get; set; }
|
public DateTime NextStart { get; set; }
|
||||||
public int? MultipleRemaining { get; set; }
|
public int? MultipleRemaining { get; set; }
|
||||||
public DateTime? DurationFinish { get; set; }
|
public DateTime? DurationFinish { get; set; }
|
||||||
|
public bool InFlood { get; set; }
|
||||||
|
|
||||||
public DateTimeOffset NextStartOffset => new DateTimeOffset(NextStart, TimeSpan.Zero).ToLocalTime();
|
public DateTimeOffset NextStartOffset => new DateTimeOffset(NextStart, TimeSpan.Zero).ToLocalTime();
|
||||||
|
|
||||||
|
|||||||
@@ -201,6 +201,7 @@ namespace ErsatzTV.Core.Scheduling
|
|||||||
// start with the previous multiple/duration states
|
// start with the previous multiple/duration states
|
||||||
Option<int> multipleRemaining = Optional(startAnchor.MultipleRemaining);
|
Option<int> multipleRemaining = Optional(startAnchor.MultipleRemaining);
|
||||||
Option<DateTimeOffset> durationFinish = startAnchor.DurationFinishOffset;
|
Option<DateTimeOffset> durationFinish = startAnchor.DurationFinishOffset;
|
||||||
|
bool inFlood = startAnchor.InFlood;
|
||||||
|
|
||||||
bool customGroup = multipleRemaining.IsSome || durationFinish.IsSome;
|
bool customGroup = multipleRemaining.IsSome || durationFinish.IsSome;
|
||||||
|
|
||||||
@@ -215,7 +216,8 @@ namespace ErsatzTV.Core.Scheduling
|
|||||||
scheduleItem,
|
scheduleItem,
|
||||||
currentTime,
|
currentTime,
|
||||||
multipleRemaining.IsSome,
|
multipleRemaining.IsSome,
|
||||||
durationFinish.IsSome);
|
durationFinish.IsSome,
|
||||||
|
inFlood);
|
||||||
|
|
||||||
IMediaCollectionEnumerator enumerator = collectionEnumerators[CollectionKeyForItem(scheduleItem)];
|
IMediaCollectionEnumerator enumerator = collectionEnumerators[CollectionKeyForItem(scheduleItem)];
|
||||||
await enumerator.Current.IfSomeAsync(
|
await enumerator.Current.IfSomeAsync(
|
||||||
@@ -318,6 +320,11 @@ namespace ErsatzTV.Core.Scheduling
|
|||||||
"Flood");
|
"Flood");
|
||||||
index++;
|
index++;
|
||||||
customGroup = false;
|
customGroup = false;
|
||||||
|
inFlood = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inFlood = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
@@ -374,7 +381,8 @@ namespace ErsatzTV.Core.Scheduling
|
|||||||
NextScheduleItemId = nextScheduleItem.Id,
|
NextScheduleItemId = nextScheduleItem.Id,
|
||||||
NextStart = GetStartTimeAfter(nextScheduleItem, currentTime).UtcDateTime,
|
NextStart = GetStartTimeAfter(nextScheduleItem, currentTime).UtcDateTime,
|
||||||
MultipleRemaining = multipleRemaining.IsSome ? multipleRemaining.ValueUnsafe() : null,
|
MultipleRemaining = multipleRemaining.IsSome ? multipleRemaining.ValueUnsafe() : null,
|
||||||
DurationFinish = durationFinish.IsSome ? durationFinish.ValueUnsafe().UtcDateTime : null
|
DurationFinish = durationFinish.IsSome ? durationFinish.ValueUnsafe().UtcDateTime : null,
|
||||||
|
InFlood = inFlood
|
||||||
};
|
};
|
||||||
|
|
||||||
// build program schedule anchors
|
// build program schedule anchors
|
||||||
@@ -419,13 +427,15 @@ namespace ErsatzTV.Core.Scheduling
|
|||||||
ProgramScheduleItem item,
|
ProgramScheduleItem item,
|
||||||
DateTimeOffset start,
|
DateTimeOffset start,
|
||||||
bool inMultiple = false,
|
bool inMultiple = false,
|
||||||
bool inDuration = false)
|
bool inDuration = false,
|
||||||
|
bool inFlood = false)
|
||||||
{
|
{
|
||||||
switch (item.StartType)
|
switch (item.StartType)
|
||||||
{
|
{
|
||||||
case StartType.Fixed:
|
case StartType.Fixed:
|
||||||
if (item is ProgramScheduleItemMultiple && inMultiple ||
|
if (item is ProgramScheduleItemMultiple && inMultiple ||
|
||||||
item is ProgramScheduleItemDuration && inDuration)
|
item is ProgramScheduleItemDuration && inDuration ||
|
||||||
|
item is ProgramScheduleItemFlood && inFlood)
|
||||||
{
|
{
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|||||||
+2979
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace ErsatzTV.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
public partial class Add_PlayoutAnchorInFlood : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<bool>(
|
||||||
|
name: "Anchor_InFlood",
|
||||||
|
table: "Playout",
|
||||||
|
type: "INTEGER",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Anchor_InFlood",
|
||||||
|
table: "Playout");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ namespace ErsatzTV.Infrastructure.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "5.0.6");
|
.HasAnnotation("ProductVersion", "5.0.7");
|
||||||
|
|
||||||
modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b =>
|
modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b =>
|
||||||
{
|
{
|
||||||
@@ -2189,6 +2189,9 @@ namespace ErsatzTV.Infrastructure.Migrations
|
|||||||
b1.Property<DateTime?>("DurationFinish")
|
b1.Property<DateTime?>("DurationFinish")
|
||||||
.HasColumnType("TEXT");
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b1.Property<bool>("InFlood")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
b1.Property<int?>("MultipleRemaining")
|
b1.Property<int?>("MultipleRemaining")
|
||||||
.HasColumnType("INTEGER");
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user