Forráskód Böngészése

Small fixes to search mapobject feature:
- Trim overly long names to prevent incorrect item display
- Use getLocaleName() for proper locale-aware to_lower conversion
- Implement scoring-based sorting for better search match ranking
- Remove Boost dependency: replace with std::string::find() and rfind()

MichalZr6 7 hónapja
szülő
commit
5363424451

+ 1 - 1
client/windows/CSpellWindow.cpp

@@ -241,7 +241,7 @@ void CSpellWindow::processSpells()
 	mySpells.reserve(LIBRARY->spellh->objects.size());
 	mySpells.reserve(LIBRARY->spellh->objects.size());
 	for(auto const & spell : LIBRARY->spellh->objects)
 	for(auto const & spell : LIBRARY->spellh->objects)
 	{
 	{
-		bool searchTextFound = !searchBox || TextOperations::textSearchSimilar(searchBox->getText(), spell->getNameTranslated());
+		bool searchTextFound = !searchBox || TextOperations::textSearchSimilarityScore(searchBox->getText(), spell->getNameTranslated()) < 100;
 
 
 		if(onSpellSelect)
 		if(onSpellSelect)
 		{
 		{

+ 78 - 15
client/windows/GUIClasses.cpp

@@ -1531,7 +1531,11 @@ CObjectListWindow::CObjectListWindow(const std::vector<int> & _items, std::share
 	items.reserve(_items.size());
 	items.reserve(_items.size());
 
 
 	for(int id : _items)
 	for(int id : _items)
-		items.push_back(std::make_pair(id, GAME->interface()->cb->getObjInstance(ObjectInstanceID(id))->getObjectName()));
+	{
+		std::string objectName = GAME->interface()->cb->getObjInstance(ObjectInstanceID(id))->getObjectName();
+		trimTextIfTooWide(objectName);
+		items.emplace_back(id, objectName);
+	}
 	itemsVisible = items;
 	itemsVisible = items;
 
 
 	init(titleWidget_, _title, _descr, searchBoxEnabled);
 	init(titleWidget_, _title, _descr, searchBoxEnabled);
@@ -1550,8 +1554,12 @@ CObjectListWindow::CObjectListWindow(const std::vector<std::string> & _items, st
 
 
 	items.reserve(_items.size());
 	items.reserve(_items.size());
 
 
-	for(size_t i=0; i<_items.size(); i++)
-		items.push_back(std::make_pair(int(i), _items[i]));
+	for(size_t i = 0; i < _items.size(); i++)
+	{
+		std::string objectName = _items[i];
+		trimTextIfTooWide(objectName);
+		items.emplace_back(static_cast<int>(i), objectName);
+	}
 	itemsVisible = items;
 	itemsVisible = items;
 
 
 	init(titleWidget_, _title, _descr, searchBoxEnabled);
 	init(titleWidget_, _title, _descr, searchBoxEnabled);
@@ -1570,7 +1578,7 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri
 	{
 	{
 		addChild(titleWidget.get());
 		addChild(titleWidget.get());
 		titleWidget->pos.x = pos.w/2 + pos.x - titleWidget->pos.w/2;
 		titleWidget->pos.x = pos.w/2 + pos.x - titleWidget->pos.w/2;
-		titleWidget->pos.y =75 + pos.y - titleWidget->pos.h/2;
+		titleWidget->pos.y = 75 + pos.y - titleWidget->pos.h/2;
 	}
 	}
 	list = std::make_shared<CListBox>(std::bind(&CObjectListWindow::genItem, this, _1),
 	list = std::make_shared<CListBox>(std::bind(&CObjectListWindow::genItem, this, _1),
 		Point(14, 151), Point(0, 25), 9, itemsVisible.size(), 0, 1, Rect(262, -32, 256, 256) );
 		Point(14, 151), Point(0, 25), 9, itemsVisible.size(), 0, 1, Rect(262, -32, 256, 256) );
@@ -1590,21 +1598,76 @@ void CObjectListWindow::init(std::shared_ptr<CIntObject> titleWidget_, std::stri
 	searchBoxDescription = std::make_shared<CLabel>(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, LIBRARY->generaltexth->translate("vcmi.spellBook.search"));
 	searchBoxDescription = std::make_shared<CLabel>(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, LIBRARY->generaltexth->translate("vcmi.spellBook.search"));
 
 
 	searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, ETextAlignment::CENTER, true);
 	searchBox = std::make_shared<CTextInput>(r, FONT_SMALL, ETextAlignment::CENTER, true);
-	searchBox->setCallback([this](const std::string & text){
-		searchBoxDescription->setEnabled(text.empty());
+	searchBox->setCallback(std::bind(&CObjectListWindow::itemsSearchCallback, this, std::placeholders::_1));
+}
+
+void CObjectListWindow::trimTextIfTooWide(std::string & text) const
+{
+	int maxWidth = pos.w - 60;
+
+	// Create a temporary label to measure text width
+	auto label = std::make_shared<CLabel>(0, 0, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, text);
+	int textWidth = label->getWidth();
+
+	std::regex pattern(R"(.*(\(\d+\))$)");
+	std::smatch match;
+
+	std::string quantity;
+	if(std::regex_match(text, match, pattern) && match.size() > 1)
+		quantity = match[1]; // Extract the quantity
+
+	std::string suffix = " ... " + quantity;
+
+	if(textWidth >= maxWidth)
+	{
+		logGlobal->warn("Mapobject name '%s' is too long and probably needs to be fixed! Trimming...", 
+			text.substr(0, text.size() - quantity.size() + 1));
+
+		// Trim text until it fits
+		while(!text.empty())
+		{
+			std::string trimmedText = text + suffix;
+			label->setText(trimmedText);
+
+			if(label->getWidth() < maxWidth)
+				break;
 
 
-		itemsVisible.clear();
-		for(auto & item : items)
-			if(TextOperations::textSearchSimilar(text, item.second))
-				itemsVisible.push_back(item);
+			text.resize(text.size() - 1);
+		}
+
+		text += suffix;
+	}
+}
 
 
-		selected = 0;
-		list->resize(itemsVisible.size());
-		list->scrollTo(0);
-		ok->block(!itemsVisible.size());
+void CObjectListWindow::itemsSearchCallback(const std::string & text)
+{
+	searchBoxDescription->setEnabled(text.empty());
+
+	itemsVisible.clear();
+	std::vector<std::pair<int, decltype(items)::value_type>> rankedItems; // Store (score, item)
+
+	for(auto & item : items)
+	{
+		int score = TextOperations::textSearchSimilarityScore(text, item.second);
+		if(score < 100) // Keep only relevant items
+			rankedItems.emplace_back(score, item);
+	}
 
 
-		redraw();
+	// Sort: Lower score is better match
+	std::sort(rankedItems.begin(), rankedItems.end(), [](const auto & a, const auto & b)
+	{
+		return a.first < b.first;
 	});
 	});
+
+	for(auto & rankedItem : rankedItems)
+		itemsVisible.push_back(rankedItem.second);
+
+	selected = 0;
+	list->resize(itemsVisible.size());
+	list->scrollTo(0);
+	ok->block(!itemsVisible.size());
+
+	redraw();
 }
 }
 
 
 std::shared_ptr<CIntObject> CObjectListWindow::genItem(size_t index)
 std::shared_ptr<CIntObject> CObjectListWindow::genItem(size_t index)

+ 2 - 0
client/windows/GUIClasses.h

@@ -197,6 +197,8 @@ class CObjectListWindow : public CWindowObject
 	std::vector< std::pair<int, std::string> > itemsVisible; //visible items present in list
 	std::vector< std::pair<int, std::string> > itemsVisible; //visible items present in list
 
 
 	void init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled);
 	void init(std::shared_ptr<CIntObject> titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled);
+	void trimTextIfTooWide(std::string & text) const; // trim items to fit within window's width
+	void itemsSearchCallback(const std::string & text);
 	void exitPressed();
 	void exitPressed();
 public:
 public:
 	size_t selected;//index of currently selected item
 	size_t selected;//index of currently selected item

+ 20 - 40
lib/texts/Languages.h

@@ -86,46 +86,26 @@ inline const auto & getLanguageList()
 {
 {
 	static const std::array<Options, 20> languages
 	static const std::array<Options, 20> languages
 	{ {
 	{ {
-<<<<<<< HEAD
-		{ "czech",       "Czech",       "Čeština",    "CP1250", "cs", "cze", "%d.%m.%Y %H:%M",    EPluralForms::CZ_3, true  },
-		{ "chinese",     "Chinese",     "简体中文",    "GBK",    "zh", "chi", "%Y-%m-%d %H:%M",    EPluralForms::VI_1, true  }, // Note: actually Simplified Chinese
-		{ "english",     "English",     "English",    "CP1252", "en", "eng", "%Y-%m-%d %H:%M",    EPluralForms::EN_2, true  }, // English uses international date/time format here
-		{ "finnish",     "Finnish",     "Suomi",      "CP1252", "fi", "fin", "%d.%m.%Y %H:%M",    EPluralForms::EN_2, true  },
-		{ "french",      "French",      "Français",   "CP1252", "fr", "fre", "%d/%m/%Y %H:%M",    EPluralForms::FR_2, true  },
-		{ "german",      "German",      "Deutsch",    "CP1252", "de", "ger", "%d.%m.%Y %H:%M",    EPluralForms::EN_2, true  },
-		{ "greek",       "Greek",       "ελληνικά",   "CP1253", "el", "ell", "%d/%m/%Y %H:%M",    EPluralForms::EN_2, false },
-		{ "hungarian",   "Hungarian",   "Magyar",     "CP1250", "hu", "hun", "%Y. %m. %d. %H:%M", EPluralForms::EN_2, true  },
-		{ "italian",     "Italian",     "Italiano",   "CP1250", "it", "ita", "%d/%m/%Y %H:%M",    EPluralForms::EN_2, true  },
-		{ "japanese",    "Japanese",    "日本語",      "JIS",    "ja", "jpn", "%Y年%m月%d日 %H:%M", EPluralForms::NONE, false },
-		{ "korean",      "Korean",      "한국어",      "CP949",  "ko", "kor", "%Y-%m-%d %H:%M",    EPluralForms::VI_1, true  },
-		{ "polish",      "Polish",      "Polski",     "CP1250", "pl", "pol", "%d.%m.%Y %H:%M",    EPluralForms::PL_3, true  },
-		{ "portuguese",  "Portuguese",  "Português",  "CP1252", "pt", "por", "%d/%m/%Y %H:%M",    EPluralForms::EN_2, true  }, // Note: actually Brazilian Portuguese
-		{ "russian",     "Russian",     "Русский",    "CP1251", "ru", "rus", "%d.%m.%Y %H:%M",    EPluralForms::UK_3, true  },
-		{ "spanish",     "Spanish",     "Español",    "CP1252", "es", "spa", "%d/%m/%Y %H:%M",    EPluralForms::EN_2, true  },
-		{ "swedish",     "Swedish",     "Svenska",    "CP1252", "sv", "swe", "%Y-%m-%d %H:%M",    EPluralForms::EN_2, true  },
-		{ "norwegian",   "Norwegian",   "Norsk",      "CP1252", "no", "nor", "%d/%m/%Y %H:%M",    EPluralForms::EN_2, false },
-		{ "turkish",     "Turkish",     "Türkçe",     "CP1254", "tr", "tur", "%d.%m.%Y %H:%M",    EPluralForms::EN_2, true  },
-		{ "ukrainian",   "Ukrainian",   "Українська", "CP1251", "uk", "ukr", "%d.%m.%Y %H:%M",    EPluralForms::UK_3, true  },
-		{ "vietnamese",  "Vietnamese",  "Tiếng Việt", "UTF-8",  "vi", "vie", "%d/%m/%Y %H:%M",    EPluralForms::VI_1, true  }, // Fan translation uses special encoding
-=======
-		{ "czech",       "Czech",       "Čeština",    "CP1250", "cs_CZ.UTF-8", "cs", "cze", "%d.%m.%Y %H:%M", EPluralForms::CZ_3 },
-		{ "chinese",     "Chinese",     "简体中文",       "GBK", "zh_CN.UTF-8", "zh", "chi", "%Y-%m-%d %H:%M", EPluralForms::VI_1 }, // Note: actually Simplified Chinese
-		{ "english",     "English",     "English",    "CP1252", "en_US.UTF-8", "en", "eng", "%Y-%m-%d %H:%M", EPluralForms::EN_2 }, // English uses international date/time format here
-		{ "finnish",     "Finnish",     "Suomi",      "CP1252", "fi_FI.UTF-8", "fi", "fin", "%d.%m.%Y %H:%M", EPluralForms::EN_2, },
-		{ "french",      "French",      "Français",   "CP1252", "fr_FR.UTF-8", "fr", "fre", "%d/%m/%Y %H:%M", EPluralForms::FR_2, },
-		{ "german",      "German",      "Deutsch",    "CP1252", "de_DE.UTF-8", "de", "ger", "%d.%m.%Y %H:%M", EPluralForms::EN_2, },
-		{ "hungarian",   "Hungarian",   "Magyar",     "CP1250", "hu_HU.UTF-8", "hu", "hun", "%Y. %m. %d. %H:%M", EPluralForms::EN_2 },
-		{ "italian",     "Italian",     "Italiano",   "CP1250", "it_IT.UTF-8", "it", "ita", "%d/%m/%Y %H:%M", EPluralForms::EN_2 },
-		{ "korean",      "Korean",      "한국어",       "CP949", "ko_KR.UTF-8", "ko", "kor", "%Y-%m-%d %H:%M", EPluralForms::VI_1 },
-		{ "polish",      "Polish",      "Polski",     "CP1250", "pl_PL.UTF-8", "pl", "pol", "%d.%m.%Y %H:%M", EPluralForms::PL_3 },
-		{ "portuguese",  "Portuguese",  "Português",  "CP1252", "pt_BR.UTF-8", "pt", "por", "%d/%m/%Y %H:%M", EPluralForms::EN_2 }, // Note: actually Brazilian Portuguese
-		{ "russian",     "Russian",     "Русский",    "CP1251", "ru_RU.UTF-8", "ru", "rus", "%d.%m.%Y %H:%M", EPluralForms::UK_3 },
-		{ "spanish",     "Spanish",     "Español",    "CP1252", "es_ES.UTF-8", "es", "spa", "%d/%m/%Y %H:%M", EPluralForms::EN_2 },
-		{ "swedish",     "Swedish",     "Svenska",    "CP1252", "sv_SE.UTF-8", "sv", "swe", "%Y-%m-%d %H:%M", EPluralForms::EN_2 },
-		{ "turkish",     "Turkish",     "Türkçe",     "CP1254", "tr_TR.UTF-8", "tr", "tur", "%d.%m.%Y %H:%M", EPluralForms::EN_2 },
-		{ "ukrainian",   "Ukrainian",   "Українська", "CP1251", "uk_UA.UTF-8", "uk", "ukr", "%d.%m.%Y %H:%M", EPluralForms::UK_3 },
-		{ "vietnamese",  "Vietnamese",  "Tiếng Việt", "UTF-8",  "vi_VN.UTF-8", "vi", "vie", "%d/%m/%Y %H:%M", EPluralForms::VI_1 }, // Fan translation uses special encoding
->>>>>>> 364b3cef9 (Use locale based on language set in config)
+		{ "czech",       "Czech",       "Čeština",		"CP1250", "cs_CZ.UTF-8", "cs", "cze", "%d.%m.%Y %H:%M",		EPluralForms::CZ_3, true },
+		{ "chinese",     "Chinese",     "简体中文",		"GBK",	  "zh_CN.UTF-8", "zh", "chi", "%Y-%m-%d %H:%M",		EPluralForms::VI_1, true }, // Note: actually Simplified Chinese
+		{ "english",     "English",     "English",		"CP1252", "en_US.UTF-8", "en", "eng", "%Y-%m-%d %H:%M",		EPluralForms::EN_2, true }, // English uses international date/time format here
+		{ "finnish",     "Finnish",     "Suomi",		"CP1252", "fi_FI.UTF-8", "fi", "fin", "%d.%m.%Y %H:%M",		EPluralForms::EN_2, true },
+		{ "french",      "French",      "Français",		"CP1252", "fr_FR.UTF-8", "fr", "fre", "%d/%m/%Y %H:%M",		EPluralForms::FR_2, true },
+		{ "german",      "German",      "Deutsch",		"CP1252", "de_DE.UTF-8", "de", "ger", "%d.%m.%Y %H:%M",		EPluralForms::EN_2, true },
+		{ "greek",       "Greek",       "ελληνικά",		"CP1253", "el_GR.UTF-8", "el", "ell", "%d/%m/%Y %H:%M",		EPluralForms::EN_2, false },
+		{ "hungarian",   "Hungarian",   "Magyar",		"CP1250", "hu_HU.UTF-8", "hu", "hun", "%Y. %m. %d. %H:%M",  EPluralForms::EN_2, true },
+		{ "italian",     "Italian",     "Italiano",		"CP1250", "it_IT.UTF-8", "it", "ita", "%d/%m/%Y %H:%M",		EPluralForms::EN_2, true },
+		{ "japanese",    "Japanese",    "日本語",		"JIS",    "ja_JP.UTF-8", "ja", "jpn", "%Y年%m月%d日 %H:%M",	EPluralForms::NONE, false },
+		{ "korean",      "Korean",      "한국어",		"CP949",  "ko_KR.UTF-8", "ko", "kor", "%Y-%m-%d %H:%M",		EPluralForms::VI_1, true },
+		{ "polish",      "Polish",      "Polski",		"CP1250", "pl_PL.UTF-8", "pl", "pol", "%d.%m.%Y %H:%M",		EPluralForms::PL_3, true },
+		{ "portuguese",  "Portuguese",  "Português",	"CP1252", "pt_BR.UTF-8", "pt", "por", "%d/%m/%Y %H:%M",		EPluralForms::EN_2, true }, // Note: actually Brazilian Portuguese
+		{ "russian",     "Russian",     "Русский",		"CP1251", "ru_RU.UTF-8", "ru", "rus", "%d.%m.%Y %H:%M",		EPluralForms::UK_3, true },
+		{ "spanish",     "Spanish",     "Español",		"CP1252", "es_ES.UTF-8", "es", "spa", "%d/%m/%Y %H:%M",		EPluralForms::EN_2, true },
+		{ "swedish",     "Swedish",     "Svenska",		"CP1252", "sv_SE.UTF-8", "sv", "swe", "%Y-%m-%d %H:%M",		EPluralForms::EN_2, true },
+		{ "norwegian",   "Norwegian",   "Norsk Bokmål", "UTF-8",  "nb_NO.UTF-8", "nb", "nor", "%d/%m/%Y %H:%M",		EPluralForms::EN_2, false },
+		{ "turkish",     "Turkish",     "Türkçe",		"CP1254", "tr_TR.UTF-8", "tr", "tur", "%d.%m.%Y %H:%M",		EPluralForms::EN_2, true },
+		{ "ukrainian",   "Ukrainian",   "Українська",	"CP1251", "uk_UA.UTF-8", "uk", "ukr", "%d.%m.%Y %H:%M",		EPluralForms::UK_3, true },
+		{ "vietnamese",  "Vietnamese",  "Tiếng Việt",	"UTF-8",  "vi_VN.UTF-8", "vi", "vie", "%d/%m/%Y %H:%M",		EPluralForms::VI_1, true }, // Fan translation uses special encoding
 	} };
 	} };
 	static_assert(languages.size() == static_cast<size_t>(ELanguages::COUNT), "Languages array is missing a value!");
 	static_assert(languages.size() == static_cast<size_t>(ELanguages::COUNT), "Languages array is missing a value!");
 
 

+ 30 - 17
lib/texts/TextOperations.cpp

@@ -252,7 +252,7 @@ std::string TextOperations::getCurrentFormattedDateTimeLocal(std::chrono::second
 	return TextOperations::getFormattedDateTimeLocal(std::chrono::system_clock::to_time_t(timepoint));
 	return TextOperations::getFormattedDateTimeLocal(std::chrono::system_clock::to_time_t(timepoint));
 }
 }
 
 
-int TextOperations::getLevenshteinDistance(const std::string & s, const std::string & t)
+int TextOperations::getLevenshteinDistance(std::string_view s, std::string_view t)
 {
 {
 	int n = t.size();
 	int n = t.size();
 	int m = s.size();
 	int m = s.size();
@@ -298,9 +298,9 @@ int TextOperations::getLevenshteinDistance(const std::string & s, const std::str
 
 
 	// after the last swap, the results of v1 are now in v0
 	// after the last swap, the results of v1 are now in v0
 	return v0[n];
 	return v0[n];
-}
-
-DLL_LINKAGE std::string TextOperations::getLocaleName()
+}
+
+DLL_LINKAGE std::string TextOperations::getLocaleName()
 {
 {
 	try
 	try
 	{
 	{
@@ -319,30 +319,43 @@ DLL_LINKAGE std::string TextOperations::getLocaleName()
 	}
 	}
 }
 }
 
 
-bool TextOperations::textSearchSimilar(const std::string & s, const std::string & t)
+int TextOperations::textSearchSimilarityScore(const std::string & s, const std::string & t)
 {
 {
 	boost::locale::generator gen;
 	boost::locale::generator gen;
 	std::locale loc = gen(getLocaleName());
 	std::locale loc = gen(getLocaleName());
-	
+
 	auto haystack = boost::locale::to_lower(t, loc);
 	auto haystack = boost::locale::to_lower(t, loc);
 	auto needle = boost::locale::to_lower(s, loc);
 	auto needle = boost::locale::to_lower(s, loc);
 
 
-	if(boost::algorithm::contains(haystack, needle))
-		return true;
+	// 0 - Best possible match: text starts with the search string
+	if(haystack.rfind(needle, 0) == 0)
+		return 0;
+
+	// 1 - Strong match: text contains the search string
+	if(haystack.find(needle) != std::string::npos)
+		return 1;
 
 
+	// If the search string is longer than the text, return a high penalty
 	if(needle.size() > haystack.size())
 	if(needle.size() > haystack.size())
-		return false;
+		return 100;
 
 
-	for(int i = 0; i < haystack.size() - needle.size() + 1; i++)
+	// Compute Levenshtein distance for fuzzy similarity
+	int minDist = 100;
+	for(size_t i = 0; i <= haystack.size() - needle.size(); i++)
 	{
 	{
-		auto dist = getLevenshteinDistance(haystack.substr(i, needle.size()), needle);
-		if(needle.size() > 2 && dist <= 1)
-			return true;
-		else if(needle.size() > 4 && dist <= 2)
-			return true;
+		std::string_view subHaystack = std::string_view(haystack).substr(i, needle.size());
+		int dist = getLevenshteinDistance(subHaystack, needle);
+		if(dist < minDist)
+			minDist = dist;
 	}
 	}
-	
-	return false;
+
+	// Apply scaling: Short words tolerate smaller distances
+	if(needle.size() > 2 && minDist <= 1)
+		return minDist + 1; // +1 to ensure it's worse than an exact match
+	else if(needle.size() > 4 && minDist <= 2)
+		return minDist + 1;
+
+	return 100; // Worst similarity
 }
 }
 
 
 VCMI_LIB_NAMESPACE_END
 VCMI_LIB_NAMESPACE_END

+ 3 - 2
lib/texts/TextOperations.h

@@ -77,7 +77,7 @@ namespace TextOperations
 	/// Algorithm for detection of typos in words
 	/// Algorithm for detection of typos in words
 	/// Determines how 'different' two strings are - how many changes must be done to turn one string into another one
 	/// Determines how 'different' two strings are - how many changes must be done to turn one string into another one
 	/// https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
 	/// https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
-	DLL_LINKAGE int getLevenshteinDistance(const std::string & s, const std::string & t);
+	DLL_LINKAGE int getLevenshteinDistance(std::string_view s, std::string_view t);
 
 
 	/// Retrieves the locale name based on the selected (in config) game language, with a safe fallback.
 	/// Retrieves the locale name based on the selected (in config) game language, with a safe fallback.
 	DLL_LINKAGE std::string getLocaleName();
 	DLL_LINKAGE std::string getLocaleName();
@@ -93,7 +93,8 @@ namespace TextOperations
 	}
 	}
 
 
 	/// Check if texts have similarity when typing into search boxes
 	/// Check if texts have similarity when typing into search boxes
-	DLL_LINKAGE bool textSearchSimilar(const std::string & s, const std::string & t);
+	/// 0 -> Exact match or substring match, 1 - 2 -> Close match based on Levenshtein distance, >100 -> Unrelated word(bad match).
+	DLL_LINKAGE int textSearchSimilarityScore(const std::string & s, const std::string & t);
 
 
 };
 };