From 85faa2de2fa22a53cf99154e3333c4c194ceaf1c Mon Sep 17 00:00:00 2001 From: tatiana-yan Date: Mon, 18 Mar 2019 17:37:09 +0300 Subject: [PATCH] [search] Add IsCategorialRequestFuzzy method. --- .../search_integration_tests/utils_test.cpp | 16 ++++++ search/utils.cpp | 49 ++++++++++++++++++- search/utils.hpp | 3 ++ 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/search/search_integration_tests/utils_test.cpp b/search/search_integration_tests/utils_test.cpp index 15fb0e68a2..16a5fe8cc0 100644 --- a/search/search_integration_tests/utils_test.cpp +++ b/search/search_integration_tests/utils_test.cpp @@ -95,5 +95,21 @@ UNIT_CLASS_TEST(SearchUtilsTest, Utils) // All. testTypes(typesFood, 3); } + +UNIT_TEST(IsCategorialRequestFuzzy) +{ + auto const isHotelRequest = [](string const & q) { return IsCategorialRequestFuzzy(q, "hotel"); }; + + TEST(isHotelRequest("hotel"), ()); + TEST(isHotelRequest("Hotel"), ()); + TEST(isHotelRequest("motel"), ()); + TEST(isHotelRequest("отель"), ()); + TEST(isHotelRequest("гостиница"), ()); + TEST(isHotelRequest("гостиница москва"), ()); + TEST(isHotelRequest("new york hotel"), ()); + TEST(!isHotelRequest("new york where to stay"), ()); + TEST(!isHotelRequest("where to stay"), ()); + TEST(!isHotelRequest("random request"), ()); +} } // namespace } // namespace search diff --git a/search/utils.cpp b/search/utils.cpp index 7f570eba75..bcf8e981e4 100644 --- a/search/utils.cpp +++ b/search/utils.cpp @@ -60,8 +60,8 @@ vector GetCategoryTypes(string const & name, string const & locale, locales.Insert(static_cast(code)); vector tokens; - SplitUniString(search::NormalizeAndSimplifyString(name), base::MakeBackInsertFunctor(tokens), - search::Delimiters()); + SplitUniString(NormalizeAndSimplifyString(name), base::MakeBackInsertFunctor(tokens), + Delimiters()); FillCategories(QuerySliceOnRawStrings>(tokens, {} /* prefix */), locales, categories, types); @@ -125,4 +125,49 @@ void ForEachOfTypesInRect(DataSource const & dataSource, vector const }); } } + +bool IsCategorialRequestFuzzy(string const & query, string const & categoryEn) +{ + auto const & catHolder = GetDefaultCategories(); + auto const types = GetCategoryTypes(categoryEn, "en", catHolder); + + vector queryTokens; + SplitUniString(NormalizeAndSimplifyString(query), base::MakeBackInsertFunctor(queryTokens), + Delimiters()); + + bool isCategorialRequest = false; + for (auto const type : types) + { + if (isCategorialRequest) + return true; + + catHolder.ForEachNameByType( + type, [&](CategoriesHolder::Category::Name const & categorySynonym) { + if (isCategorialRequest) + return; + vector categoryTokens; + SplitUniString(NormalizeAndSimplifyString(categorySynonym.m_name), + base::MakeBackInsertFunctor(categoryTokens), Delimiters()); + for (size_t start = 0; start < queryTokens.size(); ++start) + { + bool found = true; + for (size_t i = 0; i < categoryTokens.size() && start + i < queryTokens.size(); ++i) + { + if (queryTokens[start + i] != categoryTokens[i]) + { + found = false; + break; + } + } + if (found) + { + isCategorialRequest = true; + break; + } + } + }); + } + + return isCategorialRequest; +} } // namespace search diff --git a/search/utils.hpp b/search/utils.hpp index 2e225181ec..584c18bffd 100644 --- a/search/utils.hpp +++ b/search/utils.hpp @@ -130,4 +130,7 @@ using FeatureIndexCallback = std::function; // Applies |fn| to each feature index of type from |types| in |rect|. void ForEachOfTypesInRect(DataSource const & dataSource, std::vector const & types, m2::RectD const & rect, FeatureIndexCallback const & fn); + +// Returns true iff |query| contains |categoryEn| synonym. +bool IsCategorialRequestFuzzy(std::string const & query, std::string const & categoryEn); } // namespace search