diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs index 80340f2a5..b5eb433ab 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandlerTest.cs @@ -8,6 +8,7 @@ using osu.Framework.Graphics.Sprites; using osu.Game.Rulesets.Karaoke.Configuration; using osu.Game.Rulesets.Karaoke.Edit.ChangeHandlers.Lyrics; +using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Edit.Utils; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Objects.Properties; @@ -61,13 +62,7 @@ public void TestDetectReferenceLyricWithNonSupportedLyric() Text = "???" }); - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.DetectReferenceLyric)); - - AssertSelectedHitObject(h => - { - Assert.IsNull(h.ReferenceLyric); - Assert.IsNull(h.ReferenceLyricConfig); - }); + TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.DetectReferenceLyric)); } #endregion @@ -149,13 +144,7 @@ public void TestAutoGenerateRubyTagsWithNonSupportedLyric() }, }); - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRubyTags)); - - AssertSelectedHitObject(h => - { - // should not able to generate time-tag if lyric text is empty, or did not have language. - Assert.IsEmpty(h.RubyTags); - }); + TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRubyTags)); } #endregion @@ -201,13 +190,7 @@ public void TestAutoGenerateRomajiTagsWithNonSupportedLyric() }, }); - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRomajiTags)); - - AssertSelectedHitObject(h => - { - // should not able to generate time-tag if lyric text is empty, or did not have language. - Assert.IsEmpty(h.RomajiTags); - }); + TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateRomajiTags)); } #endregion @@ -251,13 +234,7 @@ public void TestAutoGenerateTimeTagsWithNonSupportedLyric() }, }); - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateTimeTags)); - - AssertSelectedHitObject(h => - { - // should not able to generate time-tag if lyric text is empty, or did not have language. - Assert.IsEmpty(h.TimeTags); - }); + TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateTimeTags)); } #endregion @@ -302,12 +279,7 @@ public void TestAutoGenerateNotesWithNonSupportedLyric() Text = "カラオケ", }); - TriggerHandlerChanged(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateNotes)); - - AssertSelectedHitObject(h => - { - Assert.IsEmpty(getMatchedNotes(h)); - }); + TriggerHandlerChangedWithException(c => c.AutoGenerate(LyricAutoGenerateProperty.AutoGenerateNotes)); } private Note[] getMatchedNotes(Lyric lyric) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BaseGeneratorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BaseGeneratorTest.cs deleted file mode 100644 index 40eebeb08..000000000 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BaseGeneratorTest.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using System; -using osu.Game.Rulesets.Karaoke.Edit.Generator; - -namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator; - -public class BaseGeneratorTest where TConfig : IHasConfig, new() -{ - protected static TConfig GeneratorConfig(Action? action = null) - { - var config = new TConfig(); - action?.Invoke(config); - return config; - } - - protected static TConfig GeneratorDefaultConfig(Action? action = null) - { - var config = new TConfig().CreateDefaultConfig(); - action?.Invoke(config); - return config; - } -} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BasePropertyDetectorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BasePropertyDetectorTest.cs new file mode 100644 index 000000000..18809fe9d --- /dev/null +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BasePropertyDetectorTest.cs @@ -0,0 +1,69 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Rulesets.Karaoke.Edit.Generator; + +namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator; + +public abstract class BasePropertyDetectorTest + : BasePropertyDetectorTest + where TDetector : PropertyDetector + where TConfig : IHasConfig, new() +{ + protected static TConfig GeneratorConfig(Action? action = null) + { + var config = new TConfig(); + action?.Invoke(config); + return config; + } + + protected static TConfig GeneratorDefaultConfig(Action? action = null) + { + var config = new TConfig().CreateDefaultConfig(); + action?.Invoke(config); + return config; + } + + protected static TDetector GenerateDetector(TConfig config) + { + if (Activator.CreateInstance(typeof(TDetector), config) is not TDetector detector) + throw new ArgumentNullException(nameof(detector)); + + return detector; + } + + protected static void CheckCanDetect(TItem item, bool canDetect, TConfig config) + { + var detector = GenerateDetector(config); + + CheckCanDetect(item, canDetect, detector); + } + + protected void CheckDetectResult(TItem item, TProperty expected, TConfig config) + { + var detector = GenerateDetector(config); + + CheckDetectResult(item, expected, detector); + } +} + +public abstract class BasePropertyDetectorTest + where TDetector : PropertyDetector +{ + protected static void CheckCanDetect(TItem item, bool canDetect, TDetector detector) + { + bool actual = detector.CanDetect(item); + Assert.AreEqual(canDetect, actual); + } + + protected void CheckDetectResult(TItem item, TProperty expected, TDetector detector) + { + // create time tag and actually time tag. + var actual = detector.Detect(item); + AssertEqual(expected, actual); + } + + protected abstract void AssertEqual(TProperty expected, TProperty actual); +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BasePropertyGeneratorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BasePropertyGeneratorTest.cs new file mode 100644 index 000000000..ffb86b4e3 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/BasePropertyGeneratorTest.cs @@ -0,0 +1,69 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using NUnit.Framework; +using osu.Game.Rulesets.Karaoke.Edit.Generator; + +namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator; + +public abstract class BasePropertyGeneratorTest + : BasePropertyGeneratorTest + where TGenerator : PropertyGenerator + where TConfig : IHasConfig, new() +{ + protected static TConfig GeneratorConfig(Action? action = null) + { + var config = new TConfig(); + action?.Invoke(config); + return config; + } + + protected static TConfig GeneratorDefaultConfig(Action? action = null) + { + var config = new TConfig().CreateDefaultConfig(); + action?.Invoke(config); + return config; + } + + protected static TGenerator GenerateGenerator(TConfig config) + { + if (Activator.CreateInstance(typeof(TGenerator), config) is not TGenerator generator) + throw new ArgumentNullException(nameof(generator)); + + return generator; + } + + protected static void CheckCanGenerate(TItem item, bool canGenerate, TConfig config) + { + var generator = GenerateGenerator(config); + + CheckCanGenerate(item, canGenerate, generator); + } + + protected void CheckGenerateResult(TItem item, TProperty expected, TConfig config) + { + var generator = GenerateGenerator(config); + + CheckGenerateResult(item, expected, generator); + } +} + +public abstract class BasePropertyGeneratorTest + where TGenerator : PropertyGenerator +{ + protected static void CheckCanGenerate(TItem item, bool canGenerate, TGenerator generator) + { + bool actual = generator.CanGenerate(item); + Assert.AreEqual(canGenerate, actual); + } + + protected void CheckGenerateResult(TItem item, TProperty expected, TGenerator generator) + { + // create time tag and actually time tag. + var actual = generator.Generate(item); + AssertEqual(expected, actual); + } + + protected abstract void AssertEqual(TProperty expected, TProperty actual); +} diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapDetectorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapDetectorTest.cs index 7eace9cd4..de124c2b1 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapDetectorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapDetectorTest.cs @@ -1,8 +1,6 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Beatmaps; using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps; @@ -10,44 +8,9 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator.Beatmaps { public abstract class BaseBeatmapDetectorTest - : BaseGeneratorTest - where TDetector : class, IBeatmapPropertyDetector where TConfig : IHasConfig, new() + : BasePropertyDetectorTest + where TDetector : BeatmapPropertyDetector + where TConfig : IHasConfig, new() { - protected static TDetector GenerateDetector(TConfig config) - { - if (Activator.CreateInstance(typeof(TDetector), config) is not TDetector detector) - throw new ArgumentNullException(nameof(detector)); - - return detector; - } - - protected static void CheckCanDetect(KaraokeBeatmap beatmap, bool canDetect, TConfig config) - { - var detector = GenerateDetector(config); - - CheckCanDetect(beatmap, canDetect, detector); - } - - protected static void CheckCanDetect(KaraokeBeatmap beatmap, bool canDetect, TDetector detector) - { - bool actual = detector.CanDetect(beatmap); - Assert.AreEqual(canDetect, actual); - } - - protected void CheckDetectResult(KaraokeBeatmap beatmap, TObject expected, TConfig config) - { - var detector = GenerateDetector(config); - - CheckDetectResult(beatmap, expected, detector); - } - - protected void CheckDetectResult(KaraokeBeatmap beatmap, TObject expected, TDetector detector) - { - // create time tag and actually time tag. - var actual = detector.Detect(beatmap); - AssertEqual(expected, actual); - } - - protected abstract void AssertEqual(TObject expected, TObject actual); } } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapGeneratorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapGeneratorTest.cs index e4a7cd96e..826a2cfb3 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapGeneratorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/BaseBeatmapGeneratorTest.cs @@ -1,8 +1,6 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Beatmaps; using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps; @@ -10,44 +8,9 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator.Beatmaps { public abstract class BaseBeatmapGeneratorTest - : BaseGeneratorTest - where TGenerator : class, IBeatmapPropertyGenerator where TConfig : IHasConfig, new() + : BasePropertyGeneratorTest + where TGenerator : BeatmapPropertyGenerator + where TConfig : IHasConfig, new() { - protected static TGenerator GenerateGenerator(TConfig config) - { - if (Activator.CreateInstance(typeof(TGenerator), config) is not TGenerator generator) - throw new ArgumentNullException(nameof(generator)); - - return generator; - } - - protected static void CheckCanGenerate(KaraokeBeatmap beatmap, bool canGenerate, TConfig config) - { - var generator = GenerateGenerator(config); - - CheckCanGenerate(beatmap, canGenerate, generator); - } - - protected static void CheckCanGenerate(KaraokeBeatmap beatmap, bool canGenerate, TGenerator generator) - { - bool actual = generator.CanGenerate(beatmap); - Assert.AreEqual(canGenerate, actual); - } - - protected void CheckGenerateResult(KaraokeBeatmap beatmap, TObject expected, TConfig config) - { - var generator = GenerateGenerator(config); - - CheckGenerateResult(beatmap, expected, generator); - } - - protected void CheckGenerateResult(KaraokeBeatmap beatmap, TObject expected, TGenerator generator) - { - // create time tag and actually time tag. - var actual = generator.Generate(beatmap); - AssertEqual(expected, actual); - } - - protected abstract void AssertEqual(TObject expected, TObject actual); } } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/Pages/PageGeneratorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/Pages/PageGeneratorTest.cs index efc0da9f3..87a09c215 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/Pages/PageGeneratorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Beatmaps/Pages/PageGeneratorTest.cs @@ -23,6 +23,7 @@ public class PageGeneratorTest : BaseBeatmapGeneratorTest() - }; - - var expectedPages = Array.Empty(); - - CheckGenerateResult(beatmap, expectedPages, config); - } - [TestCase("[1000,3000]:karaoke", new double[] { 1000, 3000 })] [TestCase("[1000,23000]:karaoke", new[] { 1000, 1000 + max_interval, 1000 + max_interval * 2, 23000 })] public void TestGenerateWithSingleLyric(string lyric, double[] expectedTimes) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricDetectorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricDetectorTest.cs index 8949b36cc..6afb14ef3 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricDetectorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricDetectorTest.cs @@ -1,8 +1,6 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; using osu.Game.Rulesets.Karaoke.Objects; @@ -10,44 +8,9 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator.Lyrics { public abstract class BaseLyricDetectorTest - : BaseGeneratorTest - where TDetector : class, ILyricPropertyDetector where TConfig : IHasConfig, new() + : BasePropertyDetectorTest + where TDetector : LyricPropertyDetector + where TConfig : IHasConfig, new() { - protected static TDetector GenerateDetector(TConfig config) - { - if (Activator.CreateInstance(typeof(TDetector), config) is not TDetector detector) - throw new ArgumentNullException(nameof(detector)); - - return detector; - } - - protected static void CheckCanDetect(Lyric lyric, bool canDetect, TConfig config) - { - var detector = GenerateDetector(config); - - CheckCanDetect(lyric, canDetect, detector); - } - - protected static void CheckCanDetect(Lyric lyric, bool canDetect, TDetector detector) - { - bool actual = detector.CanDetect(lyric); - Assert.AreEqual(canDetect, actual); - } - - protected void CheckDetectResult(Lyric lyric, TObject expected, TConfig config) - { - var detector = GenerateDetector(config); - - CheckDetectResult(lyric, expected, detector); - } - - protected void CheckDetectResult(Lyric lyric, TObject expected, TDetector detector) - { - // create time tag and actually time tag. - var actual = detector.Detect(lyric); - AssertEqual(expected, actual); - } - - protected abstract void AssertEqual(TObject expected, TObject actual); } } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorSelectorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorSelectorTest.cs index 762332e7f..b9374fd9f 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorSelectorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorSelectorTest.cs @@ -3,10 +3,14 @@ using System; using osu.Game.Rulesets.Karaoke.Configuration; +using osu.Game.Rulesets.Karaoke.Edit.Generator; +using osu.Game.Rulesets.Karaoke.Objects; namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator.Lyrics { - public abstract class BaseLyricGeneratorSelectorTest where TSelector : class + public abstract class BaseLyricGeneratorSelectorTest + : BasePropertyGeneratorTest + where TSelector : PropertyGenerator { protected TSelector CreateSelector() { diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorTest.cs index 2323e109c..007da00fe 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/BaseLyricGeneratorTest.cs @@ -1,8 +1,6 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using System; -using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; using osu.Game.Rulesets.Karaoke.Objects; @@ -10,44 +8,9 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator.Lyrics { public abstract class BaseLyricGeneratorTest - : BaseGeneratorTest - where TGenerator : class, ILyricPropertyGenerator where TConfig : IHasConfig, new() + : BasePropertyGeneratorTest + where TGenerator : LyricPropertyGenerator + where TConfig : IHasConfig, new() { - protected static TGenerator GenerateGenerator(TConfig config) - { - if (Activator.CreateInstance(typeof(TGenerator), config) is not TGenerator generator) - throw new ArgumentNullException(nameof(generator)); - - return generator; - } - - protected static void CheckCanGenerate(Lyric lyric, bool canGenerate, TConfig config) - { - var generator = GenerateGenerator(config); - - CheckCanGenerate(lyric, canGenerate, generator); - } - - protected static void CheckCanGenerate(Lyric lyric, bool canGenerate, TGenerator generator) - { - bool actual = generator.CanGenerate(lyric); - Assert.AreEqual(canGenerate, actual); - } - - protected void CheckGenerateResult(Lyric lyric, TObject expected, TConfig config) - { - var generator = GenerateGenerator(config); - - CheckGenerateResult(lyric, expected, generator); - } - - protected void CheckGenerateResult(Lyric lyric, TObject expected, TGenerator generator) - { - // create time tag and actually time tag. - var actual = generator.Generate(lyric); - AssertEqual(expected, actual); - } - - protected abstract void AssertEqual(TObject expected, TObject actual); } } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/Notes/NoteGeneratorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/Notes/NoteGeneratorTest.cs index fd1c15e6e..ba0f64949 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/Notes/NoteGeneratorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/Notes/NoteGeneratorTest.cs @@ -16,7 +16,8 @@ public class NoteGeneratorTest : BaseLyricGeneratorTest + public class RomajiTagGeneratorSelectorTest : BaseLyricGeneratorSelectorTest { + [TestCase(17, "花火大会", true)] + [TestCase(17, "我是中文", true)] // only change the language code to decide should be able to generate or not. + [TestCase(17, "", false)] // will not able to generate the romaji if lyric is empty. + [TestCase(17, " ", false)] + [TestCase(17, null, false)] + [TestCase(1028, "はなび", false)] // Should not be able to generate if language is not supported. + public void TestCanGenerate(int lcid, string text, bool canGenerate) + { + var selector = CreateSelector(); + var lyric = new Lyric + { + Language = new CultureInfo(lcid), + Text = text, + }; + + CheckCanGenerate(lyric, canGenerate, selector); + } + [TestCase(17, "花火大会", new[] { "[0,2]:hanabi", "[2,4]:taikai" })] // Japanese [TestCase(1041, "はなび", new[] { "[0,3]:hanabi" })] // Japanese - [TestCase(1028, "はなび", new string[] { })] // Chinese(should not supported) public void TestGenerate(int lcid, string text, string[] expectedRomajies) { var selector = CreateSelector(); @@ -25,7 +42,11 @@ public void TestGenerate(int lcid, string text, string[] expectedRomajies) }; var expected = TestCaseTagHelper.ParseRomajiTags(expectedRomajies); - var actual = selector.Generate(lyric); + CheckGenerateResult(lyric, expected, selector); + } + + protected override void AssertEqual(RomajiTag[] expected, RomajiTag[] actual) + { TextTagAssert.ArePropertyEqual(expected, actual); } } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/RubyTags/RubyTagGeneratorSelectorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/RubyTags/RubyTagGeneratorSelectorTest.cs index dbf6cbbe9..fc06e222f 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/RubyTags/RubyTagGeneratorSelectorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/RubyTags/RubyTagGeneratorSelectorTest.cs @@ -10,11 +10,28 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator.Lyrics.RubyTags { - public class RubyTagGeneratorSelectorTest : BaseLyricGeneratorSelectorTest + public class RubyTagGeneratorSelectorTest : BaseLyricGeneratorSelectorTest { + [TestCase(17, "花火大会", true)] + [TestCase(17, "我是中文", true)] // only change the language code to decide should be able to generate or not. + [TestCase(17, "", false)] // will not able to generate the romaji if lyric is empty. + [TestCase(17, " ", false)] + [TestCase(17, null, false)] + [TestCase(1028, "はなび", false)] // Should not be able to generate if language is not supported. + public void TestCanGenerate(int lcid, string text, bool canGenerate) + { + var selector = CreateSelector(); + var lyric = new Lyric + { + Language = new CultureInfo(lcid), + Text = text, + }; + + CheckCanGenerate(lyric, canGenerate, selector); + } + [TestCase(17, "花火大会", new[] { "[0,2]:はなび", "[2,4]:たいかい" })] // Japanese [TestCase(1041, "はなび", new string[] { })] // Japanese - [TestCase(1028, "はなび", new string[] { })] // Chinese(should not supported) public void TestGenerate(int lcid, string text, string[] expectedRubies) { var selector = CreateSelector(); @@ -25,7 +42,11 @@ public void TestGenerate(int lcid, string text, string[] expectedRubies) }; var expected = TestCaseTagHelper.ParseRubyTags(expectedRubies); - var actual = selector.Generate(lyric); + CheckGenerateResult(lyric, expected, selector); + } + + protected override void AssertEqual(RubyTag[] expected, RubyTag[] actual) + { TextTagAssert.ArePropertyEqual(expected, actual); } } diff --git a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/TimeTagGeneratorSelectorTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/TimeTagGeneratorSelectorTest.cs index daab60a2f..2fa9ae403 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/TimeTagGeneratorSelectorTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Editor/Generator/Lyrics/TimeTags/TimeTagGeneratorSelectorTest.cs @@ -10,12 +10,29 @@ namespace osu.Game.Rulesets.Karaoke.Tests.Editor.Generator.Lyrics.TimeTags { - public class TimeTagGeneratorSelectorTest : BaseLyricGeneratorSelectorTest + public class TimeTagGeneratorSelectorTest : BaseLyricGeneratorSelectorTest { + [TestCase(17, "花火大会", true)] + [TestCase(1028, "喵", true)] // Support the chinese. + [TestCase(3081, "hello", false)] // English is not supported. + [TestCase(17, "", false)] // will not able to generate the romaji if lyric is empty. + [TestCase(17, " ", false)] + [TestCase(17, null, false)] + public void TestCanGenerate(int lcid, string text, bool canGenerate) + { + var selector = CreateSelector(); + var lyric = new Lyric + { + Language = new CultureInfo(lcid), + Text = text, + }; + + CheckCanGenerate(lyric, canGenerate, selector); + } + [TestCase(17, "か", new[] { "[0,start]:", "[0,end]:" })] // Japanese [TestCase(1041, "か", new[] { "[0,start]:", "[0,end]:" })] // Japanese [TestCase(1028, "喵", new[] { "[0,start]:" })] // Chinese - [TestCase(3081, "hello", new string[] { })] // English public void TestGenerate(int lcid, string text, string[] expectedTimeTags) { var selector = CreateSelector(); @@ -26,7 +43,11 @@ public void TestGenerate(int lcid, string text, string[] expectedTimeTags) }; var expected = TestCaseTagHelper.ParseTimeTags(expectedTimeTags); - var actual = selector.Generate(lyric); + CheckGenerateResult(lyric, expected, selector); + } + + protected override void AssertEqual(TimeTag[] expected, TimeTag[] actual) + { TimeTagAssert.ArePropertyEqual(expected, actual); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs index 8fffcd20f..e00fb4630 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/ChangeHandlers/Lyrics/LyricAutoGenerateChangeHandler.cs @@ -9,7 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Configuration; -using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics; +using osu.Game.Rulesets.Karaoke.Edit.Generator; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric; @@ -69,10 +69,10 @@ public bool CanGenerate(LyricAutoGenerateProperty autoGenerateProperty) throw new ArgumentOutOfRangeException(nameof(autoGenerateProperty)); } - bool canDetect(ILyricPropertyDetector detector) + bool canDetect(PropertyDetector detector) => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(detector.CanDetect); - bool canGenerate(ILyricPropertyGenerator generator) + bool canGenerate(PropertyGenerator generator) => HitObjects.Where(x => !IsWritePropertyLocked(x)).Any(generator.CanGenerate); } @@ -110,12 +110,12 @@ public IDictionary GetNotGeneratableLyrics(LyricAutoGe throw new ArgumentOutOfRangeException(nameof(autoGenerateProperty)); } - IDictionary getInvalidMessageFromDetector(ILyricPropertyDetector detector) + IDictionary getInvalidMessageFromDetector(PropertyDetector detector) => HitObjects.Select(x => new KeyValuePair(x, detector.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) .Where(x => x.Value != null) .ToDictionary(k => k.Key, v => v.Value!.Value); - IDictionary getInvalidMessageFromGenerator(ILyricPropertyGenerator generator) + IDictionary getInvalidMessageFromGenerator(PropertyGenerator generator) => HitObjects.Select(x => new KeyValuePair(x, generator.GetInvalidMessage(x) ?? getReferenceLyricInvalidMessage(x))) .Where(x => x.Value != null) .ToDictionary(k => k.Key, v => v.Value!.Value); @@ -196,40 +196,40 @@ public void AutoGenerate(LyricAutoGenerateProperty autoGenerateProperty) } } - private ILyricPropertyDetector createLyricDetector() + private PropertyDetector createLyricDetector() { switch (typeof(T)) { case Type t when t == typeof(Lyric): var lyrics = beatmap.HitObjects.OfType().ToArray(); var referenceLyricDetectorConfig = generatorConfigManager.Get(KaraokeRulesetEditGeneratorSetting.ReferenceLyricDetectorConfig); - return (ILyricPropertyDetector)new ReferenceLyricDetector(lyrics, referenceLyricDetectorConfig); + return (PropertyDetector)(object)new ReferenceLyricDetector(lyrics, referenceLyricDetectorConfig); case Type t when t == typeof(CultureInfo): var languageDetectorConfig = generatorConfigManager.Get(KaraokeRulesetEditGeneratorSetting.LanguageDetectorConfig); - return (ILyricPropertyDetector)new LanguageDetector(languageDetectorConfig); + return (PropertyDetector)(object)new LanguageDetector(languageDetectorConfig); default: throw new NotSupportedException(); } } - private ILyricPropertyGenerator createLyricGenerator() + private PropertyGenerator createLyricGenerator() { - switch (typeof(T)) + switch (typeof(TProperty)) { case Type t when t == typeof(RubyTag[]): - return (ILyricPropertyGenerator)new RubyTagGeneratorSelector(generatorConfigManager); + return (PropertyGenerator)(object)new RubyTagGeneratorSelector(generatorConfigManager); case Type t when t == typeof(RomajiTag[]): - return (ILyricPropertyGenerator)new RomajiTagGeneratorSelector(generatorConfigManager); + return (PropertyGenerator)(object)new RomajiTagGeneratorSelector(generatorConfigManager); case Type t when t == typeof(TimeTag[]): - return (ILyricPropertyGenerator)new TimeTagGeneratorSelector(generatorConfigManager); + return (PropertyGenerator)(object)new TimeTagGeneratorSelector(generatorConfigManager); case Type t when t == typeof(Note[]): var config = generatorConfigManager.Get(KaraokeRulesetEditGeneratorSetting.NoteGeneratorConfig); - return (ILyricPropertyGenerator)new NoteGenerator(config); + return (PropertyGenerator)(object)new NoteGenerator(config); default: throw new NotSupportedException(); diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyDetector.cs new file mode 100644 index 000000000..c5a0c1034 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyDetector.cs @@ -0,0 +1,21 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Karaoke.Beatmaps; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps +{ + /// + /// Base interface of the detector. + /// + /// + /// + public abstract class BeatmapPropertyDetector : PropertyDetector + where TConfig : IHasConfig, new() + { + protected BeatmapPropertyDetector(TConfig config) + : base(config) + { + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyGenerator.cs new file mode 100644 index 000000000..426b4ffb7 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/BeatmapPropertyGenerator.cs @@ -0,0 +1,21 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Karaoke.Beatmaps; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps +{ + /// + /// Base interface of the auto-generator. + /// + /// + /// + public abstract class BeatmapPropertyGenerator : PropertyGenerator + where TConfig : IHasConfig, new() + { + protected BeatmapPropertyGenerator(TConfig config) + : base(config) + { + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/IBeatmapPropertyDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/IBeatmapPropertyDetector.cs deleted file mode 100644 index 2ee5e1ad9..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/IBeatmapPropertyDetector.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Localisation; -using osu.Game.Rulesets.Karaoke.Beatmaps; - -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps -{ - /// - /// Base interface of the detector. - /// - /// - public interface IBeatmapPropertyDetector - { - /// - /// Determined if detect property from is supported. - /// - /// - /// - bool CanDetect(KaraokeBeatmap beatmap) => GetInvalidMessage(beatmap) == null; - - /// - /// Will get the invalid message if beatmap property is not able to be detected. - /// - /// - /// - LocalisableString? GetInvalidMessage(KaraokeBeatmap beatmap); - - /// - /// Detect the property from the beatmap. - /// - /// - /// - T Detect(KaraokeBeatmap beatmap); - } -} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/IBeatmapPropertyGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/IBeatmapPropertyGenerator.cs deleted file mode 100644 index 8581a5613..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/IBeatmapPropertyGenerator.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Localisation; -using osu.Game.Rulesets.Karaoke.Beatmaps; - -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps -{ - /// - /// Base interface of the auto-generator. - /// - /// - public interface IBeatmapPropertyGenerator - { - /// - /// Determined if detect property from is supported. - /// - /// - /// - bool CanGenerate(KaraokeBeatmap beatmap) => GetInvalidMessage(beatmap) == null; - - /// - /// Will get the invalid message if beatmap property is not able to be generated. - /// - /// - /// - LocalisableString? GetInvalidMessage(KaraokeBeatmap beatmap); - - /// - /// Generate the property from the beatmap. - /// - /// - /// - T Generate(KaraokeBeatmap beatmap); - } -} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/Pages/PageGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/Pages/PageGenerator.cs index 459fd79ea..45e78e6f6 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/Pages/PageGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Beatmaps/Pages/PageGenerator.cs @@ -15,23 +15,21 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Beatmaps.Pages; -public class PageGenerator : IBeatmapPropertyGenerator +public class PageGenerator : BeatmapPropertyGenerator { - protected PageGeneratorConfig Config { get; } - public PageGenerator(PageGeneratorConfig config) + : base(config) { - Config = config; } - public LocalisableString? GetInvalidMessage(KaraokeBeatmap beatmap) + protected override LocalisableString? GetInvalidMessageFromItem(KaraokeBeatmap item) { - var lyrics = beatmap.HitObjects.OfType().ToArray(); + var lyrics = item.HitObjects.OfType().ToArray(); if (lyrics.Length < 1) return "There's not lyric in the beatmap."; var timeTagChecker = new CheckLyricTimeTag(); - var invalidIssues = timeTagChecker.Run(getContext(beatmap)); + var invalidIssues = timeTagChecker.Run(getContext(item)); if (invalidIssues.Any()) return "Should not have any time-tag related issues"; @@ -41,13 +39,13 @@ public PageGenerator(PageGeneratorConfig config) private static BeatmapVerifierContext getContext(IBeatmap beatmap) => new(beatmap, new TestWorkingBeatmap(beatmap)); - public Page[] Generate(KaraokeBeatmap beatmap) + protected override Page[] GenerateFromItem(KaraokeBeatmap item) { if (Config.MinTime < CheckBeatmapPageInfo.MIN_INTERVAL || Config.MaxTime > CheckBeatmapPageInfo.MAX_INTERVAL) throw new InvalidOperationException("Inverval time should be validate."); - var existPages = Config.ClearExistPages ? Array.Empty() : beatmap.PageInfo.SortedPages.ToArray(); - var lyricTimingInfos = beatmap.HitObjects.OfType().Select(x => new LyricTimingInfo + var existPages = Config.ClearExistPages ? Array.Empty() : item.PageInfo.SortedPages.ToArray(); + var lyricTimingInfos = item.HitObjects.OfType().Select(x => new LyricTimingInfo { StartTime = x.LyricStartTime, EndTime = x.EndTime, diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ILyricPropertyDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ILyricPropertyDetector.cs deleted file mode 100644 index 126b4a8db..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ILyricPropertyDetector.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Localisation; -using osu.Game.Rulesets.Karaoke.Objects; - -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics -{ - /// - /// Base interface of the detector. - /// - /// - public interface ILyricPropertyDetector - { - /// - /// Determined if detect property from lyric is supported. - /// - /// - /// - bool CanDetect(Lyric lyric) => GetInvalidMessage(lyric) == null; - - /// - /// Will get the invalid message if lyric property is not able to be detected. - /// - /// - /// - LocalisableString? GetInvalidMessage(Lyric lyric); - - /// - /// Detect the property from the lyric. - /// - /// - /// - T Detect(Lyric lyric); - } -} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ILyricPropertyGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ILyricPropertyGenerator.cs deleted file mode 100644 index abe938c1c..000000000 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ILyricPropertyGenerator.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) andy840119 . Licensed under the GPL Licence. -// See the LICENCE file in the repository root for full licence text. - -using osu.Framework.Localisation; -using osu.Game.Rulesets.Karaoke.Objects; - -namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics -{ - /// - /// Base interface of the auto-generator. - /// - /// - public interface ILyricPropertyGenerator - { - /// - /// Determined if generate property from lyric is supported. - /// - /// - /// - bool CanGenerate(Lyric lyric) => GetInvalidMessage(lyric) == null; - - /// - /// Will get the invalid message if lyric property is not able to be generated. - /// - /// - /// - LocalisableString? GetInvalidMessage(Lyric lyric); - - /// - /// Generate the property from the lyric. - /// - /// - /// - T Generate(Lyric lyric); - } -} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs index 7bf4a937c..8b44037d1 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Language/LanguageDetector.cs @@ -8,11 +8,12 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Language { - public class LanguageDetector : ILyricPropertyDetector + public class LanguageDetector : LyricPropertyDetector { private readonly LanguageDetection.LanguageDetector detector = new(); public LanguageDetector(LanguageDetectorConfig config) + : base(config) { var targetLanguages = config.AcceptLanguages.Where(x => x != null).ToList(); @@ -26,17 +27,17 @@ public LanguageDetector(LanguageDetectorConfig config) } } - public LocalisableString? GetInvalidMessage(Lyric lyric) + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) { - if (string.IsNullOrWhiteSpace(lyric.Text)) + if (string.IsNullOrWhiteSpace(item.Text)) return "Lyric should not be empty."; return null; } - public CultureInfo? Detect(Lyric lyric) + protected override CultureInfo? DetectFromItem(Lyric item) { - var result = detector.DetectAll(lyric.Text); + var result = detector.DetectAll(item.Text); string? languageCode = result.FirstOrDefault()?.Language; return languageCode == null ? null : new CultureInfo(languageCode); diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs index 25b19200d..44288ea44 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricGeneratorSelector.cs @@ -4,16 +4,15 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.Linq; using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Configuration; using osu.Game.Rulesets.Karaoke.Objects; namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics { - public abstract class LyricGeneratorSelector : ILyricPropertyGenerator + public abstract class LyricGeneratorSelector : PropertyGenerator { - protected Dictionary>> Generator { get; } = new(); + private Dictionary>> generator { get; } = new(); private readonly KaraokeRulesetEditGeneratorConfigManager generatorConfigManager; @@ -22,13 +21,15 @@ protected LyricGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager genera this.generatorConfigManager = generatorConfigManager; } - protected void RegisterGenerator(CultureInfo info) where TGenerator : ILyricPropertyGenerator where TConfig : TBaseConfig, new() + protected void RegisterGenerator(CultureInfo info) + where TGenerator : LyricPropertyGenerator + where TConfig : TBaseConfig, IHasConfig, new() { - Generator.Add(info, new Lazy>(() => + generator.Add(info, new Lazy>(() => { var generatorSetting = GetGeneratorConfigSetting(info); var config = generatorConfigManager.Get(generatorSetting); - if (Activator.CreateInstance(typeof(TGenerator), config) is not ILyricPropertyGenerator generator) + if (Activator.CreateInstance(typeof(TGenerator), config) is not PropertyGenerator generator) throw new InvalidCastException(); return generator; @@ -37,18 +38,29 @@ protected LyricGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager genera protected abstract KaraokeRulesetEditGeneratorSetting GetGeneratorConfigSetting(CultureInfo info); - public LocalisableString? GetInvalidMessage(Lyric lyric) + protected override TProperty GenerateFromItem(Lyric item) { - if (lyric.Language == null) + if (item.Language == null) + throw new NotGeneratableException(); + + if (!this.generator.TryGetValue(item.Language, out var generator)) + throw new NotGeneratableException(); + + return generator.Value.Generate(item); + } + + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) + { + if (item.Language == null) return "Oops, language is missing."; - var generator = Generator.FirstOrDefault(g => EqualityComparer.Default.Equals(g.Key, lyric.Language)); - if (generator.Key == null) + if (string.IsNullOrWhiteSpace(item.Text)) + return "Should have the text in the lyric"; + + if (!this.generator.TryGetValue(item.Language, out var generator)) return "Sorry, the language of lyric is not supported yet."; - return generator.Value.Value.GetInvalidMessage(lyric); + return generator.Value.GetInvalidMessage(item); } - - public abstract TProperty Generate(Lyric lyric); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyDetector.cs new file mode 100644 index 000000000..f5eb9226b --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyDetector.cs @@ -0,0 +1,21 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Karaoke.Objects; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics +{ + /// + /// Base interface of the detector. + /// + /// + /// + public abstract class LyricPropertyDetector : PropertyDetector + where TConfig : IHasConfig, new() + { + protected LyricPropertyDetector(TConfig config) + : base(config) + { + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyGenerator.cs new file mode 100644 index 000000000..98bb1df62 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/LyricPropertyGenerator.cs @@ -0,0 +1,21 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Game.Rulesets.Karaoke.Objects; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics +{ + /// + /// Base interface of the auto-generator. + /// + /// + /// + public abstract class LyricPropertyGenerator : PropertyGenerator + where TConfig : IHasConfig, new() + { + protected LyricPropertyGenerator(TConfig config) + : base(config) + { + } + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs index ead98a6d0..0fe557648 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/Notes/NoteGenerator.cs @@ -11,20 +11,18 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.Notes { - public class NoteGenerator : ILyricPropertyGenerator + public class NoteGenerator : LyricPropertyGenerator { - protected NoteGeneratorConfig Config { get; } - public NoteGenerator(NoteGeneratorConfig config) + : base(config) { - Config = config; } - public LocalisableString? GetInvalidMessage(Lyric lyric) + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) { - var timeTags = lyric.TimeTags; + var timeTags = item.TimeTags; - if (lyric.TimeTags.Count < 2) + if (item.TimeTags.Count < 2) return "Sorry, lyric must have at least two time-tags."; if (timeTags.Any(x => x.Time == null)) @@ -33,9 +31,9 @@ public NoteGenerator(NoteGeneratorConfig config) return null; } - public Note[] Generate(Lyric lyric) + protected override Note[] GenerateFromItem(Lyric item) { - var timeTags = TimeTagsUtils.ToTimeBasedDictionary(lyric.TimeTags); + var timeTags = TimeTagsUtils.ToTimeBasedDictionary(item.TimeTags); var notes = new List(); foreach (var timeTag in timeTags) @@ -55,8 +53,8 @@ public Note[] Generate(Lyric lyric) continue; int timeTagIndex = timeTags.IndexOf(timeTag); - string text = lyric.Text[startIndex..endIndex]; - string? ruby = lyric.RubyTags?.Where(x => x.StartIndex == startIndex && x.EndIndex == endIndex).FirstOrDefault()?.Text; + string text = item.Text[startIndex..endIndex]; + string? ruby = item.RubyTags?.Where(x => x.StartIndex == startIndex && x.EndIndex == endIndex).FirstOrDefault()?.Text; if (!string.IsNullOrEmpty(text)) { @@ -64,7 +62,7 @@ public Note[] Generate(Lyric lyric) { Text = text, RubyText = ruby, - ReferenceLyric = lyric, + ReferenceLyric = item, ReferenceTimeTagIndex = timeTagIndex }); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs index 770dd8451..9fa3f94b4 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/ReferenceLyric/ReferenceLyricDetector.cs @@ -10,34 +10,33 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.ReferenceLyric { - public class ReferenceLyricDetector : ILyricPropertyDetector + public class ReferenceLyricDetector : LyricPropertyDetector { private readonly Lyric[] lyrics; - private readonly ReferenceLyricDetectorConfig config; public ReferenceLyricDetector(IEnumerable lyrics, ReferenceLyricDetectorConfig config) + : base(config) { this.lyrics = lyrics.ToArray(); - this.config = config; } - public LocalisableString? GetInvalidMessage(Lyric lyric) + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) { - var referencedLyric = getReferenceLyric(lyric); + var referencedLyric = getReferenceLyric(item); if (referencedLyric == null) return "There's no matched lyric."; return null; } - public Lyric? Detect(Lyric lyric) + protected override Lyric? DetectFromItem(Lyric item) { - var referencedLyric = getReferenceLyric(lyric); + var referencedLyric = getReferenceLyric(item); if (referencedLyric == null) return null; // prevent first lyric(referenced lyric) reference by other lyric. - if (referencedLyric.Order > lyric.Order) + if (referencedLyric.Order > item.Order) return null; return referencedLyric; @@ -59,7 +58,7 @@ private bool canBeReferenced(Lyric lyric, Lyric referencedLyric) if (lyricText == referencedLyricText) return true; - if (!config.IgnorePrefixAndPostfixSymbol) + if (!Config.IgnorePrefixAndPostfixSymbol) return false; // check if contains intersect part between two lyrics. diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs index 9542da174..0c9b36736 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/Ja/JaRomajiTagGenerator.cs @@ -7,6 +7,7 @@ using Lucene.Net.Analysis.Ja; using Lucene.Net.Analysis.TokenAttributes; using osu.Framework.Extensions.IEnumerableExtensions; +using osu.Framework.Localisation; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; @@ -26,9 +27,9 @@ public JaRomajiTagGenerator(JaRomajiTagGeneratorConfig config) }); } - public override RomajiTag[] Generate(Lyric lyric) + protected override RomajiTag[] GenerateFromItem(Lyric item) { - string text = lyric.Text; + string text = item.Text; var processingTags = new List(); // Tokenize the text diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs index f7d3f43e8..703dcb60c 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGenerator.cs @@ -6,23 +6,20 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags { - public abstract class RomajiTagGenerator : ILyricPropertyGenerator where T : RomajiTagGeneratorConfig + public abstract class RomajiTagGenerator : LyricPropertyGenerator + where TConfig : RomajiTagGeneratorConfig, IHasConfig, new() { - protected T Config { get; } - - protected RomajiTagGenerator(T config) + protected RomajiTagGenerator(TConfig config) + : base(config) { - Config = config; } - public LocalisableString? GetInvalidMessage(Lyric lyric) + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) { - if (string.IsNullOrWhiteSpace(lyric.Text)) + if (string.IsNullOrWhiteSpace(item.Text)) return "Lyric should not be empty."; return null; } - - public abstract RomajiTag[] Generate(Lyric lyric); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs index afc5a74b9..fff752fc6 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RomajiTags/RomajiTagGeneratorSelector.cs @@ -1,7 +1,6 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Globalization; using osu.Game.Rulesets.Karaoke.Configuration; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RomajiTags.Ja; @@ -18,20 +17,6 @@ public RomajiTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager gener RegisterGenerator(new CultureInfo(1041)); } - public override RomajiTag[] Generate(Lyric lyric) - { - if (lyric.Language == null) - return Array.Empty(); - - if (string.IsNullOrEmpty(lyric.Text)) - return Array.Empty(); - - if (!Generator.TryGetValue(lyric.Language, out var generator)) - return Array.Empty(); - - return generator.Value.Generate(lyric); - } - protected override KaraokeRulesetEditGeneratorSetting GetGeneratorConfigSetting(CultureInfo info) => KaraokeRulesetEditGeneratorSetting.JaRomajiTagGeneratorConfig; } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs index 8e7bf8514..b7adea128 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/Ja/JaRubyTagGenerator.cs @@ -25,9 +25,9 @@ public JaRubyTagGenerator(JaRubyTagGeneratorConfig config) }); } - public override RubyTag[] Generate(Lyric lyric) + protected override RubyTag[] GenerateFromItem(Lyric item) { - string text = lyric.Text; + string text = item.Text; var tags = new List(); // Tokenize the text diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs index cd02c76fa..e09985ac4 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGenerator.cs @@ -6,23 +6,20 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags { - public abstract class RubyTagGenerator : ILyricPropertyGenerator where T : RubyTagGeneratorConfig + public abstract class RubyTagGenerator : LyricPropertyGenerator + where TConfig : RubyTagGeneratorConfig, IHasConfig, new() { - protected T Config { get; } - - protected RubyTagGenerator(T config) + protected RubyTagGenerator(TConfig config) + : base(config) { - Config = config; } - public LocalisableString? GetInvalidMessage(Lyric lyric) + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) { - if (string.IsNullOrWhiteSpace(lyric.Text)) + if (string.IsNullOrWhiteSpace(item.Text)) return "Lyric should not be empty."; return null; } - - public abstract RubyTag[] Generate(Lyric lyric); } } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs index ccf9931a8..92681a3d3 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/RubyTags/RubyTagGeneratorSelector.cs @@ -1,7 +1,6 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. -using System; using System.Globalization; using osu.Game.Rulesets.Karaoke.Configuration; using osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.RubyTags.Ja; @@ -18,20 +17,6 @@ public RubyTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generat RegisterGenerator(new CultureInfo(1041)); } - public override RubyTag[] Generate(Lyric lyric) - { - if (lyric.Language == null) - return Array.Empty(); - - if (string.IsNullOrEmpty(lyric.Text)) - return Array.Empty(); - - if (!Generator.TryGetValue(lyric.Language, out var generator)) - return Array.Empty(); - - return generator.Value.Generate(lyric); - } - protected override KaraokeRulesetEditGeneratorSetting GetGeneratorConfigSetting(CultureInfo info) => KaraokeRulesetEditGeneratorSetting.JaRubyTagGeneratorConfig; } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs index 3fd2f8d59..99afd1483 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGenerator.cs @@ -9,27 +9,26 @@ namespace osu.Game.Rulesets.Karaoke.Edit.Generator.Lyrics.TimeTags { - public abstract class TimeTagGenerator : ILyricPropertyGenerator where T : TimeTagGeneratorConfig + public abstract class TimeTagGenerator : LyricPropertyGenerator + where TConfig : TimeTagGeneratorConfig, IHasConfig, new() { - protected T Config { get; } - - protected TimeTagGenerator(T config) + protected TimeTagGenerator(TConfig config) + : base(config) { - Config = config; } - public LocalisableString? GetInvalidMessage(Lyric lyric) + protected override LocalisableString? GetInvalidMessageFromItem(Lyric item) { - if (string.IsNullOrEmpty(lyric.Text)) + if (string.IsNullOrEmpty(item.Text)) return "Lyric should not be empty."; return null; } - public virtual TimeTag[] Generate(Lyric lyric) + protected sealed override TimeTag[] GenerateFromItem(Lyric item) { var timeTags = new List(); - string text = lyric.Text; + string text = item.Text; if (string.IsNullOrEmpty(text)) return timeTags.ToArray(); @@ -48,7 +47,7 @@ public virtual TimeTag[] Generate(Lyric lyric) if (Config.CheckLineEndKeyUp) timeTags.Add(new TimeTag(new TextIndex(text.Length - 1, TextIndex.IndexState.End))); - TimeTagLogic(lyric, timeTags); + TimeTagLogic(item, timeTags); return timeTags.OrderBy(x => x.Index).ToArray(); } diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs index 30a9d87de..e1df7c4c9 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/Lyrics/TimeTags/TimeTagGeneratorSelector.cs @@ -20,20 +20,6 @@ public TimeTagGeneratorSelector(KaraokeRulesetEditGeneratorConfigManager generat RegisterGenerator(new CultureInfo(1028)); } - public override TimeTag[] Generate(Lyric lyric) - { - if (lyric.Language == null) - return Array.Empty(); - - if (string.IsNullOrEmpty(lyric.Text)) - return Array.Empty(); - - if (!Generator.TryGetValue(lyric.Language, out var generator)) - return Array.Empty(); - - return generator.Value.Generate(lyric); - } - protected override KaraokeRulesetEditGeneratorSetting GetGeneratorConfigSetting(CultureInfo info) => info.LCID switch { diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/NotDetectatableException.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/NotDetectatableException.cs new file mode 100644 index 000000000..bd53cab71 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/NotDetectatableException.cs @@ -0,0 +1,14 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator; + +public class NotDetectatableException : Exception +{ + public NotDetectatableException() + : base("Cannnot generate the property due to have some invalid fields, please make sure that run the CanDetect() first.") + { + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/NotGeneratableException.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/NotGeneratableException.cs new file mode 100644 index 000000000..1f363a29d --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/NotGeneratableException.cs @@ -0,0 +1,14 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator; + +public class NotGeneratableException : Exception +{ + public NotGeneratableException() + : base("Cannnot generate the property due to have some invalid fields, please make sure that run the CanGenerate() first.") + { + } +} diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/PropertyDetector.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/PropertyDetector.cs new file mode 100644 index 000000000..f55b9383f --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/PropertyDetector.cs @@ -0,0 +1,53 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator; + +public abstract class PropertyDetector : PropertyDetector + where TConfig : IHasConfig, new() +{ + protected readonly TConfig Config; + + protected PropertyDetector(TConfig config) + { + Config = config; + } +} + +public abstract class PropertyDetector +{ + /// + /// Determined if detect from is supported. + /// + /// + /// + public bool CanDetect(TItem item) => GetInvalidMessage(item) == null; + + /// + /// Will get the invalid message if from the is not able to be detected. + /// + /// + /// + public LocalisableString? GetInvalidMessage(TItem item) + => GetInvalidMessageFromItem(item); + + /// + /// Detect the from the . + /// + /// + /// + public TProperty Detect(TItem item) + { + if (!CanDetect(item)) + throw new NotDetectatableException(); + + return DetectFromItem(item); + } + + protected abstract LocalisableString? GetInvalidMessageFromItem(TItem item); + + protected abstract TProperty DetectFromItem(TItem item); +} + diff --git a/osu.Game.Rulesets.Karaoke/Edit/Generator/PropertyGenerator.cs b/osu.Game.Rulesets.Karaoke/Edit/Generator/PropertyGenerator.cs new file mode 100644 index 000000000..a52980fc0 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Edit/Generator/PropertyGenerator.cs @@ -0,0 +1,52 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using osu.Framework.Localisation; + +namespace osu.Game.Rulesets.Karaoke.Edit.Generator; + +public abstract class PropertyGenerator : PropertyGenerator + where TConfig : IHasConfig, new() +{ + protected readonly TConfig Config; + + protected PropertyGenerator(TConfig config) + { + Config = config; + } +} + +public abstract class PropertyGenerator +{ + /// + /// Determined if generate from is supported. + /// + /// + /// + public bool CanGenerate(TItem item) => GetInvalidMessage(item) == null; + + /// + /// Will get the invalid message if from the is not able to be generated. + /// + /// + /// + public LocalisableString? GetInvalidMessage(TItem item) + => GetInvalidMessageFromItem(item); + + /// + /// Generate the from the . + /// + /// + /// + public TProperty Generate(TItem item) + { + if (!CanGenerate(item)) + throw new NotGeneratableException(); + + return GenerateFromItem(item); + } + + protected abstract LocalisableString? GetInvalidMessageFromItem(TItem item); + + protected abstract TProperty GenerateFromItem(TItem item); +}