public async Task ChronologicalFlood_Should_AnchorAndMaintainExistingPlayout() { var mediaItems = new List <MediaItem> { TestMovie(1, TimeSpan.FromHours(6), DateTime.Today), TestMovie(2, TimeSpan.FromHours(6), DateTime.Today.AddHours(1)) }; (PlayoutBuilder builder, Playout playout) = TestDataFloodForItems(mediaItems, PlaybackOrder.Chronological); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(6); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Count.Should().Be(1); result.Items.Head().MediaItemId.Should().Be(1); result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); result.ProgramScheduleAnchors.Count.Should().Be(1); result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(1); DateTimeOffset start2 = HoursAfterMidnight(1); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(6); Playout result2 = await builder.BuildPlayoutItems(playout, start2, finish2); result2.Items.Count.Should().Be(2); result2.Items.Last().StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); result2.Items.Last().MediaItemId.Should().Be(2); result2.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(12)); result2.ProgramScheduleAnchors.Count.Should().Be(1); result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); }
public async Task Delete(int playoutId) { Playout playout = await _dbContext.Playouts.FindAsync(playoutId); _dbContext.Playouts.Remove(playout); await _dbContext.SaveChangesAsync(); }
public async Task ShuffleFlood_Should_MaintainRandomSeed() { var mediaItems = new List <MediaItem> { TestMovie(1, TimeSpan.FromHours(1), DateTime.Today), TestMovie(2, TimeSpan.FromHours(1), DateTime.Today.AddHours(1)), TestMovie(3, TimeSpan.FromHours(1), DateTime.Today.AddHours(3)) }; (PlayoutBuilder builder, Playout playout) = TestDataFloodForItems(mediaItems, PlaybackOrder.Shuffle); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(6); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Count.Should().Be(6); result.ProgramScheduleAnchors.Count.Should().Be(1); result.ProgramScheduleAnchors.Head().EnumeratorState.Seed.Should().BeGreaterThan(0); int firstSeedValue = result.ProgramScheduleAnchors.Head().EnumeratorState.Seed; DateTimeOffset start2 = HoursAfterMidnight(0); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(6); Playout result2 = await builder.BuildPlayoutItems(playout, start2, finish2); int secondSeedValue = result2.ProgramScheduleAnchors.Head().EnumeratorState.Seed; firstSeedValue.Should().Be(secondSeedValue); }
private async Task <Either <BaseError, Unit> > ApplyUpdateRequest(BuildPlayout request, Playout playout) { Playout result = await _playoutBuilder.BuildPlayoutItems(playout, request.Rebuild); await _playoutRepository.Update(result); return(unit); }
public async Task <Playout> Add(Playout playout) { await _dbContext.Playouts.AddAsync(playout); await _dbContext.SaveChangesAsync(); return(playout); }
private async Task <PlayoutViewModel> PersistPlayout(Playout c) { PlayoutViewModel result = await _playoutRepository.Add(c).Map(ProjectToViewModel); await _channel.WriteAsync(new BuildPlayout(result.Id)); return(result); }
private async Task <CreatePlayoutResponse> PersistPlayout(TvContext dbContext, Playout playout) { await dbContext.Playouts.AddAsync(playout); await dbContext.SaveChangesAsync(); await _channel.WriteAsync(new BuildPlayout(playout.Id, PlayoutBuildMode.Reset)); return(new CreatePlayoutResponse(playout.Id)); }
private async Task <PlayoutViewModel> ApplyUpdateRequest(Playout p, UpdatePlayout update) { p.ChannelId = update.ChannelId; p.ProgramScheduleId = update.ProgramScheduleId; p.ProgramSchedulePlayoutType = update.ProgramSchedulePlayoutType; await _playoutRepository.Update(p); await _channel.WriteAsync(new BuildPlayout(p.Id)); return(ProjectToViewModel(p)); }
/// <inheritdoc /> public OddmentTable <SabberStonePlayerTask> Create(SearchContext <List <SabberStoneAction>, SabberStoneState, SabberStoneAction, object, SabberStoneAction> context, int samplesForGeneration) { // So we have an issue here, because it's Hearthstone we don't know in advance how many dimensions we have. // -> We can just evenly distribute budget over the currently available dimensions // -- Reason is that some dimensions would be `locked' until after a specific dimensions is explored // -> Another option is to expand all possible sequences, this might be too complex though... // In Hearthstone we don't really have multiple available actions per dimension // It's more like you either play/attack or not // Although each minion can have multiple choices on what to attack // We can still try to distillate individual actions // It might be best to keep track of these through a dictionary/array // So we'd randomly choose actions and simulate when `end-turn' is chosen // And then update the value of any selected PlayerTask // I guess use OddmentTable again? var table = new Dictionary <SabberStonePlayerTask, double>(PlayerTaskComparer.Comparer); // So, we have a number of samples to use // For each of those, generate a random SabberStoneAction and playout for (var i = 0; i < samplesForGeneration; i++) { var action = PlayoutBot.CreateRandomAction(context.Source); var newState = GameLogic.Apply(context, (SabberStoneState)context.Source.Copy(), action); var endState = Playout.Playout(context, newState); var value = Evaluation.Evaluate(context, null, endState); foreach (var task in action.Tasks) { if (!table.ContainsKey(task)) { table.Add(task, 0); } table[task] += value; } } // Create the Oddment table var oddmentTable = new OddmentTable <SabberStonePlayerTask>(); foreach (var kvPair in table) { oddmentTable.Add(kvPair.Key, kvPair.Value, recalculate: false); } oddmentTable.Recalculate(); return(oddmentTable); }
public TState GetLastGameState() { if (Playout != null && Playout.Any()) { return(Playout.Last().Item2); } if (Expansion != null) { return(Expansion.State); } return(Selection.Last().State); }
/// <inheritdoc /> public void SetController(Controller controller) { Player = controller; MyPlayoutBot.SetController(Player); OpponentPlayoutBot.SetController(Player.Opponent); // Set the playout bots correctly if we are using PlayoutStrategySabberStone Playout.AddPlayoutBot(Player.Id, MyPlayoutBot); Playout.AddPlayoutBot(Player.Opponent.Id, OpponentPlayoutBot); // Create the searcher that will handle the searching and some administrative tasks Searcher = new SabberStoneSearch(Player, _debug); }
public async Task ZeroDurationItem_Should_Abort() { var mediaItems = new List <MediaItem> { TestMovie(1, TimeSpan.Zero, DateTime.Today) }; (PlayoutBuilder builder, Playout playout) = TestDataFloodForItems(mediaItems, PlaybackOrder.Random); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(6); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Should().BeNull(); }
public async Task InitialFlood_Should_StartAtMidnight() { var mediaItems = new List <MediaItem> { TestMovie(1, TimeSpan.FromHours(6), DateTime.Today) }; (PlayoutBuilder builder, Playout playout) = TestDataFloodForItems(mediaItems, PlaybackOrder.Random); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(6); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Count.Should().Be(1); result.Items.Head().StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); result.Items.Head().FinishOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); }
public async Task ShuffleFloodRebuild_Should_IgnoreAnchors() { var mediaItems = new List <MediaItem> { TestMovie(1, TimeSpan.FromHours(1), DateTime.Today), TestMovie(2, TimeSpan.FromHours(1), DateTime.Today.AddHours(1)), TestMovie(3, TimeSpan.FromHours(1), DateTime.Today.AddHours(2)), TestMovie(4, TimeSpan.FromHours(1), DateTime.Today.AddHours(3)), TestMovie(5, TimeSpan.FromHours(1), DateTime.Today.AddHours(4)), TestMovie(6, TimeSpan.FromHours(1), DateTime.Today.AddHours(5)) }; (PlayoutBuilder builder, Playout playout) = TestDataFloodForItems(mediaItems, PlaybackOrder.Shuffle); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(6); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Count.Should().Be(6); result.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); result.ProgramScheduleAnchors.Count.Should().Be(1); result.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); int firstSeedValue = result.ProgramScheduleAnchors.Head().EnumeratorState.Seed; DateTimeOffset start2 = HoursAfterMidnight(0); DateTimeOffset finish2 = start2 + TimeSpan.FromHours(6); Playout result2 = await builder.BuildPlayoutItems(playout, start2, finish2, true); result2.Items.Count.Should().Be(6); result2.Anchor.NextStartOffset.Should().Be(DateTime.Today.AddHours(6)); result2.ProgramScheduleAnchors.Count.Should().Be(1); result2.ProgramScheduleAnchors.Head().EnumeratorState.Index.Should().Be(0); int secondSeedValue = result2.ProgramScheduleAnchors.Head().EnumeratorState.Seed; firstSeedValue.Should().NotBe(secondSeedValue); }
public async Task ChronologicalContent_Should_CreateChronologicalItems() { var mediaItems = new List <MediaItem> { TestMovie(1, TimeSpan.FromHours(1), new DateTime(2020, 1, 1)), TestMovie(2, TimeSpan.FromHours(1), new DateTime(2020, 2, 1)) }; (PlayoutBuilder builder, Playout playout) = TestDataFloodForItems(mediaItems, PlaybackOrder.Chronological); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(4); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Count.Should().Be(4); result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); result.Items[0].MediaItemId.Should().Be(1); result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); result.Items[1].MediaItemId.Should().Be(2); result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); result.Items[2].MediaItemId.Should().Be(1); result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); result.Items[3].MediaItemId.Should().Be(2); }
/// <summary> /// Selects the best half of a collection of actions by evaluating them based on the provided search context. /// </summary> /// <param name="context">The current search context.</param> /// <param name="actions">The collection of actions to filter.</param> /// <param name="samplesPerAction">How many samples to run per action.</param> /// <returns>Collection of actions which Count is half of the original collection, rounded up. This collection is ordered by descending value.</returns> private List <ActionValue> SelectBestHalf(SearchContext <D, P, A, S, A> context, IReadOnlyCollection <ActionValue> actions, int samplesPerAction) { var clone = context.Cloner; // Evaluate each action by running a playout for it. foreach (var item in actions) { var tempNode = new N { Payload = item.Action }; var newState = GameLogic.Apply(context, clone.Clone(context.Source), item.Action); double value = 0; for (var i = 0; i < samplesPerAction; i++) { try { var endState = Playout.Playout(context, clone.Clone(newState)); value += Evaluation.Evaluate(context, tempNode, endState); SamplesUsedEvaluation++; } catch (Exception e) { //Console.WriteLine($"ERROR: {e.GetType()} while cloning state."); // TODO fix // Cloning here seems to very seldom cause a NullReference in the SabberStone dll // I believe failing and just using 0 as a value here is acceptable } } item.Value = value; } // Return the half with the highest value. var half = (int)Math.Max(1, Math.Ceiling(actions.Count / 2.0)); return(actions.OrderByDescending(i => i.Value).Take(half).ToList()); }
private async Task <Unit> ApplyUpdateRequest(TvContext dbContext, BuildPlayout request, Playout playout) { try { await _playoutBuilder.Build(playout, request.Mode); if (await dbContext.SaveChangesAsync() > 0) { _ffmpegSegmenterService.PlayoutUpdated(playout.Channel.Number); } await _ffmpegWorkerChannel.WriteAsync(new ExtractEmbeddedSubtitles(playout.Id)); } catch (Exception ex) { _client.Notify(ex); } return(Unit.Default); }
public async Task MultipleContent_Should_WrapAroundDynamicContent_DurationWithoutOfflineTail() { var multipleCollection = new Collection { Id = 1, Name = "Multiple 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 dynamicCollection = new Collection { Id = 2, Name = "Dynamic Items", MediaItems = new List <MediaItem> { TestMovie(3, TimeSpan.FromHours(0.75), new DateTime(2020, 1, 1)), TestMovie(4, TimeSpan.FromHours(1.5), new DateTime(2020, 1, 2)) } }; var fakeRepository = new FakeMediaCollectionRepository( Map( (multipleCollection.Id, multipleCollection.MediaItems.ToList()), (dynamicCollection.Id, dynamicCollection.MediaItems.ToList()))); var items = new List <ProgramScheduleItem> { new ProgramScheduleItemMultiple { Index = 1, Collection = multipleCollection, CollectionId = multipleCollection.Id, StartTime = null, Count = 2 }, new ProgramScheduleItemDuration { Index = 2, Collection = dynamicCollection, CollectionId = dynamicCollection.Id, StartTime = null, PlayoutDuration = TimeSpan.FromHours(2), OfflineTail = false // immediately continue } }; 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 builder = new PlayoutBuilder(fakeRepository, televisionRepo, _logger); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(6); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Count.Should().Be(6); result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); result.Items[0].MediaItemId.Should().Be(1); result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); result.Items[1].MediaItemId.Should().Be(2); result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); result.Items[2].MediaItemId.Should().Be(3); result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2.75)); result.Items[3].MediaItemId.Should().Be(1); result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3.75)); result.Items[4].MediaItemId.Should().Be(2); result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(4.75)); result.Items[5].MediaItemId.Should().Be(4); }
public async Task FloodContent_Should_FloodAroundFixedContent_Multiple() { 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 = null }, new ProgramScheduleItemMultiple { Index = 2, Collection = fixedCollection, CollectionId = fixedCollection.Id, StartTime = TimeSpan.FromHours(3), Count = 2 } }; 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 builder = new PlayoutBuilder(fakeRepository, televisionRepo, _logger); DateTimeOffset start = HoursAfterMidnight(0); DateTimeOffset finish = start + TimeSpan.FromHours(7); Playout result = await builder.BuildPlayoutItems(playout, start, finish); result.Items.Count.Should().Be(6); result.Items[0].StartOffset.TimeOfDay.Should().Be(TimeSpan.Zero); result.Items[0].MediaItemId.Should().Be(1); result.Items[1].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(1)); result.Items[1].MediaItemId.Should().Be(2); result.Items[2].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(2)); result.Items[2].MediaItemId.Should().Be(1); result.Items[3].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(3)); result.Items[3].MediaItemId.Should().Be(3); result.Items[4].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(5)); result.Items[4].MediaItemId.Should().Be(4); result.Items[5].StartOffset.TimeOfDay.Should().Be(TimeSpan.FromHours(6)); result.Items[5].MediaItemId.Should().Be(2); }
public async Task Update(Playout playout) { _dbContext.Playouts.Update(playout); await _dbContext.SaveChangesAsync(); }
internal static PlayoutViewModel ProjectToViewModel(Playout playout) =>