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()); }
public HighlyRatedSongsAdviser(IAdviseRankCalculator adviseRankCalculator, IClock dateTimeFacade, IOptions <HighlyRatedSongsAdviserSettings> options) { this.adviseRankCalculator = adviseRankCalculator ?? throw new ArgumentNullException(nameof(adviseRankCalculator)); this.dateTimeFacade = dateTimeFacade ?? throw new ArgumentNullException(nameof(dateTimeFacade)); this.settings = options?.Value ?? throw new ArgumentNullException(nameof(options)); if (settings.OneAdviseSongsNumber <= 0) { throw new InvalidOperationException($"{nameof(settings.OneAdviseSongsNumber)} is not set for highly rated songs adviser"); } maxTermsForRatings = settings.MaxTerms .ToDictionary(t => t.Rating, t => TimeSpan.FromDays(t.Days)); }
public void Constructor_OneAdviseSongsNumberIsNotSet_ThrowsInvalidOperationException() { // Arrange var settings = new HighlyRatedSongsAdviserSettings(); // Act Func <HighlyRatedSongsAdviser> call = () => new(Mock.Of <IAdviseRankCalculator>(), Mock.Of <IClock>(), Options.Create(settings)); // Assert call.Should().Throw <InvalidOperationException>(); }
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()); }
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()); }
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(); }