From 7b051f1036b6ebda98b3795a8634318d533faba1 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Tue, 1 Dec 2020 10:41:45 +0900 Subject: [PATCH 1/6] rename from iTag to iTextTag. --- .../Edit/RubyRomaji/Components/TagListPreview.cs | 4 ++-- osu.Game.Rulesets.Karaoke/Objects/RomajiTag.cs | 2 +- osu.Game.Rulesets.Karaoke/Objects/RubyTag.cs | 2 +- .../Objects/Types/{ITag.cs => ITextTag.cs} | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename osu.Game.Rulesets.Karaoke/Objects/Types/{ITag.cs => ITextTag.cs} (89%) diff --git a/osu.Game.Rulesets.Karaoke/Edit/RubyRomaji/Components/TagListPreview.cs b/osu.Game.Rulesets.Karaoke/Edit/RubyRomaji/Components/TagListPreview.cs index 73b74223f..17e4b70c7 100644 --- a/osu.Game.Rulesets.Karaoke/Edit/RubyRomaji/Components/TagListPreview.cs +++ b/osu.Game.Rulesets.Karaoke/Edit/RubyRomaji/Components/TagListPreview.cs @@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Karaoke.Edit.RubyRomaji.Components { - public class TagListPreview : Container where T : ITag + public class TagListPreview : Container where T : ITextTag { private readonly CornerBackground background; private readonly PreviewTagTable previewTagTable; @@ -148,7 +148,7 @@ private TableColumn[] createHeaders() private Drawable[] createContent(int index, T tag) { // IDK why but it only works with Bindable, Bindable doesn't work - var bindableTag = new Bindable(tag); + var bindableTag = new Bindable(tag); OsuDropdown startPositionDropdown; OsuDropdown endPositionDropdown; diff --git a/osu.Game.Rulesets.Karaoke/Objects/RomajiTag.cs b/osu.Game.Rulesets.Karaoke/Objects/RomajiTag.cs index 44be134a4..6f4c5572b 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/RomajiTag.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/RomajiTag.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Karaoke.Objects { - public struct RomajiTag : ITag + public struct RomajiTag : ITextTag { /// /// If kanji Matched, then apply romaji diff --git a/osu.Game.Rulesets.Karaoke/Objects/RubyTag.cs b/osu.Game.Rulesets.Karaoke/Objects/RubyTag.cs index c13fa0d04..47a3600ab 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/RubyTag.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/RubyTag.cs @@ -5,7 +5,7 @@ namespace osu.Game.Rulesets.Karaoke.Objects { - public struct RubyTag : ITag + public struct RubyTag : ITextTag { /// /// If kanji Matched, then apply ruby diff --git a/osu.Game.Rulesets.Karaoke/Objects/Types/ITag.cs b/osu.Game.Rulesets.Karaoke/Objects/Types/ITextTag.cs similarity index 89% rename from osu.Game.Rulesets.Karaoke/Objects/Types/ITag.cs rename to osu.Game.Rulesets.Karaoke/Objects/Types/ITextTag.cs index 2e43ee6cb..2a1b8fc15 100644 --- a/osu.Game.Rulesets.Karaoke/Objects/Types/ITag.cs +++ b/osu.Game.Rulesets.Karaoke/Objects/Types/ITextTag.cs @@ -3,7 +3,7 @@ namespace osu.Game.Rulesets.Karaoke.Objects.Types { - public interface ITag + public interface ITextTag : IHasText { string Text { get; set; } From 55541f13a60a78391a649844f5e6b26200a37010 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Tue, 1 Dec 2020 10:53:42 +0900 Subject: [PATCH 2/6] Add utils and test case. --- .../Utils/TextTagUtilsTest.cs | 68 ++++++++++++++ .../Utils/TextTagUtils.cs | 88 +++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagUtilsTest.cs create mode 100644 osu.Game.Rulesets.Karaoke/Utils/TextTagUtils.cs diff --git a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagUtilsTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagUtilsTest.cs new file mode 100644 index 000000000..a0d1c25ee --- /dev/null +++ b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagUtilsTest.cs @@ -0,0 +1,68 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using NUnit.Framework; +using osu.Game.Rulesets.Karaoke.Objects; + +namespace osu.Game.Rulesets.Karaoke.Tests.Utils +{ + [TestFixture] + public class TextTagUtilsTest + { + #region valid source + + public static RubyTag[] ValidTextTagWithSorted() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = 1 }, + new RubyTag { StartIndex = 1, EndIndex = 2 }, + new RubyTag { StartIndex = 2, EndIndex = 3 } + }; + + public static RubyTag[] ValidTextTagWithUnsorted() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = 1 }, + new RubyTag { StartIndex = 2, EndIndex = 3 }, + new RubyTag { StartIndex = 1, EndIndex = 2 } + }; + + #endregion + + #region invalid source + + public static RubyTag[] InvalidTextTagWithWrongIndex() + => new[] + { + new RubyTag { StartIndex = 1, EndIndex = 0 }, + }; + + public static RubyTag[] InvalidTextTagWithNegativeIndex() + => new[] + { + new RubyTag { StartIndex = -1, EndIndex = 0 }, + }; + + public static RubyTag[] InvalidTextTagWithEndLargerThenNextStart() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = 2 }, // End is larger than second start. + new RubyTag { StartIndex = 1, EndIndex = 2 } + }; + + public static RubyTag[] InvalidTextTagWithWrapNextTextTag() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = 3 }, // Wrap second text tag. + new RubyTag { StartIndex = 1, EndIndex = 2 } + }; + + public static RubyTag[] InvalidTextTagWithSameStartAndEndIndex() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = 0 }, // Same number. + }; + + #endregion + } +} diff --git a/osu.Game.Rulesets.Karaoke/Utils/TextTagUtils.cs b/osu.Game.Rulesets.Karaoke/Utils/TextTagUtils.cs new file mode 100644 index 000000000..34fe0c146 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Utils/TextTagUtils.cs @@ -0,0 +1,88 @@ +// 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.Types; +using System.Collections.Generic; +using System.Linq; + +namespace osu.Game.Rulesets.Karaoke.Utils +{ + public static class TextTagUtils + { + public static T[] Sort(T[] textTags) where T : ITextTag + { + return textTags?.OrderBy(x => x.StartIndex).ThenBy(x => x.EndIndex).ToArray(); + } + + public static T[] FindInvalid(T[] textTags, GroupCheck other = GroupCheck.Asc, SelfCheck self = SelfCheck.BasedOnStart) where T : ITextTag + { + var sortedTextTags = Sort(textTags); + var groupedTextTags = sortedTextTags.GroupBy(x => x.StartIndex); + + var invalidList = new List(); + + foreach (var groupedTimeTag in groupedTextTags) + { + // add invalid group into list. + var groupInvalid = findGroupInvalid(); + if (groupInvalid != null) + invalidList.AddRange(groupInvalid); + + // add invalid self into list. + var selfInvalid = findSelfInvalid(); + if (selfInvalid != null) + invalidList.AddRange(selfInvalid); + + List findGroupInvalid() + { + switch (other) + { + case GroupCheck.Asc: + // mark next is invalid if smaller then self + var groupMaxTime = groupedTimeTag.Max(x => x.Item2); + if (groupMaxTime == null) + return null; + + return groupedTimeTag.Where(x => x.Index > groupedTimeTag.Key && x.Item2 < groupMaxTime).ToList(); + + case GroupCheck.Desc: + // mark previous is invalid if larger then self + var groupMinTime = groupedTimeTag.Min(x => x.Item2); + if (groupMinTime == null) + return null; + + return groupedTimeTag.Where(x => x.Index < groupedTimeTag.Key && x.Item2 > groupMinTime).ToList(); + + default: + return null; + } + } + + List findSelfInvalid() + { + switch (self) + { + case SelfCheck.BasedOnStart: + var maxStartTime = startTimeGroup.Max(x => x.Item2); + if (maxStartTime == null) + return null; + + return endTimeGroup.Where(x => x.Item2.Value < maxStartTime.Value).ToList(); + + case SelfCheck.BasedOnEnd: + var minEndTime = endTimeGroup.Min(x => x.Item2); + if (minEndTime == null) + return null; + + return startTimeGroup.Where(x => x.Item2.Value > minEndTime.Value).ToList(); + + default: + return null; + } + } + } + + return Sort(invalidList.Distinct().ToArray()); + } + } +} From 1d3f176b036ac5898f9ffb5744fdd892c1e0df17 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Tue, 1 Dec 2020 11:00:05 +0900 Subject: [PATCH 3/6] Should add "s" because it deal with multi text tag at the same time. --- .../{TextTagUtilsTest.cs => TextTagsUtilsTest.cs} | 15 ++++++++++++++- .../Utils/{TextTagUtils.cs => TextTagsUtils.cs} | 2 +- 2 files changed, 15 insertions(+), 2 deletions(-) rename osu.Game.Rulesets.Karaoke.Tests/Utils/{TextTagUtilsTest.cs => TextTagsUtilsTest.cs} (80%) rename osu.Game.Rulesets.Karaoke/Utils/{TextTagUtils.cs => TextTagsUtils.cs} (98%) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagUtilsTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs similarity index 80% rename from osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagUtilsTest.cs rename to osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs index a0d1c25ee..21330f870 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagUtilsTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs @@ -3,12 +3,25 @@ using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Objects; +using osu.Game.Rulesets.Karaoke.Utils; namespace osu.Game.Rulesets.Karaoke.Tests.Utils { [TestFixture] - public class TextTagUtilsTest + public class TextTagsUtilsTest { + [TestCase(nameof(ValidTextTagWithSorted), new int[] { })] + public void TestSort(string testCase, int[] results) + { + // result : start, end, start, end... + } + + [TestCase(nameof(ValidTextTagWithSorted), GroupCheck.Asc, SelfCheck.BasedOnStart, new int[] { })] + public void TestFindInvalid(string testCase, GroupCheck other, SelfCheck self, int[] errorIndex) + { + + } + #region valid source public static RubyTag[] ValidTextTagWithSorted() diff --git a/osu.Game.Rulesets.Karaoke/Utils/TextTagUtils.cs b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs similarity index 98% rename from osu.Game.Rulesets.Karaoke/Utils/TextTagUtils.cs rename to osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs index 34fe0c146..3b9043b93 100644 --- a/osu.Game.Rulesets.Karaoke/Utils/TextTagUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs @@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Karaoke.Utils { - public static class TextTagUtils + public static class TextTagsUtils { public static T[] Sort(T[] textTags) where T : ITextTag { From 9e47586eff83bdd834a7394bb9578d6a61f437d8 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Tue, 1 Dec 2020 23:38:55 +0900 Subject: [PATCH 4/6] implement test case and some check part. --- .../Utils/TextTagsUtilsTest.cs | 62 +++++++++--- .../Utils/TextTagsUtils.cs | 99 ++++++++----------- 2 files changed, 93 insertions(+), 68 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs index 21330f870..f45fb8ca4 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs @@ -1,25 +1,65 @@ // Copyright (c) andy840119 . Licensed under the GPL Licence. // See the LICENCE file in the repository root for full licence text. +using Microsoft.EntityFrameworkCore.Internal; using NUnit.Framework; using osu.Game.Rulesets.Karaoke.Objects; using osu.Game.Rulesets.Karaoke.Utils; +using System; +using System.Linq; namespace osu.Game.Rulesets.Karaoke.Tests.Utils { [TestFixture] public class TextTagsUtilsTest { - [TestCase(nameof(ValidTextTagWithSorted), new int[] { })] - public void TestSort(string testCase, int[] results) + private const string lyric = "Test lyric"; + + [TestCase(nameof(ValidTextTagWithSorted), TextTagsUtils.Sorting.Asc, new int[] { 0, 1, 1, 2, 2, 3 })] + [TestCase(nameof(ValidTextTagWithSorted), TextTagsUtils.Sorting.Desc, new int[] { 2, 3, 1, 2, 0, 1 })] + [TestCase(nameof(ValidTextTagWithUnsorted), TextTagsUtils.Sorting.Asc, new int[] { 0, 1, 1, 2, 2, 3 })] + [TestCase(nameof(ValidTextTagWithUnsorted), TextTagsUtils.Sorting.Desc, new int[] { 2, 3, 1, 2, 0, 1 })] + public void TestSort(string testCase, TextTagsUtils.Sorting sorting, int[] results) + { + var textTags = getValueByMethodName(testCase); + + var sortedTextTags = TextTagsUtils.Sort(textTags, sorting); + for (int i = 0; i < sortedTextTags.Length; i++) + { + // result would be start, end, start, end... + Assert.AreEqual(sortedTextTags[i].StartIndex, results[i * 2]); + Assert.AreEqual(sortedTextTags[i].EndIndex, results[i * 2 + 1]); + } + } + + [TestCase(nameof(ValidTextTagWithSorted), TextTagsUtils.Sorting.Asc, new int[] { })] + [TestCase(nameof(ValidTextTagWithUnsorted), TextTagsUtils.Sorting.Asc, new int[] { })] + [TestCase(nameof(InvalidTextTagWithSameStartAndEndIndex), TextTagsUtils.Sorting.Asc, new int[] {0 })] + [TestCase(nameof(InvalidTextTagWithWrongIndex), TextTagsUtils.Sorting.Asc, new int[] { 0 })] + [TestCase(nameof(InvalidTextTagWithNegativeIndex), TextTagsUtils.Sorting.Asc, new int[] { 0 })] + [TestCase(nameof(InvalidTextTagWithEndLargerThenNextStart), TextTagsUtils.Sorting.Asc, new int[] { 1 })] + [TestCase(nameof(InvalidTextTagWithEndLargerThenNextStart), TextTagsUtils.Sorting.Desc, new int[] { 0 })] + [TestCase(nameof(InvalidTextTagWithWrapNextTextTag), TextTagsUtils.Sorting.Asc, new int[] { 1 })] + [TestCase(nameof(InvalidTextTagWithWrapNextTextTag), TextTagsUtils.Sorting.Desc, new int[] { 0 })] + + public void TestFindInvalid(string testCase, TextTagsUtils.Sorting sorting, int[] errorIndex) { - // result : start, end, start, end... + var textTags = getValueByMethodName(testCase); + + // run all and find invalid indexes. + var invalidTextTag = TextTagsUtils.FindInvalid(textTags, lyric, sorting); + var invalidIndexes = invalidTextTag.Select(v => textTags.IndexOf(v)).ToArray(); + Assert.AreEqual(invalidIndexes, errorIndex); } - [TestCase(nameof(ValidTextTagWithSorted), GroupCheck.Asc, SelfCheck.BasedOnStart, new int[] { })] - public void TestFindInvalid(string testCase, GroupCheck other, SelfCheck self, int[] errorIndex) + private RubyTag[] getValueByMethodName(string methodName) { + Type thisType = GetType(); + var theMethod = thisType.GetMethod(methodName); + if (theMethod == null) + throw new MissingMethodException("Test method is not exist."); + return theMethod.Invoke(this, null) as RubyTag[]; } #region valid source @@ -56,6 +96,12 @@ public static RubyTag[] InvalidTextTagWithNegativeIndex() new RubyTag { StartIndex = -1, EndIndex = 0 }, }; + public static RubyTag[] InvalidTextTagWithSameStartAndEndIndex() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = 0 }, // Same number. + }; + public static RubyTag[] InvalidTextTagWithEndLargerThenNextStart() => new[] { @@ -70,12 +116,6 @@ public static RubyTag[] InvalidTextTagWithWrapNextTextTag() new RubyTag { StartIndex = 1, EndIndex = 2 } }; - public static RubyTag[] InvalidTextTagWithSameStartAndEndIndex() - => new[] - { - new RubyTag { StartIndex = 0, EndIndex = 0 }, // Same number. - }; - #endregion } } diff --git a/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs index 3b9043b93..a7fc1aa25 100644 --- a/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs @@ -4,85 +4,70 @@ using osu.Game.Rulesets.Karaoke.Objects.Types; using System.Collections.Generic; using System.Linq; +using System; namespace osu.Game.Rulesets.Karaoke.Utils { public static class TextTagsUtils { - public static T[] Sort(T[] textTags) where T : ITextTag + public static T[] Sort(T[] textTags, Sorting sorting = Sorting.Asc) where T : ITextTag { - return textTags?.OrderBy(x => x.StartIndex).ThenBy(x => x.EndIndex).ToArray(); + switch (sorting) + { + case Sorting.Asc: + return textTags?.OrderBy(x => x.StartIndex).ThenBy(x => x.EndIndex).ToArray(); + case Sorting.Desc: + return textTags?.OrderByDescending(x => x.EndIndex).ThenByDescending(x => x.StartIndex).ToArray(); + default: + throw new ArgumentOutOfRangeException(nameof(sorting)); + } } - public static T[] FindInvalid(T[] textTags, GroupCheck other = GroupCheck.Asc, SelfCheck self = SelfCheck.BasedOnStart) where T : ITextTag + public static T[] FindInvalid(T[] textTags, string lyric, Sorting sorting = Sorting.Asc) where T : ITextTag { - var sortedTextTags = Sort(textTags); - var groupedTextTags = sortedTextTags.GroupBy(x => x.StartIndex); - - var invalidList = new List(); - - foreach (var groupedTimeTag in groupedTextTags) - { - // add invalid group into list. - var groupInvalid = findGroupInvalid(); - if (groupInvalid != null) - invalidList.AddRange(groupInvalid); - - // add invalid self into list. - var selfInvalid = findSelfInvalid(); - if (selfInvalid != null) - invalidList.AddRange(selfInvalid); - - List findGroupInvalid() - { - switch (other) - { - case GroupCheck.Asc: - // mark next is invalid if smaller then self - var groupMaxTime = groupedTimeTag.Max(x => x.Item2); - if (groupMaxTime == null) - return null; + // check is null or empty + if (textTags == null || textTags.Length == 0) + return new T[] { }; - return groupedTimeTag.Where(x => x.Index > groupedTimeTag.Key && x.Item2 < groupMaxTime).ToList(); + var sortedTextTags = Sort(textTags, sorting); - case GroupCheck.Desc: - // mark previous is invalid if larger then self - var groupMinTime = groupedTimeTag.Min(x => x.Item2); - if (groupMinTime == null) - return null; + var invalidList = new List(); - return groupedTimeTag.Where(x => x.Index < groupedTimeTag.Key && x.Item2 > groupMinTime).ToList(); + // check invalid range + invalidList.AddRange(sortedTextTags.Where(x => x.StartIndex < 0 || x.EndIndex > lyric.Length)); - default: - return null; - } - } + // check end is less or equal to start index + invalidList.AddRange(sortedTextTags.Where(x => x.EndIndex <= x.StartIndex)); - List findSelfInvalid() + // find other is smaller or bigger + foreach (var textTag in sortedTextTags) + { + switch (sorting) { - switch (self) - { - case SelfCheck.BasedOnStart: - var maxStartTime = startTimeGroup.Max(x => x.Item2); - if (maxStartTime == null) - return null; + case Sorting.Asc: - return endTimeGroup.Where(x => x.Item2.Value < maxStartTime.Value).ToList(); + break; - case SelfCheck.BasedOnEnd: - var minEndTime = endTimeGroup.Min(x => x.Item2); - if (minEndTime == null) - return null; + case Sorting.Desc: - return startTimeGroup.Where(x => x.Item2.Value > minEndTime.Value).ToList(); - - default: - return null; - } + break; } } return Sort(invalidList.Distinct().ToArray()); } + + public enum Sorting + { + /// + /// Mark next time tag is error if conflict. + /// + Asc, + + /// + /// Mark previous tag is error if conflict. + /// + Desc + } } } From c0e985d3a0f72af238e1ec57bf1df9ed37f860f2 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Wed, 2 Dec 2020 00:48:25 +0900 Subject: [PATCH 5/6] pass most of test case. --- .../Utils/TextTagsUtilsTest.cs | 15 +++++++++++++-- osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs | 11 +++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs index f45fb8ca4..4dca64de0 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs @@ -41,7 +41,6 @@ public void TestSort(string testCase, TextTagsUtils.Sorting sorting, int[] resul [TestCase(nameof(InvalidTextTagWithEndLargerThenNextStart), TextTagsUtils.Sorting.Desc, new int[] { 0 })] [TestCase(nameof(InvalidTextTagWithWrapNextTextTag), TextTagsUtils.Sorting.Asc, new int[] { 1 })] [TestCase(nameof(InvalidTextTagWithWrapNextTextTag), TextTagsUtils.Sorting.Desc, new int[] { 0 })] - public void TestFindInvalid(string testCase, TextTagsUtils.Sorting sorting, int[] errorIndex) { var textTags = getValueByMethodName(testCase); @@ -102,11 +101,23 @@ public static RubyTag[] InvalidTextTagWithSameStartAndEndIndex() new RubyTag { StartIndex = 0, EndIndex = 0 }, // Same number. }; + public static RubyTag[] InvalidTextTagWithStartTimeExceedLyricSize() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = lyric.Length + 1 }, // Same number. + }; + + public static RubyTag[] InvalidTextTagWithEndTimeExceedLyricSize() + => new[] + { + new RubyTag { StartIndex = lyric.Length + 1, EndIndex = lyric.Length + 2 }, // Same number. + }; + public static RubyTag[] InvalidTextTagWithEndLargerThenNextStart() => new[] { new RubyTag { StartIndex = 0, EndIndex = 2 }, // End is larger than second start. - new RubyTag { StartIndex = 1, EndIndex = 2 } + new RubyTag { StartIndex = 1, EndIndex = 3 } }; public static RubyTag[] InvalidTextTagWithWrapNextTextTag() diff --git a/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs index a7fc1aa25..ded75b1a6 100644 --- a/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs @@ -42,14 +42,21 @@ public static T[] FindInvalid(T[] textTags, string lyric, Sorting sorting = S // find other is smaller or bigger foreach (var textTag in sortedTextTags) { + + if (invalidList.Contains(textTag)) + continue; + + var checkTags = sortedTextTags.Except(new[] { textTag }); switch (sorting) { case Sorting.Asc: - + // start index within tne target + invalidList.AddRange(checkTags.Where(x => x.StartIndex >= textTag.StartIndex && x.StartIndex < textTag.EndIndex)); break; case Sorting.Desc: - + // end index within tne target + invalidList.AddRange(checkTags.Where(x => x.EndIndex >= textTag.StartIndex && x.StartIndex < textTag.EndIndex)); break; } } From 4cfc0a72bd1ad2755fc25701387a76c2421681b0 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Wed, 2 Dec 2020 10:58:00 +0900 Subject: [PATCH 6/6] finish checking algorithm. --- .../Utils/TextTagsUtilsTest.cs | 12 +++++++++++- osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs | 4 ++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs index 4dca64de0..576c5a556 100644 --- a/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs +++ b/osu.Game.Rulesets.Karaoke.Tests/Utils/TextTagsUtilsTest.cs @@ -40,7 +40,9 @@ public void TestSort(string testCase, TextTagsUtils.Sorting sorting, int[] resul [TestCase(nameof(InvalidTextTagWithEndLargerThenNextStart), TextTagsUtils.Sorting.Asc, new int[] { 1 })] [TestCase(nameof(InvalidTextTagWithEndLargerThenNextStart), TextTagsUtils.Sorting.Desc, new int[] { 0 })] [TestCase(nameof(InvalidTextTagWithWrapNextTextTag), TextTagsUtils.Sorting.Asc, new int[] { 1 })] - [TestCase(nameof(InvalidTextTagWithWrapNextTextTag), TextTagsUtils.Sorting.Desc, new int[] { 0 })] + [TestCase(nameof(InvalidTextTagWithWrapNextTextTag), TextTagsUtils.Sorting.Desc, new int[] { 1 })] + [TestCase(nameof(InvalidTextTagWithSandwichTextTag), TextTagsUtils.Sorting.Asc, new int[] { 1 })] + [TestCase(nameof(InvalidTextTagWithSandwichTextTag), TextTagsUtils.Sorting.Desc, new int[] { 1 })] public void TestFindInvalid(string testCase, TextTagsUtils.Sorting sorting, int[] errorIndex) { var textTags = getValueByMethodName(testCase); @@ -127,6 +129,14 @@ public static RubyTag[] InvalidTextTagWithWrapNextTextTag() new RubyTag { StartIndex = 1, EndIndex = 2 } }; + public static RubyTag[] InvalidTextTagWithSandwichTextTag() + => new[] + { + new RubyTag { StartIndex = 0, EndIndex = 2 }, + new RubyTag { StartIndex = 1, EndIndex = 3 }, + new RubyTag { StartIndex = 2, EndIndex = 4 } + }; + #endregion } } diff --git a/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs index ded75b1a6..5f5382f4d 100644 --- a/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs +++ b/osu.Game.Rulesets.Karaoke/Utils/TextTagsUtils.cs @@ -29,6 +29,7 @@ public static T[] FindInvalid(T[] textTags, string lyric, Sorting sorting = S if (textTags == null || textTags.Length == 0) return new T[] { }; + // todo : need to make suure is need to sort in here? var sortedTextTags = Sort(textTags, sorting); var invalidList = new List(); @@ -42,7 +43,6 @@ public static T[] FindInvalid(T[] textTags, string lyric, Sorting sorting = S // find other is smaller or bigger foreach (var textTag in sortedTextTags) { - if (invalidList.Contains(textTag)) continue; @@ -56,7 +56,7 @@ public static T[] FindInvalid(T[] textTags, string lyric, Sorting sorting = S case Sorting.Desc: // end index within tne target - invalidList.AddRange(checkTags.Where(x => x.EndIndex >= textTag.StartIndex && x.StartIndex < textTag.EndIndex)); + invalidList.AddRange(checkTags.Where(x => x.EndIndex > textTag.StartIndex && x.EndIndex <= textTag.EndIndex)); break; } }