From 63816adbc081065fe68b9bc20b49b9329c4abbd2 Mon Sep 17 00:00:00 2001 From: Arthur Araujo Date: Sat, 16 Mar 2024 21:20:12 -0300 Subject: [PATCH] Add verify checks to unused audio at the end --- .../Checks/CheckUnusedAudioAtEndTest.cs | 90 +++++++++++++++++++ .../CheckUnusedAudioAtEndStrings.cs | 19 ++++ osu.Game/Rulesets/Edit/BeatmapVerifier.cs | 2 + .../Edit/Checks/CheckUnusedAudioAtEnd.cs | 50 +++++++++++ 4 files changed, 161 insertions(+) create mode 100644 osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs create mode 100644 osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs create mode 100644 osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs diff --git a/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs new file mode 100644 index 0000000000..687feae63d --- /dev/null +++ b/osu.Game.Tests/Editing/Checks/CheckUnusedAudioAtEndTest.cs @@ -0,0 +1,90 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using Moq; +using NUnit.Framework; +using osu.Framework.Timing; +using osu.Game.Beatmaps; +using osu.Game.Rulesets.Edit; +using osu.Game.Rulesets.Edit.Checks; +using osu.Game.Rulesets.Objects; +using osu.Game.Rulesets.Osu.Objects; +using static osu.Game.Tests.Visual.OsuTestScene.ClockBackedTestWorkingBeatmap; + +namespace osu.Game.Tests.Editing.Checks +{ + public class CheckUnusedAudioTest + { + private CheckUnusedAudioAtEnd check = null!; + + private IBeatmap beatmapNotFullyMapped = null!; + + private IBeatmap beatmapFullyMapped = null!; + + [SetUp] + public void Setup() + { + check = new CheckUnusedAudioAtEnd(); + beatmapNotFullyMapped = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 1_298 }, + }, + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata { AudioFile = "abc123.jpg" } + } + }; + beatmapFullyMapped = new Beatmap + { + HitObjects = + { + new HitCircle { StartTime = 0 }, + new HitCircle { StartTime = 9000 }, + }, + BeatmapInfo = new BeatmapInfo + { + Metadata = new BeatmapMetadata { AudioFile = "abc123.jpg" } + } + }; + } + + [Test] + public void TestAudioNotFullyUsed() + { + var context = getContext(beatmapNotFullyMapped); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(1)); + Assert.That(issues.Single().Template is CheckUnusedAudioAtEnd.IssueTemplateUnusedAudioAtEnd); + } + + [Test] + public void TestAudioFullyUsed() + { + var context = getContext(beatmapFullyMapped); + var issues = check.Run(context).ToList(); + + Assert.That(issues, Has.Count.EqualTo(0)); + } + + private BeatmapVerifierContext getContext(IBeatmap beatmap) + { + return new BeatmapVerifierContext(beatmap, getMockWorkingBeatmap(beatmap).Object); + } + + private Mock getMockWorkingBeatmap(IBeatmap beatmap) + { + var mockTrack = new TrackVirtualStore(new FramedClock()).GetVirtual(10000, "virtual"); + + var mockWorkingBeatmap = new Mock(); + mockWorkingBeatmap.SetupGet(w => w.Beatmap).Returns(beatmap); + mockWorkingBeatmap.SetupGet(w => w.Track).Returns(mockTrack); + + return mockWorkingBeatmap; + } + } +} diff --git a/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs b/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs new file mode 100644 index 0000000000..46f92237a9 --- /dev/null +++ b/osu.Game/Localisation/CheckUnusedAudioAtEndStrings.cs @@ -0,0 +1,19 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Localisation +{ + public static class CheckUnusedAudioAtEndStrings + { + private const string prefix = @"osu.Game.Resources.Localisation.CheckUnusedAudioAtEnd"; + + /// + /// "{0}% of the audio is not mapped." + /// + public static LocalisableString OfTheAudioIsNot(double percentageLeft) => new TranslatableString(getKey(@"of_the_audio_is_not"), @"{0}% of the audio is not mapped.", percentageLeft); + + private static string getKey(string key) => $@"{prefix}:{key}"; + } +} diff --git a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs index dcf5eb4da9..4bba72d828 100644 --- a/osu.Game/Rulesets/Edit/BeatmapVerifier.cs +++ b/osu.Game/Rulesets/Edit/BeatmapVerifier.cs @@ -36,12 +36,14 @@ namespace osu.Game.Rulesets.Edit new CheckConcurrentObjects(), new CheckZeroLengthObjects(), new CheckDrainLength(), + new CheckUnusedAudioAtEnd(), // Timing new CheckPreviewTime(), // Events new CheckBreaks() + }; public IEnumerable Run(BeatmapVerifierContext context) diff --git a/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs new file mode 100644 index 0000000000..c120e0993a --- /dev/null +++ b/osu.Game/Rulesets/Edit/Checks/CheckUnusedAudioAtEnd.cs @@ -0,0 +1,50 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using osu.Game.Rulesets.Edit.Checks.Components; +using osu.Game.Rulesets.Objects; + +namespace osu.Game.Rulesets.Edit.Checks +{ + public class CheckUnusedAudioAtEnd : ICheck + { + public CheckMetadata Metadata => new CheckMetadata(CheckCategory.Compose, "More than 20% unused audio at the end"); + + public IEnumerable PossibleTemplates => new IssueTemplate[] + { + new IssueTemplateUnusedAudioAtEnd(this), + }; + + public IEnumerable Run(BeatmapVerifierContext context) + { + double mappedLength = context.Beatmap.HitObjects.Last().GetEndTime(); + double trackLength = context.WorkingBeatmap.Track.Length; + + double mappedPercentage = calculatePercentage(mappedLength, trackLength); + + if (mappedPercentage < 80) + { + yield return new IssueTemplateUnusedAudioAtEnd(this).Create(); + } + + } + + private double calculatePercentage(double mappedLenght, double trackLenght) + { + return Math.Round(mappedLenght / trackLenght * 100); + } + + public class IssueTemplateUnusedAudioAtEnd : IssueTemplate + { + public IssueTemplateUnusedAudioAtEnd(ICheck check) + : base(check, IssueType.Problem, "There is more than 20% unused audio at the end.") + { + } + + public Issue Create() => new Issue(this); + } + } +}