diff --git a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs index c85c432dd..7f7f2da60 100644 --- a/Flow.Launcher.Infrastructure/PinyinAlphabet.cs +++ b/Flow.Launcher.Infrastructure/PinyinAlphabet.cs @@ -107,12 +107,12 @@ namespace Flow.Launcher.Infrastructure if (previousIsChinese) { resultBuilder.Append(' '); - map.AddNewIndex(i, resultBuilder.Length, translated.Length); + map.AddNewIndex(resultBuilder.Length, translated.Length); resultBuilder.Append(translated); } else { - map.AddNewIndex(i, resultBuilder.Length, translated.Length); + map.AddNewIndex(resultBuilder.Length, translated.Length); resultBuilder.Append(translated); previousIsChinese = true; } @@ -124,6 +124,7 @@ namespace Flow.Launcher.Infrastructure previousIsChinese = false; resultBuilder.Append(' '); } + map.AddNewIndex(resultBuilder.Length, resultList[i].Length); resultBuilder.Append(resultList[i]); } } diff --git a/Flow.Launcher.Infrastructure/TranslationMapping.cs b/Flow.Launcher.Infrastructure/TranslationMapping.cs index b33a094db..6d4feccd4 100644 --- a/Flow.Launcher.Infrastructure/TranslationMapping.cs +++ b/Flow.Launcher.Infrastructure/TranslationMapping.cs @@ -8,82 +8,23 @@ namespace Flow.Launcher.Infrastructure { private bool constructed; - private readonly List originalIndexes = new(); - private readonly List translatedIndexes = new(); + // Asssuming one original item maps to multi translated items + // list[i] is the last translated index + 1 of original index i + private readonly List originalToTranslated = []; - private int translatedLength = 0; - - public void AddNewIndex(int originalIndex, int translatedIndex, int length) + public void AddNewIndex(int translatedIndex, int length) { if (constructed) throw new InvalidOperationException("Mapping shouldn't be changed after constructed"); - originalIndexes.Add(originalIndex); - translatedIndexes.Add(translatedIndex); - translatedIndexes.Add(translatedIndex + length); - translatedLength += length - 1; + originalToTranslated.Add(translatedIndex + length); } public int MapToOriginalIndex(int translatedIndex) { - if (translatedIndex > translatedIndexes.Last()) - return translatedIndex - translatedLength - 1; + int loc = originalToTranslated.BinarySearch(translatedIndex); - int lowerBound = 0; - int upperBound = originalIndexes.Count - 1; - - int count = 0; - - // Corner case handle - if (translatedIndex < translatedIndexes[0]) - return translatedIndex; - - if (translatedIndex > translatedIndexes.Last()) - { - int indexDef = 0; - for (int k = 0; k < originalIndexes.Count; k++) - { - indexDef += translatedIndexes[k * 2 + 1] - translatedIndexes[k * 2]; - } - - return translatedIndex - indexDef - 1; - } - - // Binary Search with Range - for (int i = originalIndexes.Count / 2;; count++) - { - if (translatedIndex < translatedIndexes[i * 2]) - { - // move to lower middle - upperBound = i; - i = (i + lowerBound) / 2; - } - else if (translatedIndex > translatedIndexes[i * 2 + 1] - 1) - { - lowerBound = i; - // move to upper middle - // due to floor of integer division, move one up on corner case - i = (i + upperBound + 1) / 2; - } - else - { - return originalIndexes[i]; - } - - if (upperBound - lowerBound <= 1 && - translatedIndex > translatedIndexes[lowerBound * 2 + 1] && - translatedIndex < translatedIndexes[upperBound * 2]) - { - int indexDef = 0; - - for (int j = 0; j < upperBound; j++) - { - indexDef += translatedIndexes[j * 2 + 1] - translatedIndexes[j * 2]; - } - - return translatedIndex - indexDef - 1; - } - } + return loc > 0 ? loc : ~loc; } public void endConstruct() diff --git a/Flow.Launcher.Test/TranslationMappingTest.cs b/Flow.Launcher.Test/TranslationMappingTest.cs new file mode 100644 index 000000000..10d765f5a --- /dev/null +++ b/Flow.Launcher.Test/TranslationMappingTest.cs @@ -0,0 +1,56 @@ +using Flow.Launcher.Infrastructure; +using NUnit.Framework; +using NUnit.Framework.Legacy; + +namespace Flow.Launcher.Test +{ + [TestFixture] + public class TranslationMappingTest + { + [Test] + public void AddNewIndex_ShouldAddTranslatedIndexPlusLength() + { + var mapping = new TranslationMapping(); + mapping.AddNewIndex(5, 3); + mapping.AddNewIndex(8, 2); + + // 5+3=8, 8+2=10 + ClassicAssert.AreEqual(2, GetOriginalToTranslatedCount(mapping)); + ClassicAssert.AreEqual(8, GetOriginalToTranslatedAt(mapping, 0)); + ClassicAssert.AreEqual(10, GetOriginalToTranslatedAt(mapping, 1)); + } + + [TestCase(0, 0)] + [TestCase(2, 1)] + [TestCase(3, 1)] + [TestCase(5, 2)] + [TestCase(6, 2)] + public void MapToOriginalIndex_ShouldReturnExpectedIndex(int translatedIndex, int expectedOriginalIndex) + { + var mapping = new TranslationMapping(); + // a测试 + // a Ce Shi + mapping.AddNewIndex(0, 1); + mapping.AddNewIndex(2, 2); + mapping.AddNewIndex(5, 3); + + + var result = mapping.MapToOriginalIndex(translatedIndex); + ClassicAssert.AreEqual(expectedOriginalIndex, result); + } + + private int GetOriginalToTranslatedCount(TranslationMapping mapping) + { + var field = typeof(TranslationMapping).GetField("originalToTranslated", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + var list = (System.Collections.Generic.List)field.GetValue(mapping); + return list.Count; + } + + private int GetOriginalToTranslatedAt(TranslationMapping mapping, int index) + { + var field = typeof(TranslationMapping).GetField("originalToTranslated", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + var list = (System.Collections.Generic.List)field.GetValue(mapping); + return list[index]; + } + } +}