From 42edb20b07fb5f44fe18bf72ad144ec95d8996cc Mon Sep 17 00:00:00 2001
From: AT <14300910+theClueless@users.noreply.github.com>
Date: Mon, 30 Dec 2019 01:13:33 +0200
Subject: [PATCH 01/23] fixes to string matcher alg and some logging stuff
---
Wox.Infrastructure/Logger/Log.cs | 126 ++++++++--------
Wox.Infrastructure/StringMatcher.cs | 155 ++++++++++++++------
Wox.Infrastructure/UserSettings/Settings.cs | 23 ++-
Wox.Test/FuzzyMatcherTest.cs | 135 +++++++++++------
Wox/App.xaml.cs | 2 +-
Wox/SettingWindow.xaml | 2 +-
6 files changed, 278 insertions(+), 165 deletions(-)
diff --git a/Wox.Infrastructure/Logger/Log.cs b/Wox.Infrastructure/Logger/Log.cs
index ff72dff1c3..cc1408b533 100644
--- a/Wox.Infrastructure/Logger/Log.cs
+++ b/Wox.Infrastructure/Logger/Log.cs
@@ -47,8 +47,53 @@ namespace Wox.Infrastructure.Logger
return valid;
}
- /// example: "|prefix|unprefixed"
- public static void Error(string message)
+
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ public static void Exception(string className, string message, System.Exception exception, [CallerMemberName] string methodName = "")
+ {
+ if (string.IsNullOrWhiteSpace(className))
+ {
+ LogFaultyFormat($"Fail to specify a class name during logging of message: {message ?? "no message entered"}");
+ }
+
+ if (string.IsNullOrWhiteSpace(message))
+ { // todo: not sure we really need that
+ LogFaultyFormat($"Fail to specify a message during logging");
+ }
+
+ if (!string.IsNullOrWhiteSpace(methodName))
+ {
+ className += "." + methodName;
+ }
+
+ ExceptionInternal(className, message, exception);
+ }
+
+ private static void ExceptionInternal(string classAndMethod, string message, System.Exception e)
+ {
+ var logger = LogManager.GetLogger(classAndMethod);
+
+ System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
+
+ logger.Error("-------------------------- Begin exception --------------------------");
+ logger.Error(message);
+
+ do
+ {
+ logger.Error($"Exception full name:\n <{e.GetType().FullName}>");
+ logger.Error($"Exception message:\n <{e.Message}>");
+ logger.Error($"Exception stack trace:\n <{e.StackTrace}>");
+ logger.Error($"Exception source:\n <{e.Source}>");
+ logger.Error($"Exception target site:\n <{e.TargetSite}>");
+ logger.Error($"Exception HResult:\n <{e.HResult}>");
+ e = e.InnerException;
+ } while (e != null);
+
+ logger.Error("-------------------------- End exception --------------------------");
+ }
+
+ private static void LogInternal(string message, LogLevel level)
{
if (FormatValid(message))
{
@@ -57,8 +102,8 @@ namespace Wox.Infrastructure.Logger
var unprefixed = parts[2];
var logger = LogManager.GetLogger(prefix);
- System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
- logger.Error(unprefixed);
+ System.Diagnostics.Debug.WriteLine($"{level.Name}|{message}");
+ logger.Log(level, unprefixed);
}
else
{
@@ -78,25 +123,7 @@ namespace Wox.Infrastructure.Logger
var parts = message.Split('|');
var prefix = parts[1];
var unprefixed = parts[2];
- var logger = LogManager.GetLogger(prefix);
-
- System.Diagnostics.Debug.WriteLine($"ERROR|{message}");
-
- logger.Error("-------------------------- Begin exception --------------------------");
- logger.Error(unprefixed);
-
- do
- {
- logger.Error($"Exception full name:\n <{e.GetType().FullName}>");
- logger.Error($"Exception message:\n <{e.Message}>");
- logger.Error($"Exception stack trace:\n <{e.StackTrace}>");
- logger.Error($"Exception source:\n <{e.Source}>");
- logger.Error($"Exception target site:\n <{e.TargetSite}>");
- logger.Error($"Exception HResult:\n <{e.HResult}>");
- e = e.InnerException;
- } while (e != null);
-
- logger.Error("-------------------------- End exception --------------------------");
+ ExceptionInternal(prefix, unprefixed, e);
}
else
{
@@ -104,62 +131,29 @@ namespace Wox.Infrastructure.Logger
}
#endif
}
-
+
+ /// example: "|prefix|unprefixed"
+ public static void Error(string message)
+ {
+ LogInternal(message, LogLevel.Error);
+ }
+
/// example: "|prefix|unprefixed"
public static void Debug(string message)
{
- if (FormatValid(message))
- {
- var parts = message.Split('|');
- var prefix = parts[1];
- var unprefixed = parts[2];
- var logger = LogManager.GetLogger(prefix);
-
- System.Diagnostics.Debug.WriteLine($"DEBUG|{message}");
- logger.Debug(unprefixed);
- }
- else
- {
- LogFaultyFormat(message);
- }
+ LogInternal(message, LogLevel.Debug);
}
/// example: "|prefix|unprefixed"
public static void Info(string message)
{
- if (FormatValid(message))
- {
- var parts = message.Split('|');
- var prefix = parts[1];
- var unprefixed = parts[2];
- var logger = LogManager.GetLogger(prefix);
-
- System.Diagnostics.Debug.WriteLine($"INFO|{message}");
- logger.Info(unprefixed);
- }
- else
- {
- LogFaultyFormat(message);
- }
+ LogInternal(message, LogLevel.Info);
}
/// example: "|prefix|unprefixed"
public static void Warn(string message)
{
- if (FormatValid(message))
- {
- var parts = message.Split('|');
- var prefix = parts[1];
- var unprefixed = parts[2];
- var logger = LogManager.GetLogger(prefix);
-
- System.Diagnostics.Debug.WriteLine($"WARN|{message}");
- logger.Warn(unprefixed);
- }
- else
- {
- LogFaultyFormat(message);
- }
+ LogInternal(message, LogLevel.Warn);
}
}
}
\ No newline at end of file
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 58ffa336fc..deff9ff7b5 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -6,13 +6,14 @@ using Wox.Infrastructure.Logger;
using Wox.Infrastructure.UserSettings;
using static Wox.Infrastructure.StringMatcher;
-namespace Wox.Infrastructure
+namespace Wox.Infrastructure
{
public static class StringMatcher
{
public static MatchOption DefaultMatchOption = new MatchOption();
- public static string UserSettingSearchPrecision { get; set; }
+ public static int UserSettingSearchPrecision { get; set; }
+
public static bool ShouldUsePinyin { get; set; }
[Obsolete("This method is obsolete and should not be used. Please use the static function StringMatcher.FuzzySearch")]
@@ -45,51 +46,106 @@ namespace Wox.Infrastructure
public static MatchResult FuzzySearch(string query, string stringToCompare, MatchOption opt)
{
if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query)) return new MatchResult { Success = false };
-
+
query = query.Trim();
- var len = stringToCompare.Length;
- var compareString = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
- var pattern = opt.IgnoreCase ? query.ToLower() : query;
+ var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
- var sb = new StringBuilder(stringToCompare.Length + (query.Length * (opt.Prefix.Length + opt.Suffix.Length)));
- var patternIdx = 0;
+ var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
+
+ int currentQueryToCompareIndex = 0;
+ var queryToCompareSeparated = queryWithoutCase.Split(' ');
+ var currentQueryToCompare = queryToCompareSeparated[currentQueryToCompareIndex];
+
+ var patternIndex = 0;
var firstMatchIndex = -1;
+ var firstMatchIndexInWord = -1;
var lastMatchIndex = 0;
- char ch;
+ bool allMatched = false;
+ bool isFullWordMatched = false;
+ bool allWordsFullyMatched = true;
var indexList = new List();
- for (var idx = 0; idx < len; idx++)
+ for (var index = 0; index < fullStringToCompareWithoutCase.Length; index++)
{
- ch = stringToCompare[idx];
- if (compareString[idx] == pattern[patternIdx])
+ var ch = stringToCompare[index];
+ if (fullStringToCompareWithoutCase[index] == currentQueryToCompare[patternIndex])
{
if (firstMatchIndex < 0)
- firstMatchIndex = idx;
- lastMatchIndex = idx + 1;
+ { // first matched char will become the start of the compared string
+ firstMatchIndex = index;
+ }
- indexList.Add(idx);
- sb.Append(opt.Prefix + ch + opt.Suffix);
- patternIdx += 1;
+ if (patternIndex == 0)
+ { // first letter of current word
+ isFullWordMatched = true;
+ firstMatchIndexInWord = index;
+ }
+ else if (!isFullWordMatched)
+ { // we want to verify that there is not a better match if this is not a full word
+ // in order to do so we need to verify all previous chars are part of the pattern
+ int startIndexToVerify = index - patternIndex;
+ bool allMatch = true;
+ for (int indexToCheck = 0; indexToCheck < patternIndex; indexToCheck++)
+ {
+ if (fullStringToCompareWithoutCase[startIndexToVerify + indexToCheck] !=
+ currentQueryToCompare[indexToCheck])
+ {
+ allMatch = false;
+ }
+ }
+
+ if (allMatch)
+ { // update to this as a full word
+ isFullWordMatched = true;
+ if (currentQueryToCompareIndex == 0)
+ { // first word so we need to update start index
+ firstMatchIndex = startIndexToVerify;
+ }
+
+ indexList.RemoveAll(x => x >= firstMatchIndexInWord);
+ for (int indexToCheck = 0; indexToCheck < patternIndex; indexToCheck++)
+ { // update the index list
+ indexList.Add(startIndexToVerify + indexToCheck);
+ }
+ }
+ }
+
+ lastMatchIndex = index + 1;
+ indexList.Add(index);
+
+ // increase the pattern matched index and check if everything was matched
+ if (++patternIndex == currentQueryToCompare.Length)
+ {
+ if (++currentQueryToCompareIndex >= queryToCompareSeparated.Length)
+ { // moved over all the words
+ allMatched = true;
+ break;
+ }
+
+ // otherwise move to the next word
+ currentQueryToCompare = queryToCompareSeparated[currentQueryToCompareIndex];
+ patternIndex = 0;
+ if (!isFullWordMatched)
+ { // if any of the words was not fully matched all are not fully matched
+ allWordsFullyMatched = false;
+ }
+ }
}
else
{
- sb.Append(ch);
- }
-
- // match success, append remain char
- if (patternIdx == pattern.Length && (idx + 1) != compareString.Length)
- {
- sb.Append(stringToCompare.Substring(idx + 1));
- break;
+ isFullWordMatched = false;
}
}
- // return rendered string if we have a match for every char
- if (patternIdx == pattern.Length)
+
+ // return rendered string if we have a match for every char or all substring without whitespaces matched
+ if (allMatched)
{
- var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex);
+ // check if all query string was contained in string to compare
+ bool containedFully = lastMatchIndex - firstMatchIndex == queryWithoutCase.Length;
+ var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, containedFully, allWordsFullyMatched);
var pinyinScore = ScoreForPinyin(stringToCompare, query);
var result = new MatchResult
@@ -105,7 +161,8 @@ namespace Wox.Infrastructure
return new MatchResult { Success = false };
}
- private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen)
+ private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen,
+ bool isFullyContained, bool allWordsFullyMatched)
{
// A match found near the beginning of a string is scored more than a match found near the end
// A match is scored more if the characters in the patterns are closer to each other,
@@ -122,6 +179,16 @@ namespace Wox.Infrastructure
score += 10;
}
+ if (isFullyContained)
+ {
+ score += 20; // honestly I'm not sure what would be a good number here or should it factor the size of the pattern
+ }
+
+ if (allWordsFullyMatched)
+ {
+ score += 20;
+ }
+
return score;
}
@@ -143,11 +210,11 @@ namespace Wox.Infrastructure
{
if (Alphabet.ContainsChinese(source))
{
- var combination = Alphabet.PinyinComination(source);
+ var combination = Alphabet.PinyinComination(source);
var pinyinScore = combination
.Select(pinyin => FuzzySearch(target, string.Join("", pinyin)).Score)
.Max();
- var acronymScore = combination.Select(Alphabet.Acronym)
+ var acronymScore = combination.Select(Alphabet.Acronym)
.Select(pinyin => FuzzySearch(target, pinyin).Score)
.Max();
var score = Math.Max(pinyinScore, acronymScore);
@@ -162,7 +229,7 @@ namespace Wox.Infrastructure
{
return 0;
}
- }
+ }
}
public class MatchResult
@@ -178,6 +245,7 @@ namespace Wox.Infrastructure
/// The raw calculated search score without any search precision filtering applied.
///
private int _rawScore;
+
public int RawScore
{
get { return _rawScore; }
@@ -200,10 +268,7 @@ namespace Wox.Infrastructure
private bool IsSearchPrecisionScoreMet(int score)
{
- var precisionScore = (SearchPrecisionScore)Enum.Parse(
- typeof(SearchPrecisionScore),
- UserSettingSearchPrecision ?? SearchPrecisionScore.Regular.ToString());
- return score >= (int)precisionScore;
+ return score >= UserSettingSearchPrecision;
}
private int ApplySearchPrecisionFilter(int score)
@@ -214,22 +279,18 @@ namespace Wox.Infrastructure
public class MatchOption
{
- public MatchOption()
- {
- Prefix = "";
- Suffix = "";
- IgnoreCase = true;
- }
-
///
/// prefix of match char, use for hightlight
///
- public string Prefix { get; set; }
+ [Obsolete("this is never used")]
+ public string Prefix { get; set; } = "";
+
///
/// suffix of match char, use for hightlight
///
- public string Suffix { get; set; }
+ [Obsolete("this is never used")]
+ public string Suffix { get; set; } = "";
- public bool IgnoreCase { get; set; }
+ public bool IgnoreCase { get; set; } = true;
}
-}
+}
\ No newline at end of file
diff --git a/Wox.Infrastructure/UserSettings/Settings.cs b/Wox.Infrastructure/UserSettings/Settings.cs
index de5a2e6624..5a129832aa 100644
--- a/Wox.Infrastructure/UserSettings/Settings.cs
+++ b/Wox.Infrastructure/UserSettings/Settings.cs
@@ -36,14 +36,27 @@ namespace Wox.Infrastructure.UserSettings
}
- private string _querySearchPrecision { get; set; } = StringMatcher.SearchPrecisionScore.Regular.ToString();
- public string QuerySearchPrecision
+ internal StringMatcher.SearchPrecisionScore QuerySearchPrecision { get; private set; } = StringMatcher.SearchPrecisionScore.Regular;
+
+ public string QuerySearchPrecisionString
{
- get { return _querySearchPrecision; }
+ get { return QuerySearchPrecision.ToString(); }
set
{
- _querySearchPrecision = value;
- StringMatcher.UserSettingSearchPrecision = value;
+ try
+ {
+ var precisionScore = (StringMatcher.SearchPrecisionScore)Enum.Parse(
+ typeof(StringMatcher.SearchPrecisionScore),
+ value);
+ QuerySearchPrecision = precisionScore;
+ StringMatcher.UserSettingSearchPrecision = (int)precisionScore;
+ }
+ catch (System.Exception e)
+ {
+ // what do we do here?!
+ Logger.Log.Exception(nameof(Settings), "Fail to set QuerySearchPrecision", e);
+ throw;
+ }
}
}
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index 21563f91f9..b5fe58cac1 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -12,17 +12,25 @@ namespace Wox.Test
[TestFixture]
public class FuzzyMatcherTest
{
+ private const string Chrome = "Chrome";
+ private const string CandyCrushSagaFromKing = "Candy Crush Saga from King";
+ private const string HelpCureHopeRaiseOnMindEntityChrome = "Help cure hope raise on mind entity Chrome";
+ private const string UninstallOrChangeProgramsOnYourComputer = "Uninstall or change programs on your computer";
+ private const string LastIsChrome = "Last is chrome";
+ private const string OneOneOneOne = "1111";
+ private const string MicrosoftSqlServerManagementStudio = "Microsoft SQL Server Management Studio";
+
public List GetSearchStrings()
=> new List
{
- "Chrome",
+ Chrome,
"Choose which programs you want Windows to use for activities like web browsing, editing photos, sending e-mail, and playing music.",
- "Help cure hope raise on mind entity Chrome ",
- "Candy Crush Saga from King",
- "Uninstall or change programs on your computer",
+ HelpCureHopeRaiseOnMindEntityChrome,
+ CandyCrushSagaFromKing,
+ UninstallOrChangeProgramsOnYourComputer,
"Add, change, and manage fonts on your computer",
- "Last is chrome",
- "1111"
+ LastIsChrome,
+ OneOneOneOne
};
public List GetPrecisionScores()
@@ -76,17 +84,17 @@ namespace Wox.Test
Assert.True(scoreResult == 0);
}
-
+
[TestCase("chr")]
[TestCase("chrom")]
- [TestCase("chrome")]
+ [TestCase("chrome")]
[TestCase("cand")]
[TestCase("cpywa")]
[TestCase("ccs")]
public void WhenGivenStringsAndAppliedPrecisionFilteringThenShouldReturnGreaterThanPrecisionScoreResults(string searchTerm)
{
var results = new List();
-
+
foreach (var str in GetSearchStrings())
{
results.Add(new Result
@@ -94,7 +102,7 @@ namespace Wox.Test
Title = str,
Score = StringMatcher.FuzzySearch(searchTerm, str).Score
});
- }
+ }
foreach (var precisionScore in GetPrecisionScores())
{
@@ -114,20 +122,23 @@ namespace Wox.Test
}
}
- [TestCase("chrome")]
- public void WhenGivenStringsForCalScoreMethodThenShouldReturnCurrentScoring(string searchTerm)
+ [TestCase]
+ public void WhenGivenStringsForCalScoreMethodThenShouldReturnCurrentScoring()
{
+ // Arrange
+ string searchTerm = "chrome"; // since this looks for specific results it will always be one case
var searchStrings = new List
{
- "Chrome",//SCORE: 107
- "Last is chrome",//SCORE: 53
- "Help cure hope raise on mind entity Chrome",//SCORE: 21
- "Uninstall or change programs on your computer", //SCORE: 15
- "Candy Crush Saga from King"//SCORE: 0
+ Chrome,//SCORE: 107
+ LastIsChrome,//SCORE: 53
+ HelpCureHopeRaiseOnMindEntityChrome,//SCORE: 21
+ UninstallOrChangeProgramsOnYourComputer, //SCORE: 15
+ CandyCrushSagaFromKing//SCORE: 0
}
.OrderByDescending(x => x)
.ToList();
+ // Act
var results = new List();
foreach (var str in searchStrings)
{
@@ -138,23 +149,23 @@ namespace Wox.Test
});
}
- var orderedResults = results.OrderByDescending(x => x.Title).ToList();
+ // Assert
+ VerifyResult(147, Chrome);
+ VerifyResult(93, LastIsChrome);
+ VerifyResult(41, HelpCureHopeRaiseOnMindEntityChrome);
+ VerifyResult(35, UninstallOrChangeProgramsOnYourComputer);
+ VerifyResult(0, CandyCrushSagaFromKing);
- Debug.WriteLine("");
- Debug.WriteLine("###############################################");
- Debug.WriteLine("SEARCHTERM: " + searchTerm);
- foreach (var item in orderedResults)
+ void VerifyResult(int expectedScore, string expectedTitle)
{
- Debug.WriteLine("SCORE: " + item.Score.ToString() + ", FoundString: " + item.Title);
+ var result = results.FirstOrDefault(x => x.Title == expectedTitle);
+ if (result == null)
+ {
+ Assert.Fail($"Fail to find result: {expectedTitle} in result list");
+ }
+
+ Assert.AreEqual(expectedScore, result.Score, $"Expected score for {expectedTitle}: {expectedScore}, Actual: {result.Score}");
}
- Debug.WriteLine("###############################################");
- Debug.WriteLine("");
-
- Assert.IsTrue(orderedResults[0].Score == 15 && orderedResults[0].Title == searchStrings[0]);
- Assert.IsTrue(orderedResults[1].Score == 53 && orderedResults[1].Title == searchStrings[1]);
- Assert.IsTrue(orderedResults[2].Score == 21 && orderedResults[2].Title == searchStrings[2]);
- Assert.IsTrue(orderedResults[3].Score == 107 && orderedResults[3].Title == searchStrings[3]);
- Assert.IsTrue(orderedResults[4].Score == 0 && orderedResults[4].Title == searchStrings[4]);
}
[TestCase("goo", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
@@ -168,24 +179,58 @@ namespace Wox.Test
[TestCase("cand", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("cand", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
public void WhenGivenDesiredPrecisionThenShouldReturnAllResultsGreaterOrEqual(
- string queryString,
- string compareString,
- int expectedPrecisionScore,
+ string queryString,
+ string compareString,
+ int expectedPrecisionScore,
bool expectedPrecisionResult)
{
- var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
- StringMatcher.UserSettingSearchPrecision = expectedPrecisionString.ToString();
+ // Arrange
+ var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
+ StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore; // this is why static state is evil...
+
+ // Act
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
- Debug.WriteLine("");
- Debug.WriteLine("###############################################");
- Debug.WriteLine($"SearchTerm: {queryString} PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})");
- Debug.WriteLine($"SCORE: {matchResult.Score.ToString()}, ComparedString: {compareString}");
- Debug.WriteLine("###############################################");
- Debug.WriteLine("");
+ // Assert
+ Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
+ $"Query:{queryString}{Environment.NewLine} " +
+ $"Compare:{compareString}{Environment.NewLine}" +
+ $"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
+ $"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}");
+ }
- var matchPrecisionResult = matchResult.IsSearchPrecisionScoreMet();
- Assert.IsTrue(matchPrecisionResult == expectedPrecisionResult);
+ [TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("term", "Windows Terminal (Preview)", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql s managa", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("sql s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql serv", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("mic", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("chr", "Shutdown", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("a test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ public void WhenGivenQueryShouldReturnResultsContainingAllQuerySubstrings(
+ string queryString,
+ string compareString,
+ int expectedPrecisionScore,
+ bool expectedPrecisionResult)
+ {
+ // Arrange
+ var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
+ StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore; // this is why static state is evil...
+
+ // Act
+ var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
+
+ // Assert
+ Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
+ $"Query:{queryString}{Environment.NewLine} " +
+ $"Compare:{compareString}{Environment.NewLine}" +
+ $"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
+ $"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}");
}
}
-}
+}
\ No newline at end of file
diff --git a/Wox/App.xaml.cs b/Wox/App.xaml.cs
index 9436df4758..aa5426d062 100644
--- a/Wox/App.xaml.cs
+++ b/Wox/App.xaml.cs
@@ -55,7 +55,7 @@ namespace Wox
Alphabet.Initialize(_settings);
- StringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
+ StringMatcher.UserSettingSearchPrecision = (int)_settings.QuerySearchPrecision;
StringMatcher.ShouldUsePinyin = _settings.ShouldUsePinyin;
PluginManager.LoadPlugins(_settings.PluginSettings);
diff --git a/Wox/SettingWindow.xaml b/Wox/SettingWindow.xaml
index 9a5146c7ee..a6f23814ff 100644
--- a/Wox/SettingWindow.xaml
+++ b/Wox/SettingWindow.xaml
@@ -62,7 +62,7 @@
+ SelectedItem="{Binding Settings.QuerySearchPrecisionString}" />
From 52615c6f52d1d483afeab31c57fa8f8895db745e Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Thu, 2 Jan 2020 08:02:23 +1100
Subject: [PATCH 02/23] WIP variables
---
Wox.Infrastructure/StringMatcher.cs | 36 ++++++++++++++++-------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index deff9ff7b5..91ac09f017 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -52,12 +52,12 @@ namespace Wox.Infrastructure
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
+
+ var separatedqueryStrings = queryWithoutCase.Split(' ');
+ int currentSeparatedQueryStringIndex = 0;
+ var currentSeparatedQueryString = separatedqueryStrings[currentSeparatedQueryStringIndex];
- int currentQueryToCompareIndex = 0;
- var queryToCompareSeparated = queryWithoutCase.Split(' ');
- var currentQueryToCompare = queryToCompareSeparated[currentQueryToCompareIndex];
-
- var patternIndex = 0;
+ var queryIndex = 0;
var firstMatchIndex = -1;
var firstMatchIndexInWord = -1;
var lastMatchIndex = 0;
@@ -70,14 +70,14 @@ namespace Wox.Infrastructure
for (var index = 0; index < fullStringToCompareWithoutCase.Length; index++)
{
var ch = stringToCompare[index];
- if (fullStringToCompareWithoutCase[index] == currentQueryToCompare[patternIndex])
+ if (fullStringToCompareWithoutCase[index] == currentSeparatedQueryString[queryIndex])
{
if (firstMatchIndex < 0)
{ // first matched char will become the start of the compared string
firstMatchIndex = index;
}
- if (patternIndex == 0)
+ if (queryIndex == 0)
{ // first letter of current word
isFullWordMatched = true;
firstMatchIndexInWord = index;
@@ -85,12 +85,12 @@ namespace Wox.Infrastructure
else if (!isFullWordMatched)
{ // we want to verify that there is not a better match if this is not a full word
// in order to do so we need to verify all previous chars are part of the pattern
- int startIndexToVerify = index - patternIndex;
+ int startIndexToVerify = index - queryIndex;
bool allMatch = true;
- for (int indexToCheck = 0; indexToCheck < patternIndex; indexToCheck++)
+ for (int indexToCheck = 0; indexToCheck < queryIndex; indexToCheck++)
{
if (fullStringToCompareWithoutCase[startIndexToVerify + indexToCheck] !=
- currentQueryToCompare[indexToCheck])
+ currentSeparatedQueryString[indexToCheck])
{
allMatch = false;
}
@@ -99,13 +99,13 @@ namespace Wox.Infrastructure
if (allMatch)
{ // update to this as a full word
isFullWordMatched = true;
- if (currentQueryToCompareIndex == 0)
+ if (currentSeparatedQueryStringIndex == 0)
{ // first word so we need to update start index
firstMatchIndex = startIndexToVerify;
}
indexList.RemoveAll(x => x >= firstMatchIndexInWord);
- for (int indexToCheck = 0; indexToCheck < patternIndex; indexToCheck++)
+ for (int indexToCheck = 0; indexToCheck < queryIndex; indexToCheck++)
{ // update the index list
indexList.Add(startIndexToVerify + indexToCheck);
}
@@ -115,18 +115,22 @@ namespace Wox.Infrastructure
lastMatchIndex = index + 1;
indexList.Add(index);
+ queryIndex++;
+
// increase the pattern matched index and check if everything was matched
- if (++patternIndex == currentQueryToCompare.Length)
+ if (queryIndex == currentSeparatedQueryString.Length)
{
- if (++currentQueryToCompareIndex >= queryToCompareSeparated.Length)
+ currentSeparatedQueryStringIndex++;
+
+ if (currentSeparatedQueryStringIndex >= separatedqueryStrings.Length)
{ // moved over all the words
allMatched = true;
break;
}
// otherwise move to the next word
- currentQueryToCompare = queryToCompareSeparated[currentQueryToCompareIndex];
- patternIndex = 0;
+ currentSeparatedQueryString = separatedqueryStrings[currentSeparatedQueryStringIndex];
+ queryIndex = 0;
if (!isFullWordMatched)
{ // if any of the words was not fully matched all are not fully matched
allWordsFullyMatched = false;
From f6d0738c79636918d141930956ecf4ebdfcbee9f Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Thu, 2 Jan 2020 08:04:16 +1100
Subject: [PATCH 03/23] debug logging
---
Wox.Test/FuzzyMatcherTest.cs | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index b5fe58cac1..3091102c75 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -191,6 +191,13 @@ namespace Wox.Test
// Act
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
+ Debug.WriteLine("");
+ Debug.WriteLine("###############################################");
+ Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
+ Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})");
+ Debug.WriteLine("###############################################");
+ Debug.WriteLine("");
+
// Assert
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
$"Query:{queryString}{Environment.NewLine} " +
@@ -225,6 +232,13 @@ namespace Wox.Test
// Act
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
+ Debug.WriteLine("");
+ Debug.WriteLine("###############################################");
+ Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
+ Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})");
+ Debug.WriteLine("###############################################");
+ Debug.WriteLine("");
+
// Assert
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
$"Query:{queryString}{Environment.NewLine} " +
From 84d6fc2787cdd6ebddbd80febc42e9e1d61e3e77 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 3 Jan 2020 07:58:20 +1100
Subject: [PATCH 04/23] Update variable names
Make variables more descriptive of the state they represent
---
Wox.Infrastructure/StringMatcher.cs | 128 +++++++++++++---------------
1 file changed, 59 insertions(+), 69 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 91ac09f017..db84d302eb 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -52,100 +52,90 @@ namespace Wox.Infrastructure
var fullStringToCompareWithoutCase = opt.IgnoreCase ? stringToCompare.ToLower() : stringToCompare;
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
-
- var separatedqueryStrings = queryWithoutCase.Split(' ');
- int currentSeparatedQueryStringIndex = 0;
- var currentSeparatedQueryString = separatedqueryStrings[currentSeparatedQueryStringIndex];
+
+ var querySubstrings = queryWithoutCase.Split(' ');
+ int currentQuerySubstringIndex = 0;
+ var currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
+ var currentQuerySubstringCharacterIndex = 0;
- var queryIndex = 0;
var firstMatchIndex = -1;
var firstMatchIndexInWord = -1;
var lastMatchIndex = 0;
- bool allMatched = false;
- bool isFullWordMatched = false;
+ bool allQuerySubstringsMatched = false;
+ bool matchFoundInPreviousLoop = false;
bool allWordsFullyMatched = true;
var indexList = new List();
- for (var index = 0; index < fullStringToCompareWithoutCase.Length; index++)
+ for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
{
- var ch = stringToCompare[index];
- if (fullStringToCompareWithoutCase[index] == currentSeparatedQueryString[queryIndex])
+ if (fullStringToCompareWithoutCase[compareStringIndex] == currentQuerySubstring[currentQuerySubstringCharacterIndex])
{
if (firstMatchIndex < 0)
- { // first matched char will become the start of the compared string
- firstMatchIndex = index;
- }
-
- if (queryIndex == 0)
- { // first letter of current word
- isFullWordMatched = true;
- firstMatchIndexInWord = index;
- }
- else if (!isFullWordMatched)
- { // we want to verify that there is not a better match if this is not a full word
- // in order to do so we need to verify all previous chars are part of the pattern
- int startIndexToVerify = index - queryIndex;
- bool allMatch = true;
- for (int indexToCheck = 0; indexToCheck < queryIndex; indexToCheck++)
- {
- if (fullStringToCompareWithoutCase[startIndexToVerify + indexToCheck] !=
- currentSeparatedQueryString[indexToCheck])
- {
- allMatch = false;
- }
- }
-
- if (allMatch)
- { // update to this as a full word
- isFullWordMatched = true;
- if (currentSeparatedQueryStringIndex == 0)
- { // first word so we need to update start index
- firstMatchIndex = startIndexToVerify;
- }
-
- indexList.RemoveAll(x => x >= firstMatchIndexInWord);
- for (int indexToCheck = 0; indexToCheck < queryIndex; indexToCheck++)
- { // update the index list
- indexList.Add(startIndexToVerify + indexToCheck);
- }
- }
- }
-
- lastMatchIndex = index + 1;
- indexList.Add(index);
-
- queryIndex++;
-
- // increase the pattern matched index and check if everything was matched
- if (queryIndex == currentSeparatedQueryString.Length)
{
- currentSeparatedQueryStringIndex++;
+ // first matched char will become the start of the compared string
+ firstMatchIndex = compareStringIndex;
+ }
- if (currentSeparatedQueryStringIndex >= separatedqueryStrings.Length)
- { // moved over all the words
- allMatched = true;
+ if (currentQuerySubstringCharacterIndex == 0)
+ {
+ // first letter of current word
+ matchFoundInPreviousLoop = true;
+ firstMatchIndexInWord = compareStringIndex;
+ }
+ else if (!matchFoundInPreviousLoop)
+ {
+ // we want to verify that there is not a better match if this is not a full word
+ // in order to do so we need to verify all previous chars are part of the pattern
+ var startIndexToVerify = compareStringIndex - currentQuerySubstringCharacterIndex;
+
+ if (AllPreviousCharsMatched(startIndexToVerify, currentQuerySubstringCharacterIndex, fullStringToCompareWithoutCase, currentQuerySubstring))
+ {
+ matchFoundInPreviousLoop = true;
+
+ // if it's the begining character of the first query substring that is matched then we need to update start index
+ firstMatchIndex = currentQuerySubstringIndex == 0 ? startIndexToVerify : firstMatchIndex;
+
+ indexList = GetUpdatedIndexList(startIndexToVerify, currentQuerySubstringCharacterIndex, firstMatchIndexInWord, indexList);
+ }
+ }
+
+ lastMatchIndex = compareStringIndex + 1;
+ indexList.Add(compareStringIndex);
+
+ currentQuerySubstringCharacterIndex++;
+
+ // if finished looping through every character in the substring
+ if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
+ {
+ currentQuerySubstringIndex++;
+
+ // if all query substrings are matched
+ if (currentQuerySubstringIndex >= querySubstrings.Length)
+ {
+ allQuerySubstringsMatched = true;
break;
}
- // otherwise move to the next word
- currentSeparatedQueryString = separatedqueryStrings[currentSeparatedQueryStringIndex];
- queryIndex = 0;
- if (!isFullWordMatched)
- { // if any of the words was not fully matched all are not fully matched
+ // otherwise move to the next query substring
+ currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
+ currentQuerySubstringCharacterIndex = 0;
+
+ if (!matchFoundInPreviousLoop)
+ {
+ // if any of the words was not fully matched all are not fully matched
allWordsFullyMatched = false;
}
}
}
else
{
- isFullWordMatched = false;
+ matchFoundInPreviousLoop = false;
}
}
-
-
+
// return rendered string if we have a match for every char or all substring without whitespaces matched
- if (allMatched)
+ if (allQuerySubstringsMatched)
{
// check if all query string was contained in string to compare
bool containedFully = lastMatchIndex - firstMatchIndex == queryWithoutCase.Length;
From 220dbd7e304ef21e44f5d7c03ec7b01392c2f2eb Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Fri, 3 Jan 2020 08:02:02 +1100
Subject: [PATCH 05/23] Move some logic into functions
- Move checking if there is a prev compare string char match into function
- Move updating of index list when a better match is found for the first substring logic into function
---
Wox.Infrastructure/StringMatcher.cs | 32 +++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index db84d302eb..e361c0c18a 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -155,6 +155,38 @@ namespace Wox.Infrastructure
return new MatchResult { Success = false };
}
+ private static bool AllPreviousCharsMatched(int startIndexToVerify, int currentQuerySubstringCharacterIndex,
+ string fullStringToCompareWithoutCase, string currentQuerySubstring)
+ {
+ var allMatch = true;
+ for (int indexToCheck = 0; indexToCheck < currentQuerySubstringCharacterIndex; indexToCheck++)
+ {
+ if (fullStringToCompareWithoutCase[startIndexToVerify + indexToCheck] !=
+ currentQuerySubstring[indexToCheck])
+ {
+ allMatch = false;
+ }
+ }
+
+ return allMatch;
+ }
+
+ private static List GetUpdatedIndexList(int startIndexToVerify, int currentQuerySubstringCharacterIndex, int firstMatchIndexInWord, List indexList)
+ {
+ var updatedList = new List();
+
+ indexList.RemoveAll(x => x >= firstMatchIndexInWord);
+
+ updatedList.AddRange(indexList);
+
+ for (int indexToCheck = 0; indexToCheck < currentQuerySubstringCharacterIndex; indexToCheck++)
+ {
+ updatedList.Add(startIndexToVerify + indexToCheck);
+ }
+
+ return updatedList;
+ }
+
private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen,
bool isFullyContained, bool allWordsFullyMatched)
{
From 42a938b50b6382ba6248a346436f0bbcf99462e6 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 6 Jan 2020 19:15:05 +1100
Subject: [PATCH 06/23] Simplify IfElse
---
Wox.Infrastructure/StringMatcher.cs | 119 ++++++++++++++--------------
1 file changed, 59 insertions(+), 60 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index e361c0c18a..0b0767f583 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -69,68 +69,67 @@ namespace Wox.Infrastructure
for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
{
- if (fullStringToCompareWithoutCase[compareStringIndex] == currentQuerySubstring[currentQuerySubstringCharacterIndex])
- {
- if (firstMatchIndex < 0)
- {
- // first matched char will become the start of the compared string
- firstMatchIndex = compareStringIndex;
- }
-
- if (currentQuerySubstringCharacterIndex == 0)
- {
- // first letter of current word
- matchFoundInPreviousLoop = true;
- firstMatchIndexInWord = compareStringIndex;
- }
- else if (!matchFoundInPreviousLoop)
- {
- // we want to verify that there is not a better match if this is not a full word
- // in order to do so we need to verify all previous chars are part of the pattern
- var startIndexToVerify = compareStringIndex - currentQuerySubstringCharacterIndex;
-
- if (AllPreviousCharsMatched(startIndexToVerify, currentQuerySubstringCharacterIndex, fullStringToCompareWithoutCase, currentQuerySubstring))
- {
- matchFoundInPreviousLoop = true;
-
- // if it's the begining character of the first query substring that is matched then we need to update start index
- firstMatchIndex = currentQuerySubstringIndex == 0 ? startIndexToVerify : firstMatchIndex;
-
- indexList = GetUpdatedIndexList(startIndexToVerify, currentQuerySubstringCharacterIndex, firstMatchIndexInWord, indexList);
- }
- }
-
- lastMatchIndex = compareStringIndex + 1;
- indexList.Add(compareStringIndex);
-
- currentQuerySubstringCharacterIndex++;
-
- // if finished looping through every character in the substring
- if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
- {
- currentQuerySubstringIndex++;
-
- // if all query substrings are matched
- if (currentQuerySubstringIndex >= querySubstrings.Length)
- {
- allQuerySubstringsMatched = true;
- break;
- }
-
- // otherwise move to the next query substring
- currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
- currentQuerySubstringCharacterIndex = 0;
-
- if (!matchFoundInPreviousLoop)
- {
- // if any of the words was not fully matched all are not fully matched
- allWordsFullyMatched = false;
- }
- }
- }
- else
+ if (fullStringToCompareWithoutCase[compareStringIndex] != currentQuerySubstring[currentQuerySubstringCharacterIndex])
{
matchFoundInPreviousLoop = false;
+ continue;
+ }
+
+ if (firstMatchIndex < 0)
+ {
+ // first matched char will become the start of the compared string
+ firstMatchIndex = compareStringIndex;
+ }
+
+ if (currentQuerySubstringCharacterIndex == 0)
+ {
+ // first letter of current word
+ matchFoundInPreviousLoop = true;
+ firstMatchIndexInWord = compareStringIndex;
+ }
+ else if (!matchFoundInPreviousLoop)
+ {
+ // we want to verify that there is not a better match if this is not a full word
+ // in order to do so we need to verify all previous chars are part of the pattern
+ var startIndexToVerify = compareStringIndex - currentQuerySubstringCharacterIndex;
+
+ if (AllPreviousCharsMatched(startIndexToVerify, currentQuerySubstringCharacterIndex, fullStringToCompareWithoutCase, currentQuerySubstring))
+ {
+ matchFoundInPreviousLoop = true;
+
+ // if it's the begining character of the first query substring that is matched then we need to update start index
+ firstMatchIndex = currentQuerySubstringIndex == 0 ? startIndexToVerify : firstMatchIndex;
+
+ indexList = GetUpdatedIndexList(startIndexToVerify, currentQuerySubstringCharacterIndex, firstMatchIndexInWord, indexList);
+ }
+ }
+
+ lastMatchIndex = compareStringIndex + 1;
+ indexList.Add(compareStringIndex);
+
+ currentQuerySubstringCharacterIndex++;
+
+ // if finished looping through every character in the substring
+ if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
+ {
+ currentQuerySubstringIndex++;
+
+ // if all query substrings are matched
+ if (currentQuerySubstringIndex >= querySubstrings.Length)
+ {
+ allQuerySubstringsMatched = true;
+ break;
+ }
+
+ // otherwise move to the next query substring
+ currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
+ currentQuerySubstringCharacterIndex = 0;
+
+ if (!matchFoundInPreviousLoop)
+ {
+ // if any of the words was not fully matched all are not fully matched
+ allWordsFullyMatched = false;
+ }
}
}
From e453dceacdb2be2db06c01bfeed505722640fdb8 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 6 Jan 2020 20:51:27 +1100
Subject: [PATCH 07/23] Move condition checking into functions
- Moved if statement that checks if all query substrings are matched into a funciton
- convert into shorthand expression the if statement that checks if all words are fully matched
---
Wox.Infrastructure/StringMatcher.cs | 23 +++++++++++------------
1 file changed, 11 insertions(+), 12 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 0b0767f583..2d74c2f127 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -109,34 +109,28 @@ namespace Wox.Infrastructure
currentQuerySubstringCharacterIndex++;
- // if finished looping through every character in the substring
+ // if finished looping through every character in the current substring
if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
{
currentQuerySubstringIndex++;
- // if all query substrings are matched
- if (currentQuerySubstringIndex >= querySubstrings.Length)
- {
- allQuerySubstringsMatched = true;
+ allQuerySubstringsMatched = AllQuerySubstringsMatched(currentQuerySubstringIndex, querySubstrings.Length);
+ if (allQuerySubstringsMatched)
break;
- }
// otherwise move to the next query substring
currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
currentQuerySubstringCharacterIndex = 0;
- if (!matchFoundInPreviousLoop)
- {
- // if any of the words was not fully matched all are not fully matched
- allWordsFullyMatched = false;
- }
+ // if any of the substrings was not matched then consider as all are not matched
+ allWordsFullyMatched = !matchFoundInPreviousLoop ? false : allWordsFullyMatched;
}
}
// return rendered string if we have a match for every char or all substring without whitespaces matched
if (allQuerySubstringsMatched)
{
- // check if all query string was contained in string to compare
+ // check if all query substrings were contained in the string to compare
bool containedFully = lastMatchIndex - firstMatchIndex == queryWithoutCase.Length;
var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, containedFully, allWordsFullyMatched);
var pinyinScore = ScoreForPinyin(stringToCompare, query);
@@ -186,6 +180,11 @@ namespace Wox.Infrastructure
return updatedList;
}
+ private static bool AllQuerySubstringsMatched(int currentQuerySubstringIndex, int querySubstringsLength)
+ {
+ return currentQuerySubstringIndex >= querySubstringsLength;
+ }
+
private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen,
bool isFullyContained, bool allWordsFullyMatched)
{
From 04b0f8b2a4cbfb427a9b8067ebacf11e03204511 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 6 Jan 2020 21:06:41 +1100
Subject: [PATCH 08/23] Remove fuzzy match github repo reference + add logic
context in summary
1. Remove the github repo reference as we have mixed in substring matching
2. Added context on how the logic is run
---
Wox.Infrastructure/StringMatcher.cs | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 2d74c2f127..d71dddb235 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -41,7 +41,13 @@ namespace Wox.Infrastructure
}
///
- /// refer to https://github.com/mattyork/fuzzy
+ /// Current method:
+ /// Character matching + substring matching;
+ /// 1. Check query substring's character against full compare string,
+ /// 2. if matched, loop back to verify the previous character.
+ /// 3. If previous character also matches, and is the start of the substring, update list.
+ /// 4. Once the previous character is verified, move on to the next character in the query substring.
+ /// 5. Consider success and move onto scoring if every char or substring without whitespaces matched
///
public static MatchResult FuzzySearch(string query, string stringToCompare, MatchOption opt)
{
@@ -127,7 +133,7 @@ namespace Wox.Infrastructure
}
}
- // return rendered string if we have a match for every char or all substring without whitespaces matched
+ // return rendered string if every char or substring without whitespaces matched
if (allQuerySubstringsMatched)
{
// check if all query substrings were contained in the string to compare
From 19911d9f1f0d3d5cc9f5d370f46105f93589f162 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 6 Jan 2020 21:19:15 +1100
Subject: [PATCH 09/23] Update comment only
---
Wox.Infrastructure/StringMatcher.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index d71dddb235..902490e2af 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -133,7 +133,7 @@ namespace Wox.Infrastructure
}
}
- // return rendered string if every char or substring without whitespaces matched
+ // proceed to calculate score if every char or substring without whitespaces matched
if (allQuerySubstringsMatched)
{
// check if all query substrings were contained in the string to compare
From 5040f09f0c149db2be2210241cec10c0aede2f56 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Mon, 6 Jan 2020 21:38:07 +1100
Subject: [PATCH 10/23] Update method summary only
---
Wox.Infrastructure/StringMatcher.cs | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 902490e2af..cfdb0880ac 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -41,13 +41,15 @@ namespace Wox.Infrastructure
}
///
- /// Current method:
+ /// Current method:
/// Character matching + substring matching;
- /// 1. Check query substring's character against full compare string,
- /// 2. if matched, loop back to verify the previous character.
- /// 3. If previous character also matches, and is the start of the substring, update list.
- /// 4. Once the previous character is verified, move on to the next character in the query substring.
- /// 5. Consider success and move onto scoring if every char or substring without whitespaces matched
+ /// 1. Query search string is split into substrings, separator is whitespace.
+ /// 2. Check each query substring's characters against full compare string,
+ /// 3. if a character in the substring is matched, loop back to verify the previous character.
+ /// 4. If previous character also matches, and is the start of the substring, update list.
+ /// 5. Once the previous character is verified, move on to the next character in the query substring.
+ /// 6. Move onto the next substring's characters until all substrings are checked.
+ /// 7. Consider success and move onto scoring if every char or substring without whitespaces matched
///
public static MatchResult FuzzySearch(string query, string stringToCompare, MatchOption opt)
{
From e4b017b3040444f11d6af27b613e56b1acbd9999 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 05:59:47 +1100
Subject: [PATCH 11/23] fix index out of range exception
occurs when query contains more than one whitespace eg. 'sql manag'
---
Wox.Infrastructure/StringMatcher.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index cfdb0880ac..d8c6ae2155 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -61,7 +61,7 @@ namespace Wox.Infrastructure
var queryWithoutCase = opt.IgnoreCase ? query.ToLower() : query;
- var querySubstrings = queryWithoutCase.Split(' ');
+ var querySubstrings = queryWithoutCase.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
int currentQuerySubstringIndex = 0;
var currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
var currentQuerySubstringCharacterIndex = 0;
From 13996740e032d8568aebbc64a4e91e9220609b06 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 07:12:34 +1100
Subject: [PATCH 12/23] Add additional test which should pass for regular
precision
---
Wox.Test/FuzzyMatcherTest.cs | 1 +
1 file changed, 1 insertion(+)
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index 3091102c75..7eb16c8a0c 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -214,6 +214,7 @@ namespace Wox.Test
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql serv", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql studio", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("mic", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Shutdown", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
From dde658a514eb504c0d0aa5ec99ba6e26295869de Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 07:22:00 +1100
Subject: [PATCH 13/23] rename variable state allWordsFullyMatched
---
Wox.Infrastructure/StringMatcher.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index d8c6ae2155..45fbe5808a 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -71,7 +71,7 @@ namespace Wox.Infrastructure
var lastMatchIndex = 0;
bool allQuerySubstringsMatched = false;
bool matchFoundInPreviousLoop = false;
- bool allWordsFullyMatched = true;
+ bool allSubstringsContainedInCompareString = true;
var indexList = new List();
@@ -131,7 +131,7 @@ namespace Wox.Infrastructure
currentQuerySubstringCharacterIndex = 0;
// if any of the substrings was not matched then consider as all are not matched
- allWordsFullyMatched = !matchFoundInPreviousLoop ? false : allWordsFullyMatched;
+ allSubstringsContainedInCompareString = !matchFoundInPreviousLoop ? false : allSubstringsContainedInCompareString;
}
}
@@ -140,7 +140,7 @@ namespace Wox.Infrastructure
{
// check if all query substrings were contained in the string to compare
bool containedFully = lastMatchIndex - firstMatchIndex == queryWithoutCase.Length;
- var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, containedFully, allWordsFullyMatched);
+ var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, containedFully, allSubstringsContainedInCompareString);
var pinyinScore = ScoreForPinyin(stringToCompare, query);
var result = new MatchResult
From 0093838a7535b92f996170e3dc090fd284b0207e Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 07:25:13 +1100
Subject: [PATCH 14/23] fix variable state which failed to represent correctly
Failed if query text is 'sql servman'- returns true when should be false
- moved it up so evaluation is included in the final substring check
---
Wox.Infrastructure/StringMatcher.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 45fbe5808a..1868eee6e1 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -120,6 +120,9 @@ namespace Wox.Infrastructure
// if finished looping through every character in the current substring
if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
{
+ // if any of the substrings was not matched then consider as all are not matched
+ allSubstringsContainedInCompareString = !matchFoundInPreviousLoop ? false : allSubstringsContainedInCompareString;
+
currentQuerySubstringIndex++;
allQuerySubstringsMatched = AllQuerySubstringsMatched(currentQuerySubstringIndex, querySubstrings.Length);
@@ -129,9 +132,6 @@ namespace Wox.Infrastructure
// otherwise move to the next query substring
currentQuerySubstring = querySubstrings[currentQuerySubstringIndex];
currentQuerySubstringCharacterIndex = 0;
-
- // if any of the substrings was not matched then consider as all are not matched
- allSubstringsContainedInCompareString = !matchFoundInPreviousLoop ? false : allSubstringsContainedInCompareString;
}
}
From 24cc5dbaa0930e4ea6176c99410175745e566c57 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 07:55:02 +1100
Subject: [PATCH 15/23] Add unit tests for checking substrings
checking if all substrings contained in compareString
---
Wox.Infrastructure/StringMatcher.cs | 8 +++++++-
Wox.Test/FuzzyMatcherTest.cs | 16 ++++++++++++++++
2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 1868eee6e1..a5162c2813 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -147,7 +147,8 @@ namespace Wox.Infrastructure
{
Success = true,
MatchData = indexList,
- RawScore = Math.Max(score, pinyinScore)
+ RawScore = Math.Max(score, pinyinScore),
+ AllSubstringsContainedInCompareString = allSubstringsContainedInCompareString
};
return result;
@@ -288,6 +289,11 @@ namespace Wox.Infrastructure
}
}
+ ///
+ /// Indicates if all query's substrings are contained in the string to compare
+ ///
+ public bool AllSubstringsContainedInCompareString { get; set; }
+
///
/// Matched data to highlight.
///
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index 7eb16c8a0c..660a8ff96d 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -247,5 +247,21 @@ namespace Wox.Test
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
$"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}");
}
+
+ [TestCase("sql servman", MicrosoftSqlServerManagementStudio, false)]
+ [TestCase("sql serv man", MicrosoftSqlServerManagementStudio, true)]
+ [TestCase("sql", MicrosoftSqlServerManagementStudio, true)]
+ [TestCase("sqlserv", MicrosoftSqlServerManagementStudio, false)]
+ [TestCase("mssms", MicrosoftSqlServerManagementStudio, false)]
+ [TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", false)]
+ [TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", true)]
+ public void WhenGivenQueryShouldEvaluateTrueFalseIfCompareStringContainsAllSubstrings(string queryString, string compareString, bool expectedResult)
+ {
+ // When, Given
+ var matchResult = StringMatcher.FuzzySearch(queryString, compareString).AllSubstringsContainedInCompareString;
+
+ // Should
+ Assert.AreEqual(matchResult, expectedResult);
+ }
}
}
\ No newline at end of file
From 78a20865350e6994105e1185b496e211d289a49f Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 08:04:56 +1100
Subject: [PATCH 16/23] Remove containedFully variable state
Not necessary to have and not needed to add another dimension to the scoring
---
Wox.Infrastructure/StringMatcher.cs | 12 ++----------
1 file changed, 2 insertions(+), 10 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index a5162c2813..27f99b2a61 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -138,9 +138,7 @@ namespace Wox.Infrastructure
// proceed to calculate score if every char or substring without whitespaces matched
if (allQuerySubstringsMatched)
{
- // check if all query substrings were contained in the string to compare
- bool containedFully = lastMatchIndex - firstMatchIndex == queryWithoutCase.Length;
- var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, containedFully, allSubstringsContainedInCompareString);
+ var score = CalculateSearchScore(query, stringToCompare, firstMatchIndex, lastMatchIndex - firstMatchIndex, allSubstringsContainedInCompareString);
var pinyinScore = ScoreForPinyin(stringToCompare, query);
var result = new MatchResult
@@ -194,8 +192,7 @@ namespace Wox.Infrastructure
return currentQuerySubstringIndex >= querySubstringsLength;
}
- private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen,
- bool isFullyContained, bool allWordsFullyMatched)
+ private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen, bool allWordsFullyMatched)
{
// A match found near the beginning of a string is scored more than a match found near the end
// A match is scored more if the characters in the patterns are closer to each other,
@@ -212,11 +209,6 @@ namespace Wox.Infrastructure
score += 10;
}
- if (isFullyContained)
- {
- score += 20; // honestly I'm not sure what would be a good number here or should it factor the size of the pattern
- }
-
if (allWordsFullyMatched)
{
score += 20;
From b54241a5b27d4802e976f2f1b9571a4c4d6f2d36 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 08:28:27 +1100
Subject: [PATCH 17/23] Update scoring for all substrings contained in compare
string
---
Wox.Infrastructure/StringMatcher.cs | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 27f99b2a61..45d65549a4 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -192,7 +192,7 @@ namespace Wox.Infrastructure
return currentQuerySubstringIndex >= querySubstringsLength;
}
- private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen, bool allWordsFullyMatched)
+ private static int CalculateSearchScore(string query, string stringToCompare, int firstIndex, int matchLen, bool allSubstringsContainedInCompareString)
{
// A match found near the beginning of a string is scored more than a match found near the end
// A match is scored more if the characters in the patterns are closer to each other,
@@ -209,10 +209,8 @@ namespace Wox.Infrastructure
score += 10;
}
- if (allWordsFullyMatched)
- {
- score += 20;
- }
+ if (allSubstringsContainedInCompareString)
+ score += 10 * string.Concat(query.Where(c => !char.IsWhiteSpace(c))).Count();
return score;
}
From 2a49b3899aa9f62af3484ca86055a99f35ded274 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 20:26:26 +1100
Subject: [PATCH 18/23] Update tests
Two scoring changes only as a result of substring matching.
---
Wox.Test/FuzzyMatcherTest.cs | 80 +++++++++++-------------------------
1 file changed, 24 insertions(+), 56 deletions(-)
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index 660a8ff96d..1d3d16c958 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -122,50 +122,20 @@ namespace Wox.Test
}
}
- [TestCase]
- public void WhenGivenStringsForCalScoreMethodThenShouldReturnCurrentScoring()
+ [TestCase(Chrome, Chrome, 167)]
+ [TestCase(Chrome, LastIsChrome, 113)]
+ [TestCase(Chrome, HelpCureHopeRaiseOnMindEntityChrome, 21)]
+ [TestCase(Chrome, UninstallOrChangeProgramsOnYourComputer, 15)]
+ [TestCase(Chrome, CandyCrushSagaFromKing, 0)]
+ [TestCase("sql", MicrosoftSqlServerManagementStudio, 56)]
+ [TestCase("sql manag", MicrosoftSqlServerManagementStudio, 119)]//double spacing intended
+ public void WhenGivenQueryStringThenShouldReturnCurrentScoring(string queryString, string compareString, int expectedScore)
{
- // Arrange
- string searchTerm = "chrome"; // since this looks for specific results it will always be one case
- var searchStrings = new List
- {
- Chrome,//SCORE: 107
- LastIsChrome,//SCORE: 53
- HelpCureHopeRaiseOnMindEntityChrome,//SCORE: 21
- UninstallOrChangeProgramsOnYourComputer, //SCORE: 15
- CandyCrushSagaFromKing//SCORE: 0
- }
- .OrderByDescending(x => x)
- .ToList();
+ // When, Given
+ var rawScore = StringMatcher.FuzzySearch(queryString, compareString).RawScore;
- // Act
- var results = new List();
- foreach (var str in searchStrings)
- {
- results.Add(new Result
- {
- Title = str,
- Score = StringMatcher.FuzzySearch(searchTerm, str).RawScore
- });
- }
-
- // Assert
- VerifyResult(147, Chrome);
- VerifyResult(93, LastIsChrome);
- VerifyResult(41, HelpCureHopeRaiseOnMindEntityChrome);
- VerifyResult(35, UninstallOrChangeProgramsOnYourComputer);
- VerifyResult(0, CandyCrushSagaFromKing);
-
- void VerifyResult(int expectedScore, string expectedTitle)
- {
- var result = results.FirstOrDefault(x => x.Title == expectedTitle);
- if (result == null)
- {
- Assert.Fail($"Fail to find result: {expectedTitle} in result list");
- }
-
- Assert.AreEqual(expectedScore, result.Score, $"Expected score for {expectedTitle}: {expectedScore}, Actual: {result.Score}");
- }
+ // Should
+ Assert.AreEqual(expectedScore, rawScore, $"Expected score for compare string '{compareString}': {expectedScore}, Actual: {rawScore}");
}
[TestCase("goo", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
@@ -184,26 +154,25 @@ namespace Wox.Test
int expectedPrecisionScore,
bool expectedPrecisionResult)
{
- // Arrange
- var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
- StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore; // this is why static state is evil...
+ // When
+ StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore;
- // Act
+ // Given
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
Debug.WriteLine("");
Debug.WriteLine("###############################################");
Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
- Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})");
+ Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore} ({expectedPrecisionScore})");
Debug.WriteLine("###############################################");
Debug.WriteLine("");
- // Assert
+ // Should
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
$"Query:{queryString}{Environment.NewLine} " +
$"Compare:{compareString}{Environment.NewLine}" +
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
- $"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}");
+ $"Precision Level: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore}={expectedPrecisionScore}");
}
[TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
@@ -226,26 +195,25 @@ namespace Wox.Test
int expectedPrecisionScore,
bool expectedPrecisionResult)
{
- // Arrange
- var expectedPrecisionString = (StringMatcher.SearchPrecisionScore)expectedPrecisionScore;
- StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore; // this is why static state is evil...
+ // When
+ StringMatcher.UserSettingSearchPrecision = expectedPrecisionScore;
- // Act
+ // Given
var matchResult = StringMatcher.FuzzySearch(queryString, compareString);
Debug.WriteLine("");
Debug.WriteLine("###############################################");
Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
- Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionString} ({expectedPrecisionScore})");
+ Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore} ({expectedPrecisionScore})");
Debug.WriteLine("###############################################");
Debug.WriteLine("");
- // Assert
+ // Should
Assert.AreEqual(expectedPrecisionResult, matchResult.IsSearchPrecisionScoreMet(),
$"Query:{queryString}{Environment.NewLine} " +
$"Compare:{compareString}{Environment.NewLine}" +
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
- $"Precision Level: {expectedPrecisionString}={expectedPrecisionScore}");
+ $"Precision Level: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore}={expectedPrecisionScore}");
}
[TestCase("sql servman", MicrosoftSqlServerManagementStudio, false)]
From 76727d09bf618ad086b6d2f133b532347819e086 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 7 Jan 2020 22:30:36 +1100
Subject: [PATCH 19/23] Update StringMatcher's UserSettingSearchPrecision
property type
makes more sense and less conversion to int for actual precision score
---
Wox.Infrastructure/StringMatcher.cs | 4 +-
Wox.Infrastructure/UserSettings/Settings.cs | 17 +++---
Wox.Test/FuzzyMatcherTest.cs | 61 ++++++++++-----------
Wox/App.xaml.cs | 2 +-
Wox/ViewModel/SettingWindowViewModel.cs | 2 +-
5 files changed, 44 insertions(+), 42 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 45d65549a4..9c667ced07 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -12,7 +12,7 @@ namespace Wox.Infrastructure
{
public static MatchOption DefaultMatchOption = new MatchOption();
- public static int UserSettingSearchPrecision { get; set; }
+ public static SearchPrecisionScore UserSettingSearchPrecision { get; set; }
public static bool ShouldUsePinyin { get; set; }
@@ -296,7 +296,7 @@ namespace Wox.Infrastructure
private bool IsSearchPrecisionScoreMet(int score)
{
- return score >= UserSettingSearchPrecision;
+ return score >= (int)UserSettingSearchPrecision;
}
private int ApplySearchPrecisionFilter(int score)
diff --git a/Wox.Infrastructure/UserSettings/Settings.cs b/Wox.Infrastructure/UserSettings/Settings.cs
index 5a129832aa..b11ec069ca 100644
--- a/Wox.Infrastructure/UserSettings/Settings.cs
+++ b/Wox.Infrastructure/UserSettings/Settings.cs
@@ -45,16 +45,19 @@ namespace Wox.Infrastructure.UserSettings
{
try
{
- var precisionScore = (StringMatcher.SearchPrecisionScore)Enum.Parse(
- typeof(StringMatcher.SearchPrecisionScore),
- value);
+ var precisionScore = (StringMatcher.SearchPrecisionScore)Enum
+ .Parse(typeof(StringMatcher.SearchPrecisionScore), value);
+
QuerySearchPrecision = precisionScore;
- StringMatcher.UserSettingSearchPrecision = (int)precisionScore;
+ StringMatcher.UserSettingSearchPrecision = precisionScore;
}
- catch (System.Exception e)
+ catch (ArgumentException e)
{
- // what do we do here?!
- Logger.Log.Exception(nameof(Settings), "Fail to set QuerySearchPrecision", e);
+ Logger.Log.Exception(nameof(Settings), "Failed to load QuerySearchPrecisionString value from Settings file", e);
+
+ QuerySearchPrecision = StringMatcher.SearchPrecisionScore.Regular;
+ StringMatcher.UserSettingSearchPrecision = StringMatcher.SearchPrecisionScore.Regular;
+
throw;
}
}
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index 1d3d16c958..1a82559874 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -4,7 +4,6 @@ using System.Diagnostics;
using System.Linq;
using NUnit.Framework;
using Wox.Infrastructure;
-using Wox.Infrastructure.UserSettings;
using Wox.Plugin;
namespace Wox.Test
@@ -138,20 +137,20 @@ namespace Wox.Test
Assert.AreEqual(expectedScore, rawScore, $"Expected score for compare string '{compareString}': {expectedScore}, Actual: {rawScore}");
}
- [TestCase("goo", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("chr", "Google Chrome", (int)StringMatcher.SearchPrecisionScore.Low, true)]
- [TestCase("chr", "Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("chr", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
- [TestCase("chr", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Low, true)]
- [TestCase("chr", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
- [TestCase("chr", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.None, true)]
- [TestCase("ccs", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Low, true)]
- [TestCase("cand", "Candy Crush Saga from King", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("cand", "Help cure hope raise on mind entity Chrome", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("goo", "Google Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("chr", "Google Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
+ [TestCase("chr", "Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
+ [TestCase("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.None, true)]
+ [TestCase("ccs", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.Low, true)]
+ [TestCase("cand", "Candy Crush Saga from King",StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("cand", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, false)]
public void WhenGivenDesiredPrecisionThenShouldReturnAllResultsGreaterOrEqual(
string queryString,
string compareString,
- int expectedPrecisionScore,
+ StringMatcher.SearchPrecisionScore expectedPrecisionScore,
bool expectedPrecisionResult)
{
// When
@@ -163,7 +162,7 @@ namespace Wox.Test
Debug.WriteLine("");
Debug.WriteLine("###############################################");
Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
- Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore} ({expectedPrecisionScore})");
+ Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionScore} ({(int)expectedPrecisionScore})");
Debug.WriteLine("###############################################");
Debug.WriteLine("");
@@ -172,27 +171,27 @@ namespace Wox.Test
$"Query:{queryString}{Environment.NewLine} " +
$"Compare:{compareString}{Environment.NewLine}" +
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
- $"Precision Level: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore}={expectedPrecisionScore}");
+ $"Precision Score: {(int)expectedPrecisionScore}");
}
- [TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
- [TestCase("term", "Windows Terminal (Preview)", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("sql s managa", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
- [TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, false)]
- [TestCase("sql s manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("sql manag", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("sql", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("sql serv", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("sql studio", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("mic", MicrosoftSqlServerManagementStudio, (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("chr", "Shutdown", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
- [TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", (int)StringMatcher.SearchPrecisionScore.Regular, false)]
- [TestCase("a test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
- [TestCase("test", "This is a test", (int)StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("exce", "OverLeaf-Latex: An online LaTeX editor", StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("term", "Windows Terminal (Preview)", StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql s managa", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("sql' s manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("sql s manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql serv", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sql studio", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("mic", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("chr", "Shutdown", StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("a test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
public void WhenGivenQueryShouldReturnResultsContainingAllQuerySubstrings(
string queryString,
string compareString,
- int expectedPrecisionScore,
+ StringMatcher.SearchPrecisionScore expectedPrecisionScore,
bool expectedPrecisionResult)
{
// When
@@ -204,7 +203,7 @@ namespace Wox.Test
Debug.WriteLine("");
Debug.WriteLine("###############################################");
Debug.WriteLine($"QueryString: {queryString} CompareString: {compareString}");
- Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore} ({expectedPrecisionScore})");
+ Debug.WriteLine($"RAW SCORE: {matchResult.RawScore.ToString()}, PrecisionLevelSetAt: {expectedPrecisionScore} ({(int)expectedPrecisionScore})");
Debug.WriteLine("###############################################");
Debug.WriteLine("");
@@ -213,7 +212,7 @@ namespace Wox.Test
$"Query:{queryString}{Environment.NewLine} " +
$"Compare:{compareString}{Environment.NewLine}" +
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
- $"Precision Level: {(StringMatcher.SearchPrecisionScore)expectedPrecisionScore}={expectedPrecisionScore}");
+ $"Precision Score: {(int)expectedPrecisionScore}");
}
[TestCase("sql servman", MicrosoftSqlServerManagementStudio, false)]
diff --git a/Wox/App.xaml.cs b/Wox/App.xaml.cs
index aa5426d062..9436df4758 100644
--- a/Wox/App.xaml.cs
+++ b/Wox/App.xaml.cs
@@ -55,7 +55,7 @@ namespace Wox
Alphabet.Initialize(_settings);
- StringMatcher.UserSettingSearchPrecision = (int)_settings.QuerySearchPrecision;
+ StringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;
StringMatcher.ShouldUsePinyin = _settings.ShouldUsePinyin;
PluginManager.LoadPlugins(_settings.PluginSettings);
diff --git a/Wox/ViewModel/SettingWindowViewModel.cs b/Wox/ViewModel/SettingWindowViewModel.cs
index 67b8d7af06..19a31be58c 100644
--- a/Wox/ViewModel/SettingWindowViewModel.cs
+++ b/Wox/ViewModel/SettingWindowViewModel.cs
@@ -73,7 +73,7 @@ namespace Wox.ViewModel
public List QuerySearchPrecisionStrings
{
get
- {
+ {
var precisionStrings = new List();
var enumList = Enum.GetValues(typeof(StringMatcher.SearchPrecisionScore)).Cast().ToList();
From 60959338479f44e4982604fbcad54d45df609482 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 14 Jan 2020 07:29:21 +1100
Subject: [PATCH 20/23] simplify condition as per comment
---
Wox.Infrastructure/StringMatcher.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 9c667ced07..a82d58582c 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -121,7 +121,7 @@ namespace Wox.Infrastructure
if (currentQuerySubstringCharacterIndex == currentQuerySubstring.Length)
{
// if any of the substrings was not matched then consider as all are not matched
- allSubstringsContainedInCompareString = !matchFoundInPreviousLoop ? false : allSubstringsContainedInCompareString;
+ allSubstringsContainedInCompareString = matchFoundInPreviousLoop && allSubstringsContainedInCompareString;
currentQuerySubstringIndex++;
From 71d8c2080c9e1fd5f534e351ee500e63b35ee375 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 14 Jan 2020 07:30:40 +1100
Subject: [PATCH 21/23] update comment typo
---
Wox.Infrastructure/StringMatcher.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index a82d58582c..c4d340efa7 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -105,7 +105,7 @@ namespace Wox.Infrastructure
{
matchFoundInPreviousLoop = true;
- // if it's the begining character of the first query substring that is matched then we need to update start index
+ // if it's the beginning character of the first query substring that is matched then we need to update start index
firstMatchIndex = currentQuerySubstringIndex == 0 ? startIndexToVerify : firstMatchIndex;
indexList = GetUpdatedIndexList(startIndexToVerify, currentQuerySubstringCharacterIndex, firstMatchIndexInWord, indexList);
From 592f1cafdbfce0282a63faec0a98163bc353e813 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 14 Jan 2020 07:36:53 +1100
Subject: [PATCH 22/23] update allSubstringsContainedInCompareString
calculation as per comment
---
Wox.Infrastructure/StringMatcher.cs | 6 +++++-
Wox.Test/FuzzyMatcherTest.cs | 6 +++---
2 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index c4d340efa7..5d5a9b9a8c 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -210,7 +210,11 @@ namespace Wox.Infrastructure
}
if (allSubstringsContainedInCompareString)
- score += 10 * string.Concat(query.Where(c => !char.IsWhiteSpace(c))).Count();
+ {
+ int count = query.Count(c => !char.IsWhiteSpace(c));
+ int factor = count < 4 ? 10 : 5;
+ score += factor * count;
+ }
return score;
}
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index 1a82559874..b7e0374f04 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -121,13 +121,13 @@ namespace Wox.Test
}
}
- [TestCase(Chrome, Chrome, 167)]
- [TestCase(Chrome, LastIsChrome, 113)]
+ [TestCase(Chrome, Chrome, 137)]
+ [TestCase(Chrome, LastIsChrome, 83)]
[TestCase(Chrome, HelpCureHopeRaiseOnMindEntityChrome, 21)]
[TestCase(Chrome, UninstallOrChangeProgramsOnYourComputer, 15)]
[TestCase(Chrome, CandyCrushSagaFromKing, 0)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, 56)]
- [TestCase("sql manag", MicrosoftSqlServerManagementStudio, 119)]//double spacing intended
+ [TestCase("sql manag", MicrosoftSqlServerManagementStudio, 79)]//double spacing intended
public void WhenGivenQueryStringThenShouldReturnCurrentScoring(string queryString, string compareString, int expectedScore)
{
// When, Given
From 504c08a0fc5128e608e3f341330c306bee574105 Mon Sep 17 00:00:00 2001
From: Jeremy Wu
Date: Tue, 14 Jan 2020 07:53:59 +1100
Subject: [PATCH 23/23] Update test per comment
---
Wox.Infrastructure/StringMatcher.cs | 8 +-------
Wox.Test/FuzzyMatcherTest.cs | 21 +++++----------------
2 files changed, 6 insertions(+), 23 deletions(-)
diff --git a/Wox.Infrastructure/StringMatcher.cs b/Wox.Infrastructure/StringMatcher.cs
index 5d5a9b9a8c..d1cc1fdecb 100644
--- a/Wox.Infrastructure/StringMatcher.cs
+++ b/Wox.Infrastructure/StringMatcher.cs
@@ -145,8 +145,7 @@ namespace Wox.Infrastructure
{
Success = true,
MatchData = indexList,
- RawScore = Math.Max(score, pinyinScore),
- AllSubstringsContainedInCompareString = allSubstringsContainedInCompareString
+ RawScore = Math.Max(score, pinyinScore)
};
return result;
@@ -283,11 +282,6 @@ namespace Wox.Infrastructure
}
}
- ///
- /// Indicates if all query's substrings are contained in the string to compare
- ///
- public bool AllSubstringsContainedInCompareString { get; set; }
-
///
/// Matched data to highlight.
///
diff --git a/Wox.Test/FuzzyMatcherTest.cs b/Wox.Test/FuzzyMatcherTest.cs
index b7e0374f04..f2de39a289 100644
--- a/Wox.Test/FuzzyMatcherTest.cs
+++ b/Wox.Test/FuzzyMatcherTest.cs
@@ -182,10 +182,15 @@ namespace Wox.Test
[TestCase("sql manag", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql serv", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
+ [TestCase("sqlserv", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("sql servman", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("sql serv man", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("sql studio", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("mic", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("chr", "Shutdown", StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("mssms", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
[TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, false)]
+ [TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("a test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
[TestCase("test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
public void WhenGivenQueryShouldReturnResultsContainingAllQuerySubstrings(
@@ -214,21 +219,5 @@ namespace Wox.Test
$"Raw Score: {matchResult.RawScore}{Environment.NewLine}" +
$"Precision Score: {(int)expectedPrecisionScore}");
}
-
- [TestCase("sql servman", MicrosoftSqlServerManagementStudio, false)]
- [TestCase("sql serv man", MicrosoftSqlServerManagementStudio, true)]
- [TestCase("sql", MicrosoftSqlServerManagementStudio, true)]
- [TestCase("sqlserv", MicrosoftSqlServerManagementStudio, false)]
- [TestCase("mssms", MicrosoftSqlServerManagementStudio, false)]
- [TestCase("chr", "Change settings for text-to-speech and for speech recognition (if installed).", false)]
- [TestCase("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", true)]
- public void WhenGivenQueryShouldEvaluateTrueFalseIfCompareStringContainsAllSubstrings(string queryString, string compareString, bool expectedResult)
- {
- // When, Given
- var matchResult = StringMatcher.FuzzySearch(queryString, compareString).AllSubstringsContainedInCompareString;
-
- // Should
- Assert.AreEqual(matchResult, expectedResult);
- }
}
}
\ No newline at end of file