Example #1
0
        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);
        }
Example #2
0
        public async Task Delete(int playoutId)
        {
            Playout playout = await _dbContext.Playouts.FindAsync(playoutId);

            _dbContext.Playouts.Remove(playout);
            await _dbContext.SaveChangesAsync();
        }
Example #3
0
        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);
        }
Example #4
0
        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);
        }
Example #5
0
        public async Task <Playout> Add(Playout playout)
        {
            await _dbContext.Playouts.AddAsync(playout);

            await _dbContext.SaveChangesAsync();

            return(playout);
        }
Example #6
0
        private async Task <PlayoutViewModel> PersistPlayout(Playout c)
        {
            PlayoutViewModel result = await _playoutRepository.Add(c).Map(ProjectToViewModel);

            await _channel.WriteAsync(new BuildPlayout(result.Id));

            return(result);
        }
Example #7
0
    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));
        }
Example #9
0
            /// <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);
            }
Example #10
0
        public TState GetLastGameState()
        {
            if (Playout != null && Playout.Any())
            {
                return(Playout.Last().Item2);
            }

            if (Expansion != null)
            {
                return(Expansion.State);
            }

            return(Selection.Last().State);
        }
Example #11
0
        /// <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);
        }
Example #12
0
        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();
        }
Example #13
0
        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));
        }
Example #14
0
        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);
        }
Example #15
0
        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);
        }
Example #16
0
        /// <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);
    }
Example #18
0
        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);
        }
Example #19
0
        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);
        }
Example #20
0
 public async Task Update(Playout playout)
 {
     _dbContext.Playouts.Update(playout);
     await _dbContext.SaveChangesAsync();
 }
Example #21
0
 internal static PlayoutViewModel ProjectToViewModel(Playout playout) =>