Files
ersatztv/ErsatzTV.Application/ProgramSchedules/Queries/GetProgramScheduleItemsWithDurationsHandler.cs
T

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;
}
}