using Ludarium.Domain; using Ludarium.Application; namespace Ludarium.UnitTests; public sealed class ArtworkQualityTests { [Theory] [InlineData(1526, 1370)] [InlineData(2100, 1536)] [InlineData(512, 521)] public void LandscapeOrSquareImagesAreNotCoverQuality(int width, int height) => Assert.True(ArtworkQuality.Score(width, height, null, "LaunchBox", Confidence.High) < ArtworkQuality.VerifiedThreshold); [Fact] public void PortraitHighResolutionTrustedArtworkIsVerified() => Assert.True(ArtworkQuality.Score(600, 900, 0.6667m, "LaunchBox", Confidence.High) >= ArtworkQuality.VerifiedThreshold); [Theory] [InlineData("ps5", 1600, 2040)] [InlineData("switch", 1000, 1600)] [InlineData("nds", 1350, 1220)] [InlineData("3ds", 1300, 1160)] [InlineData("n64", 1400, 1000)] [InlineData("snes", 1400, 1000)] [InlineData("gb", 1000, 1000)] public void PlatformRetailProfilesVerifyTheirActualFrontCoverGeometry(string platform, int width, int height) => Assert.True(ArtworkQuality.Score(width, height, null, "LaunchBox", Confidence.High, platform) >= ArtworkQuality.VerifiedThreshold); [Theory] [InlineData("amiga-cd32", 1000, 1000)] [InlineData("fds", 900, 1200)] [InlineData("n64dd", 1290, 1120)] [InlineData("atari-lynx", 1300, 1600)] [InlineData("neo-geo-pocket", 1050, 1200)] [InlineData("wonderswan-color", 1000, 1500)] public void NicheRetailProfilesVerifyTheirDocumentedFrontGeometry(string platform, int width, int height) => Assert.True(ArtworkQuality.Score(width, height, null, "LaunchBox", Confidence.High, platform) >= ArtworkQuality.VerifiedThreshold); [Theory] [InlineData("wiiu", "wii-u")] [InlineData("xbox360", "xbox-360")] [InlineData("xboxone", "xbox-one")] [InlineData("xboxseries", "xbox-series")] [InlineData("mastersystem", "master-system")] [InlineData("gamegear", "game-gear")] [InlineData("sega32x", "sega-32x")] [InlineData("segacd", "sega-cd")] public void HistoricalScanIdsUseTheirCanonicalRetailProfile(string historical, string canonical) => Assert.Equal(ArtworkQuality.ExpectedRatio(canonical), ArtworkQuality.ExpectedRatio(historical)); [Fact] public void GenericPortraitIsRejectedAsPs5RetailCover() => Assert.Equal(0, ArtworkQuality.Score(600, 900, null, "Provider", Confidence.High, "ps5")); [Theory] [InlineData("nds", 1220, 1350)] [InlineData("3ds", 1160, 1300)] [InlineData("n64", 1000, 1400)] [InlineData("snes", 1000, 1400)] public void InvertedOrWrongRegionGeometryIsRejected(string platform, int width, int height) => Assert.Equal(0, ArtworkQuality.Score(width, height, null, "LaunchBox", Confidence.High, platform)); [Fact] public void SteamLibraryArtCannotClaimToBeRetailPackaging() => Assert.Equal(0, ArtworkQuality.Score(1000, 1400, null, "Steam", Confidence.High, "windows")); [Fact] public void VerifiedDigitalOnlyFrontUsesItsStorefrontGeometryAndPosterRole() { var artwork = new GameArtwork(Guid.NewGuid(), Guid.NewGuid(), ArtworkRole.BoxFront, ArtworkVerificationStatus.NeedsReview, "SteamDigital", "SteamDigital", "2659050", "verified-digital-only-storefront-front", Confidence.High, 600, 900, 0.6667m, 100, new string('a', 64), 0, DateTimeOffset.UtcNow, false, "windows"); var evaluated = ArtworkQuality.EvaluateForPlatform(artwork, "windows"); Assert.True(evaluated.QualityScore >= ArtworkQuality.VerifiedThreshold); Assert.Equal(ArtworkRole.Poster, evaluated.Role); Assert.Equal(ArtworkVerificationStatus.AutomaticallyVerified, evaluated.VerificationStatus); } [Theory] [InlineData(512, 357, 1.4342)] [InlineData(400, 400, 1.0)] [InlineData(120, 180, 0.6667)] public void LandscapeSquareAndTinyImagesNeedReview(int width, int height, double ratio) => Assert.True(ArtworkQuality.Score(width, height, (decimal)ratio, "Provider", Confidence.High) < ArtworkQuality.VerifiedThreshold); [Fact] public void GeneratedArtworkCanNeverClaimVerifiedQuality() => Assert.True(ArtworkQuality.Score(1200, 1800, 0.6667m, "Generated", Confidence.Deterministic) < ArtworkQuality.VerifiedThreshold); [Fact] public void ManualCoverOverrideSurvivesPlatformEvaluation() { var uploaded = new GameArtwork(Guid.NewGuid(), Guid.NewGuid(), ArtworkRole.UserUpload, ArtworkVerificationStatus.ManuallyVerified, "Uploaded", "Uploaded", null, "operator-upload", Confidence.Deterministic, 400, 400, 1m, 10, new string('a', 64), 35, DateTimeOffset.UtcNow, Platform: null); Assert.Equal(uploaded, ArtworkQuality.EvaluateForPlatform(uploaded, "ps5")); } [Fact] public void BestCandidateUsesQualityThenConfidenceAndNeverSelectsRejectedArtwork() { var gameId = Guid.NewGuid(); var now = DateTimeOffset.UtcNow; GameArtwork Candidate(decimal score, Confidence confidence, ArtworkVerificationStatus status = ArtworkVerificationStatus.NeedsReview) => new(Guid.NewGuid(), gameId, ArtworkRole.BoxFront, status, "fixture", "fixture", null, "fixture", confidence, 600, 900, 0.6667m, 100, new string('a', 64), score, now, false); var low = Candidate(60, Confidence.Deterministic); var high = Candidate(90, Confidence.High); var rejected = Candidate(100, Confidence.Deterministic, ArtworkVerificationStatus.Rejected); Assert.Equal(high.Id, ArtworkQuality.SelectBest([low, rejected, high])?.Id); } }