mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Refactor TranslationMapping class
- Always add index to mapping rather than only Chinese characters - Simplify mapping algorithm - Add unit test for TranslationMapping
This commit is contained in:
parent
100f753e9b
commit
d9e89ad610
3 changed files with 66 additions and 68 deletions
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,82 +8,23 @@ namespace Flow.Launcher.Infrastructure
|
|||
{
|
||||
private bool constructed;
|
||||
|
||||
private readonly List<int> originalIndexes = new();
|
||||
private readonly List<int> 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<int> 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()
|
||||
|
|
|
|||
56
Flow.Launcher.Test/TranslationMappingTest.cs
Normal file
56
Flow.Launcher.Test/TranslationMappingTest.cs
Normal file
|
|
@ -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<int>)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<int>)field.GetValue(mapping);
|
||||
return list[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue