Browse Source

fix playout building

pull/31/head
Jason Dove 6 years ago
parent
commit
42d2cec545
  1. 4
      ErsatzTV.Core.Tests/Fakes/FakeTelevisionRepository.cs
  2. 4
      ErsatzTV.Core/Interfaces/Repositories/ITelevisionRepository.cs
  3. 29
      ErsatzTV.Core/Scheduling/PlayoutBuilder.cs
  4. 152
      ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs
  5. 1
      ErsatzTV.Infrastructure/Data/Repositories/PlayoutRepository.cs
  6. 69
      ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs

4
ErsatzTV.Core.Tests/Fakes/FakeTelevisionRepository.cs

@ -24,7 +24,7 @@ namespace ErsatzTV.Core.Tests.Fakes @@ -24,7 +24,7 @@ namespace ErsatzTV.Core.Tests.Fakes
public Task<List<ShowMetadata>> GetPagedShows(int pageNumber, int pageSize) =>
throw new NotSupportedException();
public Task<List<Episode>> GetShowItems(int televisionShowId) => throw new NotSupportedException();
public Task<List<Episode>> GetShowItems(int showId) => throw new NotSupportedException();
public Task<List<Season>> GetAllSeasons() => throw new NotSupportedException();
@ -35,7 +35,7 @@ namespace ErsatzTV.Core.Tests.Fakes @@ -35,7 +35,7 @@ namespace ErsatzTV.Core.Tests.Fakes
public Task<List<Season>> GetPagedSeasons(int televisionShowId, int pageNumber, int pageSize) =>
throw new NotSupportedException();
public Task<List<Episode>> GetSeasonItems(int televisionSeasonId) => throw new NotSupportedException();
public Task<List<Episode>> GetSeasonItems(int seasonId) => throw new NotSupportedException();
public Task<Option<Episode>> GetEpisode(int televisionEpisodeId) => throw new NotSupportedException();

4
ErsatzTV.Core/Interfaces/Repositories/ITelevisionRepository.cs

@ -14,12 +14,12 @@ namespace ErsatzTV.Core.Interfaces.Repositories @@ -14,12 +14,12 @@ namespace ErsatzTV.Core.Interfaces.Repositories
Task<Option<Show>> GetShow(int televisionShowId);
Task<int> GetShowCount();
Task<List<ShowMetadata>> GetPagedShows(int pageNumber, int pageSize);
Task<List<Episode>> GetShowItems(int televisionShowId);
Task<List<Episode>> GetShowItems(int showId);
Task<List<Season>> GetAllSeasons();
Task<Option<Season>> GetSeason(int televisionSeasonId);
Task<int> GetSeasonCount(int televisionShowId);
Task<List<Season>> GetPagedSeasons(int televisionShowId, int pageNumber, int pageSize);
Task<List<Episode>> GetSeasonItems(int televisionSeasonId);
Task<List<Episode>> GetSeasonItems(int seasonId);
Task<Option<Episode>> GetEpisode(int televisionEpisodeId);
Task<int> GetEpisodeCount(int televisionSeasonId);
Task<List<EpisodeMetadata>> GetPagedEpisodes(int televisionSeasonId, int pageNumber, int pageSize);

29
ErsatzTV.Core/Scheduling/PlayoutBuilder.cs

@ -55,15 +55,15 @@ namespace ErsatzTV.Core.Scheduling @@ -55,15 +55,15 @@ namespace ErsatzTV.Core.Scheduling
{
case ProgramScheduleItemCollectionType.Collection:
Option<List<MediaItem>> maybeItems =
await _mediaCollectionRepository.GetItems(collectionKey.Id);
await _mediaCollectionRepository.GetItems(collectionKey.CollectionId ?? 0);
return Tuple(collectionKey, maybeItems.IfNone(new List<MediaItem>()));
case ProgramScheduleItemCollectionType.TelevisionShow:
List<Episode> showItems =
await _televisionRepository.GetShowItems(collectionKey.Id);
await _televisionRepository.GetShowItems(collectionKey.MediaItemId ?? 0);
return Tuple(collectionKey, showItems.Cast<MediaItem>().ToList());
case ProgramScheduleItemCollectionType.TelevisionSeason:
List<Episode> seasonItems =
await _televisionRepository.GetSeasonItems(collectionKey.Id);
await _televisionRepository.GetSeasonItems(collectionKey.MediaItemId ?? 0);
return Tuple(collectionKey, seasonItems.Cast<MediaItem>().ToList());
default:
return Tuple(collectionKey, new List<MediaItem>());
@ -325,7 +325,9 @@ namespace ErsatzTV.Core.Scheduling @@ -325,7 +325,9 @@ namespace ErsatzTV.Core.Scheduling
{
Option<PlayoutProgramScheduleAnchor> maybeExisting = playout.ProgramScheduleAnchors
.FirstOrDefault(
a => a.CollectionType == collectionKey.CollectionType && a.NewCollectionId == collectionKey.Id);
a => a.CollectionType == collectionKey.CollectionType
&& a.NewCollectionId == collectionKey.CollectionId
&& a.MediaItemId == collectionKey.MediaItemId);
var maybeEnumeratorState = collectionEnumerators.GroupBy(e => e.Key, e => e.Value.State)
.ToDictionary(mcs => mcs.Key, mcs => mcs.Head());
@ -343,7 +345,8 @@ namespace ErsatzTV.Core.Scheduling @@ -343,7 +345,8 @@ namespace ErsatzTV.Core.Scheduling
ProgramSchedule = playout.ProgramSchedule,
ProgramScheduleId = playout.ProgramScheduleId,
CollectionType = collectionKey.CollectionType,
NewCollectionId = collectionKey.Id,
NewCollectionId = collectionKey.CollectionId,
MediaItemId = collectionKey.MediaItemId,
EnumeratorState = maybeEnumeratorState[collectionKey]
});
@ -360,9 +363,10 @@ namespace ErsatzTV.Core.Scheduling @@ -360,9 +363,10 @@ namespace ErsatzTV.Core.Scheduling
{
Option<PlayoutProgramScheduleAnchor> maybeAnchor = playout.ProgramScheduleAnchors
.FirstOrDefault(
a => a.ProgramScheduleId == playout.ProgramScheduleId && a.CollectionType ==
collectionKey.CollectionType
&& a.NewCollectionId == collectionKey.Id);
a => a.ProgramScheduleId == playout.ProgramScheduleId
&& a.CollectionType == collectionKey.CollectionType
&& a.NewCollectionId == collectionKey.CollectionId
&& a.MediaItemId == collectionKey.MediaItemId);
CollectionEnumeratorState state = maybeAnchor.Match(
anchor => anchor.EnumeratorState,
@ -400,17 +404,17 @@ namespace ErsatzTV.Core.Scheduling @@ -400,17 +404,17 @@ namespace ErsatzTV.Core.Scheduling
ProgramScheduleItemCollectionType.Collection => new CollectionKey
{
CollectionType = item.CollectionType,
Id = item.CollectionId.Value
CollectionId = item.CollectionId
},
ProgramScheduleItemCollectionType.TelevisionShow => new CollectionKey
{
CollectionType = item.CollectionType,
Id = item.MediaItemId.Value
MediaItemId = item.MediaItemId
},
ProgramScheduleItemCollectionType.TelevisionSeason => new CollectionKey
{
CollectionType = item.CollectionType,
Id = item.MediaItemId.Value
MediaItemId = item.MediaItemId
},
_ => throw new ArgumentOutOfRangeException(nameof(item))
};
@ -418,7 +422,8 @@ namespace ErsatzTV.Core.Scheduling @@ -418,7 +422,8 @@ namespace ErsatzTV.Core.Scheduling
private class CollectionKey : Record<CollectionKey>
{
public ProgramScheduleItemCollectionType CollectionType { get; set; }
public int Id { get; set; }
public int? CollectionId { get; set; }
public int? MediaItemId { get; set; }
}
}
}

152
ErsatzTV.Infrastructure/Data/Repositories/MediaCollectionRepository.cs

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
@ -78,7 +77,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -78,7 +77,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
_dbContext.Collections.ToListAsync();
public Task<Option<List<MediaItem>>> GetItems(int id) =>
Get(id).MapT(c => c.MediaItems);
Get(id).MapT(GetItemsForCollection).Bind(x => x.Sequence());
public Task Update(Collection collection)
{
@ -93,82 +92,75 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -93,82 +92,75 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
await _dbContext.SaveChangesAsync();
}
// private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionShowItems(SimpleMediaCollection collection)
// {
// var parameters = new { CollectionId = collection.Id };
// return await _dbConnection
// .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
// TelevisionEpisodeMediaItem>(
// @"select tmi.Id, tmi.SeasonId, mi.LibraryPathId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
// mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
// mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
// tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
// from TelevisionEpisode tmi
// inner join MediaItem mi on tmi.Id = mi.Id
// inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
// inner join TelevisionSeason tsn on tsn.Id = tmi.SeasonId
// inner join TelevisionShow ts on ts.Id = tsn.TelevisionShowId
// inner join SimpleMediaCollectionShow s on s.TelevisionShowsId = ts.Id
// where s.SimpleMediaCollectionsId = @CollectionId",
// (episode, statistics, metadata) =>
// {
// episode.Statistics = statistics;
// episode.Metadata = metadata;
// return episode;
// },
// parameters,
// splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
// }
//
// private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionSeasonItems(SimpleMediaCollection collection)
// {
// var parameters = new { CollectionId = collection.Id };
// return await _dbConnection
// .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
// TelevisionEpisodeMediaItem>(
// @"select tmi.Id, tmi.SeasonId, mi.LibraryPathId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
// mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
// mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
// tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
// from TelevisionEpisode tmi
// inner join MediaItem mi on tmi.Id = mi.Id
// inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
// inner join TelevisionSeason tsn on tsn.Id = tmi.SeasonId
// inner join SimpleMediaCollectionSeason s on s.TelevisionSeasonsId = tsn.Id
// where s.SimpleMediaCollectionsId = @CollectionId",
// (episode, statistics, metadata) =>
// {
// episode.Statistics = statistics;
// episode.Metadata = metadata;
// return episode;
// },
// parameters,
// splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
// }
//
// private async Task<List<TelevisionEpisodeMediaItem>> GetTelevisionEpisodeItems(SimpleMediaCollection collection)
// {
// var parameters = new { CollectionId = collection.Id };
// return await _dbConnection
// .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
// TelevisionEpisodeMediaItem>(
// @"select tmi.Id, tmi.SeasonId, mi.LibraryPathId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
// mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
// mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
// tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
// from TelevisionEpisode tmi
// inner join MediaItem mi on tmi.Id = mi.Id
// inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
// inner join SimpleMediaCollectionEpisode s on s.TelevisionEpisodesId = tmi.Id
// where s.SimpleMediaCollectionsId = @CollectionId",
// (episode, statistics, metadata) =>
// {
// episode.Statistics = statistics;
// episode.Metadata = metadata;
// return episode;
// },
// parameters,
// splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
// }
private async Task<List<MediaItem>> GetItemsForCollection(Collection collection)
{
var result = new List<MediaItem>();
result.AddRange(await GetMovieItems(collection));
result.AddRange(await GetShowItems(collection));
result.AddRange(await GetSeasonItems(collection));
result.AddRange(await GetEpisodeItems(collection));
return result.Distinct().ToList();
}
private async Task<List<Movie>> GetMovieItems(Collection collection)
{
IEnumerable<int> ids = await _dbConnection.QueryAsync<int>(
@"SELECT m.Id FROM CollectionItem ci
INNER JOIN Movie m ON m.Id = ci.MediaItemId
WHERE ci.CollectionId = @CollectionId",
new { CollectionId = collection.Id });
return await _dbContext.Movies
.Include(m => m.MovieMetadata)
.Filter(m => ids.Contains(m.Id))
.ToListAsync();
}
private async Task<List<Episode>> GetShowItems(Collection collection)
{
IEnumerable<int> ids = await _dbConnection.QueryAsync<int>(
@"SELECT Episode.Id FROM CollectionItem ci
INNER JOIN Show ON Show.Id = ci.MediaItemId
INNER JOIN Season ON Season.ShowId = Show.Id
INNER JOIN Episode ON Episode.SeasonId = Season.Id
WHERE ci.CollectionId = @CollectionId",
new { CollectionId = collection.Id });
return await _dbContext.Episodes
.Include(e => e.EpisodeMetadata)
.Filter(e => ids.Contains(e.Id))
.ToListAsync();
}
private async Task<List<Episode>> GetSeasonItems(Collection collection)
{
IEnumerable<int> ids = await _dbConnection.QueryAsync<int>(
@"SELECT Episode.Id FROM CollectionItem ci
INNER JOIN Season ON Season.Id = ci.MediaItemId
INNER JOIN Episode ON Episode.SeasonId = Season.Id
WHERE ci.CollectionId = @CollectionId",
new { CollectionId = collection.Id });
return await _dbContext.Episodes
.Include(e => e.EpisodeMetadata)
.Filter(e => ids.Contains(e.Id))
.ToListAsync();
}
private async Task<List<Episode>> GetEpisodeItems(Collection collection)
{
IEnumerable<int> ids = await _dbConnection.QueryAsync<int>(
@"SELECT Episode.Id FROM CollectionItem ci
INNER JOIN Episode ON Episode.Id = ci.MediaItemId
WHERE ci.CollectionId = @CollectionId",
new { CollectionId = collection.Id });
return await _dbContext.Episodes
.Include(e => e.EpisodeMetadata)
.Filter(e => ids.Contains(e.Id))
.ToListAsync();
}
}
}

1
ErsatzTV.Infrastructure/Data/Repositories/PlayoutRepository.cs

@ -32,6 +32,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -32,6 +32,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
.Include(p => p.Channel)
.Include(p => p.Items)
.Include(p => p.ProgramScheduleAnchors)
.ThenInclude(a => a.MediaItem)
.Include(p => p.ProgramSchedule)
.ThenInclude(ps => ps.Items)
.ThenInclude(psi => psi.Collection)

69
ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs

@ -3,6 +3,7 @@ using System.Collections.Generic; @@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using Dapper;
using ErsatzTV.Core;
using ErsatzTV.Core.Domain;
using ErsatzTV.Core.Interfaces.Repositories;
@ -220,57 +221,27 @@ namespace ErsatzTV.Infrastructure.Data.Repositories @@ -220,57 +221,27 @@ namespace ErsatzTV.Infrastructure.Data.Repositories
})
.ToUnit();
public async Task<List<Episode>> GetShowItems(int televisionShowId) =>
// TODO: fix this
new();
public async Task<List<Episode>> GetShowItems(int showId)
{
IEnumerable<int> ids = await _dbConnection.QueryAsync<int>(
@"SELECT Episode.Id FROM Show
INNER JOIN Season ON Season.ShowId = Show.Id
INNER JOIN Episode ON Episode.SeasonId = Season.Id
WHERE Show.Id = @ShowId",
new { ShowId = showId });
// var parameters = new { ShowId = televisionShowId };
// return await _dbConnection
// .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
// TelevisionEpisodeMediaItem>(
// @"select tmi.Id, tmi.SeasonId, mi.LibraryPathId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
// mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
// mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
// tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
// from TelevisionEpisode tmi
// inner join MediaItem mi on tmi.Id = mi.Id
// inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
// inner join TelevisionSeason tsn on tsn.Id = tmi.SeasonId
// inner join TelevisionShow ts on ts.Id = tsn.TelevisionShowId
// where ts.Id = @ShowId",
// (episode, statistics, metadata) =>
// {
// episode.Statistics = statistics;
// episode.Metadata = metadata;
// return episode;
// },
// parameters,
// splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
public async Task<List<Episode>> GetSeasonItems(int televisionSeasonId) =>
// TODO: fix this
new();
return await _dbContext.Episodes
.Include(e => e.EpisodeMetadata)
.Filter(e => ids.Contains(e.Id))
.ToListAsync();
}
public Task<List<Episode>> GetSeasonItems(int seasonId) =>
_dbContext.Episodes
.Include(e => e.EpisodeMetadata)
.Filter(e => e.SeasonId == seasonId)
.ToListAsync();
// var parameters = new { SeasonId = televisionSeasonId };
// return await _dbConnection
// .QueryAsync<TelevisionEpisodeMediaItem, MediaItemStatistics, TelevisionEpisodeMetadata,
// TelevisionEpisodeMediaItem>(
// @"select tmi.Id, tmi.SeasonId, mi.LibraryPathId, mi.LastWriteTime, mi.Path, mi.Poster, mi.PosterLastWriteTime,
// mi.Statistics_AudioCodec as AudioCodec, mi.Statistics_DisplayAspectRatio as DisplayAspectRatio, mi.Statistics_Duration as Duration, mi.Statistics_Height as Height, mi.Statistics_LastWriteTime as LastWriteTime, mi.Statistics_SampleAspectRatio as SampleAspectRatio,
// mi.Statistics_VideoCodec as VideoCodec, mi.Statistics_VideoScanType as VideoScanType, mi.Statistics_Width as Width,
// tem.TelevisionEpisodeId, tem.Id, tem.Season, tem.Episode, tem.Plot, tem.Aired, tem.Source, tem.LastWriteTime, tem.Title, tem.SortTitle
// from TelevisionEpisode tmi
// inner join MediaItem mi on tmi.Id = mi.Id
// inner join TelevisionEpisodeMetadata tem on tem.TelevisionEpisodeId = tmi.Id
// inner join TelevisionSeason tsn on tsn.Id = tmi.SeasonId
// where tsn.Id = @SeasonId",
// (episode, statistics, metadata) =>
// {
// episode.Statistics = statistics;
// episode.Metadata = metadata;
// return episode;
// },
// parameters,
// splitOn: "AudioCodec,TelevisionEpisodeId").Map(result => result.ToList());
private async Task<Either<BaseError, Season>> AddSeason(
Show show,
string path,

Loading…
Cancel
Save