コード例 #1
0
        public void CalculateAdviseGroupRank_IfAdviseGroupContainsDeletedAdviseSets_ConsidersDeletedAdviseSetsForPlaybacksAge()
        {
            // Arrange

            var adviseGroupContent1 = new AdviseGroupContent("1", isFavorite: false);

            adviseGroupContent1.AddDisc(CreateTestDisc("1.1", new[] { CreateTestSong(11, RatingModel.R5, new DateTime(2021, 06, 26)) }));
            adviseGroupContent1.AddDisc(CreateTestDisc("1.2", new[] { CreateTestSong(12, RatingModel.R5, new DateTime(2021, 06, 28), isDeleted: true) }));

            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(1, 5).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 27))));
            var adviseGroupContent3 = CreateTestAdviseGroupContent("3", Enumerable.Range(6, 5).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2, adviseGroupContent3 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank = target.CalculateAdviseGroupRank(adviseGroupContent1, playbacksInfo);

            // Assert

            // (discs number: 1 ^ 0.5) * (rating: 1.5 ^ 5) * (playbacks age: 1)
            rank.Should().Be(7.59375);
        }
コード例 #2
0
        public void CalculateAdviseSetRank_ForAdviseSetWithMixedRatings_ReturnsCorrectRank()
        {
            // Arrange

            var songs = new[]
            {
                CreateTestSong(11, rating: RatingModel.R2, new DateTime(2021, 06, 28)),
                CreateTestSong(12, rating: RatingModel.R3, new DateTime(2021, 06, 28)),
                CreateTestSong(13, rating: RatingModel.R5, new DateTime(2021, 06, 28)),
                CreateTestSong(14, rating: RatingModel.R4, new DateTime(2021, 06, 28)),
            };

            var adviseGroupContent1 = CreateTestAdviseGroupContent("1", songs);
            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(1, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank = target.CalculateAdviseSetRank(adviseGroupContent1.AdviseSets.Single(), playbacksInfo);

            // Assert

            // (rating: 1.5 ^ 2.5) * (playbacks age: 1)
            rank.Should().Be(4.133513940946613);
        }
コード例 #3
0
        public void CalculateSongRank_ForListenedSongWithRatingDefined_ReturnsCorrectRank()
        {
            // Arrange

            var song1 = CreateTestSong(11, RatingModel.R5, new DateTime(2021, 06, 26));
            var song2 = CreateTestSong(12, RatingModel.R7, new DateTime(2021, 06, 27));
            var song3 = CreateTestSong(13, RatingModel.R4, new DateTime(2021, 06, 28));

            var adviseGroupContent1 = CreateTestAdviseGroupContent("1", new[] { song1, song2, song3 });
            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(1, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank1 = target.CalculateSongRank(song1, playbacksInfo);
            var rank2 = target.CalculateSongRank(song2, playbacksInfo);
            var rank3 = target.CalculateSongRank(song3, playbacksInfo);

            // Assert

            // (rating: 1.5 ^ 5) * (playbacks age: 12)
            rank1.Should().Be(91.125);

            // (rating: 1.5 ^ 7) * (playbacks age: 11)
            rank2.Should().Be(187.9453125);

            // (rating: 1.5 ^ 4) * (playbacks age: 10)
            rank3.Should().Be(50.625);
        }
コード例 #4
0
        public void CalculateAdviseGroupRank_IfAdviseGroupContainsMultipleAdviseSets_ReturnsCorrectRank()
        {
            // Arrange

            var adviseGroupContent1 = new AdviseGroupContent("1", isFavorite: false);

            adviseGroupContent1.AddDisc(CreateTestDisc("1.1", new[] { CreateTestSong(11, RatingModel.R5, new DateTime(2021, 06, 26)) }));
            adviseGroupContent1.AddDisc(CreateTestDisc("1.2", new[] { CreateTestSong(12, RatingModel.R7, new DateTime(2021, 06, 27)) }));
            adviseGroupContent1.AddDisc(CreateTestDisc("1.3", new[] { CreateTestSong(13, RatingModel.R6, new DateTime(2021, 06, 28)) }));

            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(1, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank = target.CalculateAdviseGroupRank(adviseGroupContent1, playbacksInfo);

            // Assert

            // (discs number: 3 ^ 0.5) * (rating: 1.5 ^ 6) * (playbacks age: 1)
            rank.Should().BeApproximately(19.729141, 0.000001);
        }
コード例 #5
0
        public void CalculateAdviseGroupRank_IfAdviseGroupContainsDeletedAdviseSets_SkipsDeletedAdviseSetsWhenCountingSetsNumberAndAverageRating()
        {
            // Arrange

            var adviseGroupContent1 = new AdviseGroupContent("1", isFavorite: false);

            adviseGroupContent1.AddDisc(CreateTestDisc("1.1", new[] { CreateTestSong(11, RatingModel.R5, new DateTime(2021, 06, 26)) }));
            adviseGroupContent1.AddDisc(CreateTestDisc("1.2", new[] { CreateTestSong(12, RatingModel.R3, new DateTime(2021, 06, 27)) }));
            adviseGroupContent1.AddDisc(CreateTestDisc("1.3", new[] { CreateTestSong(13, RatingModel.R6, new DateTime(2021, 06, 28), isDeleted: true) }));

            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(1, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank = target.CalculateAdviseGroupRank(adviseGroupContent1, playbacksInfo);

            // Assert

            // (discs number: 2 ^ 0.5) * (rating: 1.5 ^ 6) * (playbacks age: 1)
            rank.Should().BeApproximately(7.15945616, 0.000001);
        }
コード例 #6
0
        public void CalculateAdviseGroupRank_ForAdviseGroupWithPlaybacksAndRatingsDefined_ReturnsCorrectRank()
        {
            // Arrange

            var adviseGroupContent1 = CreateTestAdviseGroupContent("1", new[] { CreateTestSong(11, RatingModel.R5, new DateTime(2021, 06, 26)) });
            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", new[] { CreateTestSong(12, RatingModel.R7, new DateTime(2021, 06, 27)) });
            var adviseGroupContent3 = CreateTestAdviseGroupContent("3", new[] { CreateTestSong(13, RatingModel.R4, new DateTime(2021, 06, 28)) });
            var adviseGroupContent4 = CreateTestAdviseGroupContent("4", Enumerable.Range(1, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2, adviseGroupContent3, adviseGroupContent4 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank1 = target.CalculateAdviseGroupRank(adviseGroupContent1, playbacksInfo);
            var rank2 = target.CalculateAdviseGroupRank(adviseGroupContent2, playbacksInfo);
            var rank3 = target.CalculateAdviseGroupRank(adviseGroupContent3, playbacksInfo);

            // Assert

            // (discs number: 1 ^ 0.5) * (rating: 1.5 ^ 5) * (playbacks age: 3)
            rank1.Should().Be(22.78125);

            // (discs number: 1 ^ 0.5) * (rating: 1.5 ^ 7) * (playbacks age: 2)
            rank2.Should().Be(34.171875);

            // (discs number: 1 ^ 0.5) * (rating: 1.5 ^ 4) * (playbacks age: 1)
            rank3.Should().Be(5.0625);
        }
コード例 #7
0
        public void CalculateAdviseSetRank_ForAdviseSetWithMultipleDiscs_ReturnsCorrectRank()
        {
            // Arrange

            var disc1     = CreateTestDisc("1.1", new[] { CreateTestSong(1, RatingModel.R5, new DateTime(2021, 08, 28)) });
            var disc2     = CreateTestDisc("1.2", new[] { CreateTestSong(2, RatingModel.R7, new DateTime(2021, 08, 28)) });
            var adviseSet = new AdviseSetModel {
                Id = new ItemId("1")
            };

            disc1.AdviseSetInfo = new AdviseSetInfo(adviseSet, 1);
            disc2.AdviseSetInfo = new AdviseSetInfo(adviseSet, 2);

            var adviseGroupContent1 = new AdviseGroupContent("1", isFavorite: false);

            adviseGroupContent1.AddDisc(disc1);
            adviseGroupContent1.AddDisc(disc2);

            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(11, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 08, 27))));
            var adviseGroupContent3 = CreateTestAdviseGroupContent("3", Enumerable.Range(21, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 08, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2, adviseGroupContent3 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank = target.CalculateAdviseSetRank(adviseGroupContent1.AdviseSets.Single(), playbacksInfo);

            // Assert

            // (rating: 1.5 ^ 6) * (playbacks age: 1)
            rank.Should().Be(11.390625);
        }
コード例 #8
0
        public async Task Advise_SortsAdviseGroups()
        {
            // Arrange

            var adviseSet1    = CreateTestAdviseSet("1");
            var adviseSet2    = CreateTestAdviseSet("2");
            var adviseGroups  = CreateAdviseGroups(adviseSet1, adviseSet2).ToList();
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var adviseContentSorterStub = new Mock <IAdviseContentSorter>();

            adviseContentSorterStub.Setup(x => x.SortAdviseGroups(adviseGroups, playbacksInfo)).Returns(new[] { adviseGroups[1], adviseGroups[0] });
            adviseContentSorterStub.Setup(x => x.SortAdviseSets(It.IsAny <IEnumerable <AdviseSetContent> >(), playbacksInfo))
            .Returns <IEnumerable <AdviseSetContent>, PlaybacksInfo>((adviseSets, _) => adviseSets);

            var mocker = new AutoMocker();

            mocker.Use(adviseContentSorterStub);

            var target = mocker.CreateInstance <RankBasedAdviser>();

            // Act

            var advises = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            var expectedAdvises = new[]
            {
                AdvisedPlaylist.ForAdviseSet(adviseSet2),
                AdvisedPlaylist.ForAdviseSet(adviseSet1),
            };

            advises.Should().BeEquivalentTo(expectedAdvises, x => x.WithStrictOrdering());
        }
コード例 #9
0
        public async Task Advise_IfSongsAreAdvised_ReturnsSongsWithHigherRankFirst()
        {
            // Arrange

            var settings = new HighlyRatedSongsAdviserSettings
            {
                OneAdviseSongsNumber = 3,
                MaxTerms             = new[]
                {
                    new MaxRatingTerm
                    {
                        Rating = RatingModel.R10,
                        Days   = 30,
                    },
                },
            };

            var song1         = CreateTestSong(1, RatingModel.R10, new DateTime(2017, 02, 01));
            var song2         = CreateTestSong(2, RatingModel.R10, new DateTime(2017, 02, 01));
            var song3         = CreateTestSong(3, RatingModel.R10, new DateTime(2017, 02, 01));
            var adviseSet     = CreateTestAdviseSet("1", new[] { song1, song2, song3 });
            var adviseGroups  = CreateAdviseGroups(adviseSet);
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var adviseRankCalculatorStub = new Mock <IAdviseRankCalculator>();

            adviseRankCalculatorStub.Setup(x => x.CalculateSongRank(song1, playbacksInfo)).Returns(0.25);
            adviseRankCalculatorStub.Setup(x => x.CalculateSongRank(song2, playbacksInfo)).Returns(0.75);
            adviseRankCalculatorStub.Setup(x => x.CalculateSongRank(song3, playbacksInfo)).Returns(0.50);

            var clockStub = new Mock <IClock>();

            clockStub.Setup(x => x.Now).Returns(new DateTime(2017, 10, 01));

            var mocker = new AutoMocker();

            mocker.Use(adviseRankCalculatorStub);
            mocker.Use(clockStub);
            mocker.Use(Options.Create(settings));

            var target = mocker.CreateInstance <HighlyRatedSongsAdviser>();

            // Act

            var advises = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            var expectedAdvises = new[]
            {
                AdvisedPlaylist.ForHighlyRatedSongs(new[] { song2, song3, song1 }),
            };

            advises.Should().BeEquivalentTo(expectedAdvises, x => x.WithStrictOrdering());
        }
コード例 #10
0
        public async Task Advise_IfAllAdviseSetsAreActive_AdvisesSetsInCorrectOrder()
        {
            // Arrange

            // Last playback time for each advise group:
            //
            //     adviseGroup1: 3, 2
            //     adviseGroup2: null
            //     adviseGroup3: null, 1
            //
            // Expected order (order within advise group is provided by inner adviser and is not changed):
            //
            //     adviseSet21, adviseSet11, adviseSet31
            var adviseSet11 = CreateTestAdviseSet("11", new[] { CreateTestSong(1, new DateTime(2018, 08, 17)) });
            var adviseSet12 = CreateTestAdviseSet("12", new[] { CreateTestSong(2, new DateTime(2018, 08, 18)) });
            var adviseSet21 = CreateTestAdviseSet("21", new[] { CreateTestSong(3) });
            var adviseSet31 = CreateTestAdviseSet("31", new[] { CreateTestSong(4) });
            var adviseSet32 = CreateTestAdviseSet("32", new[] { CreateTestSong(5, new DateTime(2018, 08, 19)) });

            var adviseGroups = new[]
            {
                CreateAdviseGroup("1", isFavorite: true, adviseSet11, adviseSet12),
                CreateAdviseGroup("2", isFavorite: true, adviseSet21),
                CreateAdviseGroup("3", isFavorite: true, adviseSet31, adviseSet32),
            };

            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var rankBasedAdviserStub = new Mock <IPlaylistAdviser>();

            rankBasedAdviserStub.Setup(x => x.Advise(adviseGroups, playbacksInfo, It.IsAny <CancellationToken>())).ReturnsAsync(CreatedAdvisedPlaylists(adviseGroups));

            var mocker = new AutoMocker();

            mocker.Use(rankBasedAdviserStub);

            var target = mocker.CreateInstance <FavoriteAdviseGroupsAdviser>();

            // Act

            var advisedPlaylists = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            var expectedPlaylists = new[]
            {
                AdvisedPlaylist.ForAdviseSetFromFavoriteAdviseGroup(adviseSet21),
                AdvisedPlaylist.ForAdviseSetFromFavoriteAdviseGroup(adviseSet11),
                AdvisedPlaylist.ForAdviseSetFromFavoriteAdviseGroup(adviseSet31),
            };

            advisedPlaylists.Should().BeEquivalentTo(expectedPlaylists, x => x.WithStrictOrdering());
        }
コード例 #11
0
        public async Task Advise_IfTooMuchSongsAreAdvised_SplitsThemIntoSmallerPlaylists()
        {
            // Arrange

            var settings = new HighlyRatedSongsAdviserSettings
            {
                OneAdviseSongsNumber = 12,
                MaxTerms             = new[]
                {
                    new MaxRatingTerm
                    {
                        Rating = RatingModel.R10,
                        Days   = 30,
                    },
                },
            };

            var songs1        = Enumerable.Range(1, 12).Select(id => CreateTestSong(id, RatingModel.R10, lastPlaybackTime: null)).ToList();
            var songs2        = Enumerable.Range(13, 12).Select(id => CreateTestSong(id, RatingModel.R10, lastPlaybackTime: null)).ToList();
            var adviseGroups  = CreateAdviseGroups(CreateTestAdviseSet("1", songs1), CreateTestAdviseSet("2", songs2));
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var clockStub = new Mock <IClock>();

            clockStub.Setup(x => x.Now).Returns(new DateTime(2017, 10, 01));

            var mocker = new AutoMocker();

            mocker.Use(clockStub);
            mocker.Use(Options.Create(settings));

            var target = mocker.CreateInstance <HighlyRatedSongsAdviser>();

            // Act

            var advises = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            var expectedAdvises = new[]
            {
                AdvisedPlaylist.ForHighlyRatedSongs(songs1),
                AdvisedPlaylist.ForHighlyRatedSongs(songs2),
            };

            advises.Should().BeEquivalentTo(expectedAdvises, x => x.WithStrictOrdering());
        }
コード例 #12
0
        public async Task Advise_ReturnsSongsWithHighRatingListenedEarlierThanConfiguredTerm()
        {
            // Arrange

            var settings = new HighlyRatedSongsAdviserSettings
            {
                OneAdviseSongsNumber = 12,
                MaxTerms             = new[]
                {
                    new MaxRatingTerm
                    {
                        Rating = RatingModel.R10,
                        Days   = 30,
                    },
                },
            };

            var songs         = Enumerable.Range(1, 12).Select(id => CreateTestSong(id, RatingModel.R10, new DateTime(2017, 09, 01))).ToList();
            var adviseSet     = CreateTestAdviseSet("1", songs);
            var adviseGroups  = CreateAdviseGroups(adviseSet);
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var clockStub = new Mock <IClock>();

            clockStub.Setup(x => x.Now).Returns(new DateTime(2017, 10, 07));

            var mocker = new AutoMocker();

            mocker.Use(clockStub);
            mocker.Use(Options.Create(settings));

            var target = mocker.CreateInstance <HighlyRatedSongsAdviser>();

            // Act

            var advises = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            var expectedAdvises = new[]
            {
                AdvisedPlaylist.ForHighlyRatedSongs(songs),
            };

            advises.Should().BeEquivalentTo(expectedAdvises, x => x.WithStrictOrdering());
        }
コード例 #13
0
        public async Task <IReadOnlyCollection <AdvisedPlaylist> > Advise(IEnumerable <DiscModel> discs, int requiredAdvisesCount, CancellationToken cancellationToken)
        {
            Memo ??= await sessionDataService.GetData <PlaylistAdviserMemo>(PlaylistAdviserDataKey, cancellationToken) ?? CreateDefaultMemo();

            var playbacksMemo = Memo;

            var adviseGroups  = (await discGrouper.GroupLibraryDiscs(discs, cancellationToken)).ToList();
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var highlyRatedSongsAdvises = await highlyRatedSongsAdviser.Advise(adviseGroups, playbacksInfo, cancellationToken);

            var favoriteAdviseGroupAdvises = await favoriteAdviseGroupsAdviser.Advise(adviseGroups, playbacksInfo, cancellationToken);

            var rankedAdvises = await rankBasedAdviser.Advise(adviseGroups, playbacksInfo, cancellationToken);

            var playlistQueue = new CompositeAdvisedPlaylistQueue(highlyRatedSongsAdvises, favoriteAdviseGroupAdvises, rankedAdvises);

            var advisedPlaylists = new List <AdvisedPlaylist>(requiredAdvisesCount);

            var knownAdviseSets = new HashSet <string>();

            while (advisedPlaylists.Count < requiredAdvisesCount)
            {
                var currentAdvise = GetNextAdvisedPlaylist(playbacksMemo, playlistQueue);
                if (currentAdvise == null)
                {
                    break;
                }

                var adviseSet = currentAdvise.AdviseSet;
                if (adviseSet != null)
                {
                    if (knownAdviseSets.Contains(adviseSet.Id))
                    {
                        continue;
                    }

                    knownAdviseSets.Add(adviseSet.Id);
                }

                advisedPlaylists.Add(currentAdvise);
                playbacksMemo = playbacksMemo.RegisterPlayback(currentAdvise);
            }

            return(advisedPlaylists);
        }
コード例 #14
0
        public void CalculateAdviseSetRank_ForAdviseSetWithoutPlaybacks_ReturnsMaxRank()
        {
            // Arrange

            var adviseGroupContent1 = CreateTestAdviseGroupContent("1", new[] { CreateTestSong(11, lastPlaybackTime: null) });
            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(1, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank = target.CalculateAdviseSetRank(adviseGroupContent1.AdviseSets.Single(), playbacksInfo);

            // Assert

            rank.Should().Be(Double.MaxValue);
        }
コード例 #15
0
        public async Task Advise_IfSomeAdviseSetsAreDeleted_SkipsDeletedAdviseSets()
        {
            // Arrange

            var deletedDisc = CreateTestDisc("1", isDeleted: true);
            var activeDisc  = CreateTestDisc("2", isDeleted: false);

            var adviseGroup = new AdviseGroupContent("1", isFavorite: false);

            adviseGroup.AddDisc(deletedDisc);
            adviseGroup.AddDisc(activeDisc);

            var adviseGroups  = new[] { adviseGroup };
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var adviseContentSorterStub = new Mock <IAdviseContentSorter>();

            adviseContentSorterStub.Setup(x => x.SortAdviseGroups(It.IsAny <IEnumerable <AdviseGroupContent> >(), playbacksInfo))
            .Returns <IEnumerable <AdviseGroupContent>, PlaybacksInfo>((adviseGroups, _) => adviseGroups);
            adviseContentSorterStub.Setup(x => x.SortAdviseSets(It.IsAny <IEnumerable <AdviseSetContent> >(), playbacksInfo))
            .Returns <IEnumerable <AdviseSetContent>, PlaybacksInfo>((adviseSets, _) => adviseSets);

            var mocker = new AutoMocker();

            mocker.Use(adviseContentSorterStub);

            var target = mocker.CreateInstance <RankBasedAdviser>();

            // Act

            var advises = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            var expectedAdvises = new[]
            {
                AdvisedPlaylist.ForAdviseSet(activeDisc.ToAdviseSet()),
            };

            advises.Should().BeEquivalentTo(expectedAdvises, x => x.WithStrictOrdering());
        }
コード例 #16
0
        public async Task Advise_IfNumberOfAdvisedSongsIsNotEnough_ReturnsNoPlaylists()
        {
            // Arrange

            var settings = new HighlyRatedSongsAdviserSettings
            {
                OneAdviseSongsNumber = 12,
                MaxTerms             = new[]
                {
                    new MaxRatingTerm
                    {
                        Rating = RatingModel.R10,
                        Days   = 30,
                    },
                },
            };

            var songs         = Enumerable.Range(1, 11).Select(id => CreateTestSong(id, RatingModel.R10, lastPlaybackTime: null)).ToList();
            var adviseSet     = CreateTestAdviseSet("1", songs);
            var adviseGroups  = CreateAdviseGroups(adviseSet);
            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var clockStub = new Mock <IClock>();

            clockStub.Setup(x => x.Now).Returns(new DateTime(2017, 10, 01));

            var mocker = new AutoMocker();

            mocker.Use(clockStub);
            mocker.Use(Options.Create(settings));

            var target = mocker.CreateInstance <HighlyRatedSongsAdviser>();

            // Act

            var advises = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            advises.Should().BeEmpty();
        }
コード例 #17
0
        public void CalculateAdviseSetRank_ForListenedAdviseSetWithNoRatingDefined_ReturnsCorrectRank()
        {
            // Arrange

            var adviseGroupContent1 = CreateTestAdviseGroupContent("1", new[] { CreateTestSong(11, rating: null, new DateTime(2021, 06, 28)) });
            var adviseGroupContent2 = CreateTestAdviseGroupContent("2", Enumerable.Range(1, 10).Select(id => CreateTestSong(id, RatingModel.R5, new DateTime(2021, 06, 29))));

            var playbacksInfo = new PlaybacksInfo(new[] { adviseGroupContent1, adviseGroupContent2 });

            var mocker = new AutoMocker();
            var target = mocker.CreateInstance <AdviseRankCalculator>();

            // Act

            var rank = target.CalculateAdviseSetRank(adviseGroupContent1.AdviseSets.Single(), playbacksInfo);

            // Assert

            // (rating: 1.5 ^ 5) * (playbacks age: 1)
            rank.Should().Be(7.59375);
        }
コード例 #18
0
        public async Task Advise_AdvisesOnlySetsFromFavoriteAdviseGroups()
        {
            // Arrange

            var adviseSetFromFavoriteAdviseGroup    = CreateTestAdviseSet("1", new[] { CreateTestSong(1) });
            var adviseSetFromNonFavoriteAdviseGroup = CreateTestAdviseSet("2", new[] { CreateTestSong(2) });

            var adviseGroups = new[]
            {
                CreateAdviseGroup("1", isFavorite: false, adviseSetFromNonFavoriteAdviseGroup),
                CreateAdviseGroup("2", isFavorite: true, adviseSetFromFavoriteAdviseGroup),
            };

            var playbacksInfo = new PlaybacksInfo(adviseGroups);

            var rankBasedAdviserStub = new Mock <IPlaylistAdviser>();

            rankBasedAdviserStub.Setup(x => x.Advise(adviseGroups, playbacksInfo, It.IsAny <CancellationToken>()))
            .ReturnsAsync(CreatedAdvisedPlaylists(adviseGroups));

            var mocker = new AutoMocker();

            mocker.Use(rankBasedAdviserStub);

            var target = mocker.CreateInstance <FavoriteAdviseGroupsAdviser>();

            // Act

            var advisedPlaylists = await target.Advise(adviseGroups, playbacksInfo, CancellationToken.None);

            // Assert

            var expectedPlaylists = new[]
            {
                AdvisedPlaylist.ForAdviseSetFromFavoriteAdviseGroup(adviseSetFromFavoriteAdviseGroup),
            };

            advisedPlaylists.Should().BeEquivalentTo(expectedPlaylists, x => x.WithStrictOrdering());
        }
コード例 #19
0
        public void SortAdviseSets_SortsAdviseSetsByTheirRank()
        {
            // Arrange

            var adviseSet1 = CreateTestAdviseSet("1");
            var adviseSet2 = CreateTestAdviseSet("2");
            var adviseSet3 = CreateTestAdviseSet("3");

            var playbacksInfo = new PlaybacksInfo(Enumerable.Empty <AdviseGroupContent>());

            var adviseRankCalculatorStub = new Mock <IAdviseRankCalculator>();

            adviseRankCalculatorStub.Setup(x => x.CalculateAdviseSetRank(adviseSet1, playbacksInfo)).Returns(0.25);
            adviseRankCalculatorStub.Setup(x => x.CalculateAdviseSetRank(adviseSet2, playbacksInfo)).Returns(0.75);
            adviseRankCalculatorStub.Setup(x => x.CalculateAdviseSetRank(adviseSet3, playbacksInfo)).Returns(0.50);

            var mocker = new AutoMocker();

            mocker.Use(adviseRankCalculatorStub);

            var target = mocker.CreateInstance <RankBasedAdviseContentSorter>();

            // Act

            var result = target.SortAdviseSets(new[] { adviseSet1, adviseSet2, adviseSet3, }, playbacksInfo).ToList();

            // Assert

            var expectedAdviseSets = new[]
            {
                adviseSet2,
                adviseSet3,
                adviseSet1,
            };

            result.Should().BeEquivalentTo(expectedAdviseSets, x => x.WithStrictOrdering());
        }
コード例 #20
0
        public void SortAdviseGroups_SortsAdviseGroupsByTheirRank()
        {
            // Arrange

            var adviseGroup1 = new AdviseGroupContent("group1", isFavorite: false);
            var adviseGroup2 = new AdviseGroupContent("group2", isFavorite: false);
            var adviseGroup3 = new AdviseGroupContent("group3", isFavorite: false);

            var playbacksInfo = new PlaybacksInfo(Enumerable.Empty <AdviseGroupContent>());

            var adviseRankCalculatorStub = new Mock <IAdviseRankCalculator>();

            adviseRankCalculatorStub.Setup(x => x.CalculateAdviseGroupRank(adviseGroup1, playbacksInfo)).Returns(0.25);
            adviseRankCalculatorStub.Setup(x => x.CalculateAdviseGroupRank(adviseGroup2, playbacksInfo)).Returns(0.75);
            adviseRankCalculatorStub.Setup(x => x.CalculateAdviseGroupRank(adviseGroup3, playbacksInfo)).Returns(0.50);

            var mocker = new AutoMocker();

            mocker.Use(adviseRankCalculatorStub);

            var target = mocker.CreateInstance <RankBasedAdviseContentSorter>();

            // Act

            var result = target.SortAdviseGroups(new[] { adviseGroup1, adviseGroup2, adviseGroup3 }, playbacksInfo).ToList();

            // Assert

            var expectedAdviseGroups = new[]
            {
                adviseGroup2,
                adviseGroup3,
                adviseGroup1,
            };

            result.Should().BeEquivalentTo(expectedAdviseGroups, x => x.WithStrictOrdering());
        }
コード例 #21
0
        public Task <IReadOnlyCollection <AdvisedPlaylist> > Advise(IEnumerable <AdviseGroupContent> adviseGroups, PlaybacksInfo playbacksInfo, CancellationToken cancellationToken)
        {
            var songsToAdvise = adviseGroups
                                .SelectMany(adviseGroup => adviseGroup.AdviseSets)
                                .SelectMany(adviseSet => adviseSet.Discs)
                                .SelectMany(disc => disc.ActiveSongs)
                                .Where(IsTimeToListenHighlyRatedSong)
                                .OrderByDescending(song => adviseRankCalculator.CalculateSongRank(song, playbacksInfo))
                                .ThenByDescending(song => song.GetRatingOrDefault())
                                .ToList();

            var playlists = SplitSongsToPlaylists(songsToAdvise).ToList();

            return(Task.FromResult <IReadOnlyCollection <AdvisedPlaylist> >(playlists));
        }
コード例 #22
0
        private IEnumerable <AdviseSetContent> GetSortedAdviseSets(IEnumerable <AdviseGroupContent> adviseGroups, PlaybacksInfo playbacksInfo)
        {
            var activeAdviseGroups = adviseGroups.Where(x => !x.IsDeleted);

            foreach (var adviseGroup in adviseContentSorter.SortAdviseGroups(activeAdviseGroups, playbacksInfo))
            {
                var activeAdviseSets = adviseGroup.AdviseSets.Where(x => !x.IsDeleted);
                yield return(adviseContentSorter.SortAdviseSets(activeAdviseSets, playbacksInfo).First());
            }
        }
コード例 #23
0
        public Task <IReadOnlyCollection <AdvisedPlaylist> > Advise(IEnumerable <AdviseGroupContent> adviseGroups, PlaybacksInfo playbacksInfo, CancellationToken cancellationToken)
        {
            var playlists = GetSortedAdviseSets(adviseGroups, playbacksInfo)
                            .Select(AdvisedPlaylist.ForAdviseSet)
                            .ToList();

            return(Task.FromResult <IReadOnlyCollection <AdvisedPlaylist> >(playlists));
        }
コード例 #24
0
        public async Task <IReadOnlyCollection <AdvisedPlaylist> > Advise(IEnumerable <AdviseGroupContent> adviseGroups, PlaybacksInfo playbacksInfo, CancellationToken cancellationToken)
        {
            var adviseGroupsList = adviseGroups.ToList();

            var adviseSetToAdviseGroupMap = adviseGroupsList
                                            .SelectMany(adviseGroup => adviseGroup.AdviseSets.Select(adviseSet => (adviseGroup, adviseSet)))
                                            .ToDictionary(x => x.adviseSet.Id, x => x.adviseGroup);

            var advisedPlaylists = await rankBasedAdviser.Advise(adviseGroupsList, playbacksInfo, cancellationToken);

            return(advisedPlaylists.Select(x => x.AdviseSet)
                   .GroupBy(x => adviseSetToAdviseGroupMap[x.Id], new AdviseGroupContentEqualityComparer())
                   .Where(g => g.Key.IsFavorite)
                   .OrderByDescending(g => playbacksInfo.GetPlaybacksPassed(g.Key))
                   .Select(g => g.First())
                   .Select(AdvisedPlaylist.ForAdviseSetFromFavoriteAdviseGroup)
                   .ToList());
        }