move acronym check to method and update scoring to percentage based

This commit is contained in:
Jeremy Wu 2021-02-01 21:34:35 +11:00
parent bb6a91124a
commit 99da6f207a
2 changed files with 61 additions and 70 deletions

View file

@ -66,10 +66,8 @@ namespace Flow.Launcher.Infrastructure
var currentAcronymQueryIndex = 0;
var acronymMatchData = new List<int>();
// preset acronymScore
int acronymScore = 100;
int acronymsRemainingNotMatched = 0;
int acronymsMatched = 0;
decimal acronymsTotalCount = 0;
decimal acronymsMatched = 0;
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
@ -89,21 +87,18 @@ namespace Flow.Launcher.Infrastructure
var indexList = new List<int>();
List<int> spaceIndices = new List<int>();
bool spaceMet = false;
for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
{
if (currentAcronymQueryIndex >= queryWithoutCase.Length && acronymsMatched > 0)
// If acronyms matching successfully finished, this gets the remaining not matched acronyms for score calculation
if (currentAcronymQueryIndex >= query.Length && acronymsMatched == query.Length)
{
if (char.IsUpper(stringToCompare[compareStringIndex]) ||
char.IsNumber(stringToCompare[compareStringIndex]) ||
char.IsWhiteSpace(stringToCompare[compareStringIndex]))
acronymsRemainingNotMatched++;
if (IsAcronym(stringToCompare, compareStringIndex))
acronymsTotalCount++;
continue;
}
if (currentAcronymQueryIndex >= queryWithoutCase.Length
|| allQuerySubstringsMatched && acronymScore < (int) UserSettingSearchPrecision)
if (currentAcronymQueryIndex >= query.Length ||
currentAcronymQueryIndex >= query.Length && allQuerySubstringsMatched)
break;
// To maintain a list of indices which correspond to spaces in the string to compare
@ -112,43 +107,18 @@ namespace Flow.Launcher.Infrastructure
spaceIndices.Add(compareStringIndex);
// Acronym check
if (char.IsUpper(stringToCompare[compareStringIndex]) ||
char.IsNumber(stringToCompare[compareStringIndex]) ||
char.IsWhiteSpace(stringToCompare[compareStringIndex]) ||
spaceMet)
if (IsAcronym(stringToCompare, compareStringIndex))
{
if (fullStringToCompareWithoutCase[compareStringIndex] ==
queryWithoutCase[currentAcronymQueryIndex])
{
if (!spaceMet)
{
char currentCompareChar = stringToCompare[compareStringIndex];
spaceMet = char.IsWhiteSpace(currentCompareChar);
// if is space, no need to check whether upper or digit, though insignificant
if (!spaceMet && compareStringIndex == 0 || char.IsUpper(currentCompareChar) ||
char.IsDigit(currentCompareChar))
{
acronymMatchData.Add(compareStringIndex);
acronymsMatched++;
}
}
else if (!(spaceMet = char.IsWhiteSpace(stringToCompare[compareStringIndex])))
{
acronymMatchData.Add(compareStringIndex);
acronymsMatched++;
}
acronymMatchData.Add(compareStringIndex);
acronymsMatched++;
currentAcronymQueryIndex++;
}
else
{
spaceMet = char.IsWhiteSpace(stringToCompare[compareStringIndex]);
// Acronym Penalty
if (!spaceMet)
{
acronymScore -= 10;
}
}
acronymsTotalCount++;
}
// Acronym end
@ -217,11 +187,16 @@ namespace Flow.Launcher.Infrastructure
}
}
// return acronym Match if possible
if (acronymMatchData.Count == query.Length && acronymScore >= (int) UserSettingSearchPrecision)
// return acronym match if all query char matched
if (acronymsMatched > 0 && acronymsMatched == query.Length)
{
acronymMatchData = acronymMatchData.Select(x => translationMapping?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
int acronymScore = (int)(acronymsMatched / acronymsTotalCount * 100);
if (acronymScore >= (int)UserSettingSearchPrecision)
{
acronymMatchData = acronymMatchData.Select(x => translationMapping?.MapToOriginalIndex(x) ?? x).Distinct().ToList();
return new MatchResult(true, UserSettingSearchPrecision, acronymMatchData, acronymScore);
}
}
// proceed to calculate score if every char or substring without whitespaces matched
@ -238,6 +213,22 @@ namespace Flow.Launcher.Infrastructure
return new MatchResult(false, UserSettingSearchPrecision);
}
private bool IsAcronym(string stringToCompare, int compareStringIndex)
{
if (char.IsUpper(stringToCompare[compareStringIndex]) ||
char.IsNumber(stringToCompare[compareStringIndex]) ||
char.IsDigit(stringToCompare[compareStringIndex]))
return true;
if (compareStringIndex == 0)
return true;
if (compareStringIndex != 0 && char.IsWhiteSpace(stringToCompare[compareStringIndex - 1]))
return true;
return false;
}
// To get the index of the closest space which preceeds the first matching index
private int CalculateClosestSpaceIndex(List<int> spaceIndices, int firstMatchIndex)
{

View file

@ -151,13 +151,17 @@ namespace Flow.Launcher.Test
[TestCase("goo", "Google Chrome", SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Google Chrome", SearchPrecisionScore.Low, true)]
[TestCase("chr", "Chrome", SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Low, true)]
[TestCase("chr", "Candy Crush Saga from King", SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Candy Crush Saga from King", SearchPrecisionScore.None, true)]
[TestCase("ccs", "Candy Crush Saga from King", SearchPrecisionScore.Regular, true)]
[TestCase("ccs", "Candy Crush Saga from King", SearchPrecisionScore.Low, true)]
[TestCase("cand", "Candy Crush Saga from King", SearchPrecisionScore.Regular, true)]
[TestCase("cand", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Regular,
false)]
[TestCase("cand", "Help cure hope raise on mind entity Chrome", SearchPrecisionScore.Regular, false)]
[TestCase("vsc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vs", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vts", VisualStudioCode, SearchPrecisionScore.Regular, false)]
public void WhenGivenDesiredPrecision_ThenShouldReturn_AllResultsGreaterOrEqual(
string queryString,
string compareString,
@ -188,10 +192,8 @@ namespace Flow.Launcher.Test
[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", SearchPrecisionScore.Regular, false)]
[TestCase("term", "Windows Terminal (Preview)", SearchPrecisionScore.Regular, true)]
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular,
false)]
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular,
false)]
[TestCase("sql s managa", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, false)]
[TestCase("sql s manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
@ -204,18 +206,13 @@ namespace Flow.Launcher.Test
[TestCase("mssms", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("msms", MicrosoftSqlServerManagementStudio, SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Shutdown", SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).",
SearchPrecisionScore.Regular, false)]
[TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).",
SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", SearchPrecisionScore.Regular, false)]
[TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", SearchPrecisionScore.Regular, true)]
[TestCase("a test", "This is a test", SearchPrecisionScore.Regular, true)]
[TestCase("test", "This is a test", SearchPrecisionScore.Regular, true)]
[TestCase("cod", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("code", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("codes", "Visual Studio Codes", SearchPrecisionScore.Regular, true)]
[TestCase("vsc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vs", VisualStudioCode, SearchPrecisionScore.Regular, true)]
[TestCase("vc", VisualStudioCode, SearchPrecisionScore.Regular, true)]
public void WhenGivenQuery_ShouldReturnResults_ContainingAllQuerySubstrings(
string queryString,
string compareString,
@ -300,15 +297,18 @@ namespace Flow.Launcher.Test
$"Should be greater than{Environment.NewLine}" +
$"Name of second: \"{secondName}\", Final Score: {secondScore}{Environment.NewLine}");
}
[TestCase("vsc","Visual Studio Code", 100)]
[TestCase("jbr","JetBrain Rider",100)]
[TestCase("jr","JetBrain Rider",90)]
[TestCase("vs","Visual Studio",100)]
[TestCase("vs","Visual Studio Preview",100)]
[TestCase("vsp","Visual Studio Preview",100)]
[TestCase("vsp","Visual Studio",0)]
[TestCase("pc","Postman Canary",100)]
[TestCase("vsc", "Visual Studio Code", 100)]
[TestCase("jbr", "JetBrain Rider", 100)]
[TestCase("jr", "JetBrain Rider", 66)]
[TestCase("vs", "Visual Studio", 100)]
[TestCase("vs", "Visual Studio Preview", 66)]
[TestCase("vsp", "Visual Studio Preview", 100)]
[TestCase("pc", "postman canary", 100)]
[TestCase("psc", "Postman super canary", 100)]
[TestCase("psc", "Postman super Canary", 100)]
[TestCase("vsp", "Visual Studio", 0)]
[TestCase("vps", "Visual Studio", 0)]
public void WhenGivenAnAcronymQuery_ShouldReturnAcronymScore(string queryString, string compareString,
int desiredScore)
{