diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 29934d4..67e8a67 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -4,6 +4,7 @@ concurrency: crowdin on: push: branches: [ main ] + workflow_dispatch jobs: synchronize-with-crowdin: diff --git a/PlayNext.UnitTests/Model/Score/GameScore/FinalGameScoreCalculatorTests.cs b/PlayNext.UnitTests/Model/Score/GameScore/FinalGameScoreCalculatorTests.cs index 6f59de9..c736d8a 100644 --- a/PlayNext.UnitTests/Model/Score/GameScore/FinalGameScoreCalculatorTests.cs +++ b/PlayNext.UnitTests/Model/Score/GameScore/FinalGameScoreCalculatorTests.cs @@ -1,10 +1,10 @@ using System; using System.Collections.Generic; using System.Linq; -using AutoFixture.Xunit2; using PlayNext.Model.Data; using PlayNext.Model.Score.GameScore; using Playnite.SDK.Models; +using TestTools.Shared; using Xunit; namespace PlayNext.UnitTests.Model.Score.GameScore @@ -12,33 +12,86 @@ namespace PlayNext.UnitTests.Model.Score.GameScore public class FinalGameScoreCalculatorTests { [Theory] - [InlineAutoData(nameof(Game.GenreIds))] - [InlineAutoData(nameof(Game.FeatureIds))] - [InlineAutoData(nameof(Game.DeveloperIds))] - [InlineAutoData(nameof(Game.PublisherIds))] - [InlineAutoData(nameof(Game.TagIds))] - public void Calculate( - string attributeIdsName, + [InlineAutoMoqData(nameof(Game.GenreIds), nameof(Game.TagIds), 0.50, 0.25, 100, 50)] + [InlineAutoMoqData(nameof(Game.FeatureIds), nameof(Game.GenreIds), 0.50, 0.49, 100, 98)] + [InlineAutoMoqData(nameof(Game.DeveloperIds), nameof(Game.FeatureIds), 0.2, 0.1, 100, 50)] + [InlineAutoMoqData(nameof(Game.PublisherIds), nameof(Game.DeveloperIds), 0.50, 0.49, 100, 98)] + [InlineAutoMoqData(nameof(Game.TagIds), nameof(Game.PublisherIds), 0.50, 0.49, 100, 98)] + public void TwoAttributes_BetweenTwoGames( + string topAttribute, + string secondTopAttribute, + float topAttributeWeight, + float secondTopAttributeWeight, + float topGameScore, + float secondTopGameScore, + Dictionary topAttributeScores, + Dictionary secondTopAttributeScores, Game[] games, int releaseYear, TimeSpan gameLength, - Dictionary attributeScore, FinalGameScoreCalculator sut) { // Arrange var gameScoreCalculationWeights = GetEmptyWeights(); - gameScoreCalculationWeights.Genre = 1; + SetWeight(topAttribute, gameScoreCalculationWeights, topAttributeWeight); + SetWeight(secondTopAttribute, gameScoreCalculationWeights, secondTopAttributeWeight); var topGame = games.Last(); - SetAttributes(attributeIdsName, topGame, attributeScore.Keys.ToArray()); - SetWeight(attributeIdsName, gameScoreCalculationWeights, 1); + var secondTopGame = games.First(); + SetAttributes(topAttribute, topGame, topAttributeScores.Keys.ToArray()); + SetAttributes(secondTopAttribute, secondTopGame, secondTopAttributeScores.Keys.ToArray()); + var attributeScore = topAttributeScores.Concat(secondTopAttributeScores).ToDictionary(x => x.Key, x => x.Value); // Act var result = sut.Calculate(games, attributeScore, gameScoreCalculationWeights, releaseYear, gameLength); // Assert Assert.Equal(topGame.Id, result.First().Key); - Assert.Equal(100, result.First().Value); + Assert.Equal(topGameScore, result.First().Value); + Assert.Equal(secondTopGame.Id, result.Skip(1).First().Key); + Assert.Equal(secondTopGameScore, result.Skip(1).First().Value); + } + + [Theory] + [InlineAutoMoqData(nameof(Game.GenreIds), 0.50, 100, 50, 100, 50)] + [InlineAutoMoqData(nameof(Game.FeatureIds), 0.1, 5, 1, 100, 20)] + [InlineAutoMoqData(nameof(Game.DeveloperIds), 1, 50, 25, 100, 50)] + [InlineAutoMoqData(nameof(Game.PublisherIds), 0.33, 100, 1, 100, 1)] + [InlineAutoMoqData(nameof(Game.TagIds), 0.2, 50, 49, 100, 98)] + public void SameAttributeBetweenTwoGames( + string attribute, + float attributeWeight, + float topGameAttributeSum, + float secondGameTopAttributeSum, + float topGameScore, + float secondTopGameScore, + Game[] games, + int releaseYear, + TimeSpan gameLength, + Guid topAttributeId, + Guid secondTopAttributeId, + FinalGameScoreCalculator sut) + { + // Arrange + var topAttributeScores = new Dictionary() { { topAttributeId, topGameAttributeSum } }; + var secondTopAttributeScores = new Dictionary() { { secondTopAttributeId, secondGameTopAttributeSum } }; + var gameScoreCalculationWeights = GetEmptyWeights(); + SetWeight(attribute, gameScoreCalculationWeights, attributeWeight); + + var topGame = games.Last(); + var secondTopGame = games.First(); + SetAttributes(attribute, topGame, topAttributeScores.Keys.ToArray()); + SetAttributes(attribute, secondTopGame, secondTopAttributeScores.Keys.ToArray()); + var attributeScore = topAttributeScores.Concat(secondTopAttributeScores).ToDictionary(x => x.Key, x => x.Value); + + // Act + var result = sut.Calculate(games, attributeScore, gameScoreCalculationWeights, releaseYear, gameLength); + + // Assert + Assert.Equal(topGame.Id, result.First().Key); + Assert.Equal(topGameScore, result.First().Value); + Assert.Equal(secondTopGame.Id, result.Skip(1).First().Key); + Assert.Equal(secondTopGameScore, result.Skip(1).First().Value); } private GameScoreWeights GetEmptyWeights() diff --git a/PlayNext/HowLongToBeat/HowLongToBeatExtension.cs b/PlayNext/HowLongToBeat/HowLongToBeatExtension.cs index a8aaa58..2f73b69 100644 --- a/PlayNext/HowLongToBeat/HowLongToBeatExtension.cs +++ b/PlayNext/HowLongToBeat/HowLongToBeatExtension.cs @@ -10,7 +10,7 @@ namespace PlayNext.HowLongToBeat { - public class HowLongToBeatExtension + public class HowLongToBeatExtension : IHowLongToBeatExtension { private static Guid _extensionId = Guid.Parse("e08cd51f-9c9a-4ee3-a094-fde03b55492f"); private readonly ILogger _logger = LogManager.GetLogger(nameof(HowLongToBeatExtension)); diff --git a/PlayNext/HowLongToBeat/IHowLongToBeatExtension.cs b/PlayNext/HowLongToBeat/IHowLongToBeatExtension.cs new file mode 100644 index 0000000..b28f429 --- /dev/null +++ b/PlayNext/HowLongToBeat/IHowLongToBeatExtension.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Playnite.SDK.Models; + +namespace PlayNext.HowLongToBeat +{ + public interface IHowLongToBeatExtension + { + bool DoesDataExist(); + Task ParseFiles(IEnumerable games); + Dictionary GetTimeToPlay(); + } +} \ No newline at end of file diff --git a/PlayNext/Model/Score/GameScore/FinalGameScoreCalculator.cs b/PlayNext/Model/Score/GameScore/FinalGameScoreCalculator.cs index 33f2fd5..e83d609 100644 --- a/PlayNext/Model/Score/GameScore/FinalGameScoreCalculator.cs +++ b/PlayNext/Model/Score/GameScore/FinalGameScoreCalculator.cs @@ -10,7 +10,7 @@ namespace PlayNext.Model.Score.GameScore { public class FinalGameScoreCalculator { - private readonly HowLongToBeatExtension _howLongToBeatExtension; + private readonly IHowLongToBeatExtension _howLongToBeatExtension; private readonly GameScoreByAttributeCalculator _gameScoreByAttributeCalculator; private readonly CriticScoreCalculator _criticScoreCalculator; private readonly CommunityScoreCalculator _communityScoreCalculator; @@ -19,7 +19,7 @@ public class FinalGameScoreCalculator private readonly ScoreNormalizer _scoreNormalizer; private readonly Summator _summator; - public FinalGameScoreCalculator(HowLongToBeatExtension howLongToBeatExtension, + public FinalGameScoreCalculator(IHowLongToBeatExtension howLongToBeatExtension, GameScoreByAttributeCalculator gameScoreByAttributeCalculator, CriticScoreCalculator criticScoreCalculator, CommunityScoreCalculator communityScoreCalculator, diff --git a/PlayNext/PlayNext.csproj b/PlayNext/PlayNext.csproj index 4edf25d..fbb0ee3 100644 --- a/PlayNext/PlayNext.csproj +++ b/PlayNext/PlayNext.csproj @@ -69,6 +69,7 @@ +