71 lines
2.8 KiB
C#
71 lines
2.8 KiB
C#
using ErsatzTV.Core.Domain;
|
|
using ErsatzTV.Core.Extensions;
|
|
using ErsatzTV.Core.Interfaces.Repositories;
|
|
using static ErsatzTV.Application.ProgramSchedules.ScheduleItemDurationEstimator;
|
|
|
|
namespace ErsatzTV.Application.ProgramSchedules;
|
|
|
|
public class GetProgramScheduleItemsWithDurationsHandler(
|
|
IMediator mediator,
|
|
IMediaCollectionRepository mediaCollectionRepository)
|
|
: IRequestHandler<GetProgramScheduleItemsWithDurations, ProgramScheduleItemsWithDurationViewModel>
|
|
{
|
|
public async Task<ProgramScheduleItemsWithDurationViewModel> Handle(
|
|
GetProgramScheduleItemsWithDurations request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
List<ProgramScheduleItemViewModel> items =
|
|
await mediator.Send(new GetProgramScheduleItems(request.Id), cancellationToken);
|
|
|
|
Dictionary<int, CollectionDuration> durationsByCollectionId =
|
|
await AggregateReferencedCollections(items);
|
|
|
|
var itemsWithEstimates = items
|
|
.Map(item => item with { DurationEstimate = Estimate(item, durationsByCollectionId) })
|
|
.ToList();
|
|
|
|
List<TimeSpan> estimates = itemsWithEstimates
|
|
.Map(item => Optional(item.DurationEstimate))
|
|
.Somes()
|
|
.ToList();
|
|
|
|
TimeSpan? total = estimates.Count > 0
|
|
? TimeSpan.FromTicks(estimates.Sum(estimate => estimate.Ticks))
|
|
: null;
|
|
|
|
return new ProgramScheduleItemsWithDurationViewModel(itemsWithEstimates, total);
|
|
}
|
|
|
|
// Aggregate MediaVersion.Duration once per distinct referenced collection (not per item). Only plain
|
|
// collections are resolved here; other reference types are estimated as null (see DurationEstimate docs).
|
|
private async Task<Dictionary<int, CollectionDuration>> AggregateReferencedCollections(
|
|
IReadOnlyList<ProgramScheduleItemViewModel> items)
|
|
{
|
|
List<int> collectionIds = items
|
|
.Filter(item => item.CollectionType is CollectionType.Collection && item.Collection is not null)
|
|
.Filter(item => item.PlayoutMode is PlayoutMode.One or PlayoutMode.Multiple)
|
|
.Map(item => item.Collection.Id)
|
|
.Distinct()
|
|
.ToList();
|
|
|
|
var result = new Dictionary<int, CollectionDuration>();
|
|
foreach (int collectionId in collectionIds)
|
|
{
|
|
List<MediaItem> mediaItems = await mediaCollectionRepository.GetItems(collectionId);
|
|
|
|
List<TimeSpan> durations = mediaItems
|
|
.Map(mediaItem => mediaItem.GetDurationForPlayout())
|
|
.Filter(duration => duration > TimeSpan.Zero)
|
|
.ToList();
|
|
|
|
if (durations.Count > 0)
|
|
{
|
|
var total = TimeSpan.FromTicks(durations.Sum(duration => duration.Ticks));
|
|
result[collectionId] = new CollectionDuration(total, durations.Count);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|