diff --git a/search/search_tests/house_numbers_matcher_test.cpp b/search/search_tests/house_numbers_matcher_test.cpp index f6cb3fb7d8..6a4573f0bf 100644 --- a/search/search_tests/house_numbers_matcher_test.cpp +++ b/search/search_tests/house_numbers_matcher_test.cpp @@ -11,24 +11,24 @@ using namespace search::v2; namespace { -void NormalizeHouseNumber(string const & s, vector & ts) +void ParseHouseNumber(string const & s, vector> & ts) { - Parse p; - ParseHouseNumber(MakeUniString(s), p); - for (auto const & part : p.m_parts) - ts.push_back(ToUtf8(part)); + vector parses; + ParseQuery(MakeUniString(s), false /* queryIsPrefix */, parses); + for (auto const & parse : parses) + { + ts.emplace_back(); + auto & tsb = ts.back(); + for (auto const & part : parse.m_parts) + tsb.push_back(ToUtf8(part)); + } } -bool HouseNumbersMatch(string const & houseNumber, string const & query) +bool HouseNumbersMatch(string const & houseNumber, string const & query, bool queryIsPrefix = false) { - return search::v2::HouseNumbersMatch(MakeUniString(houseNumber), MakeUniString(query)); -} - -bool HouseNumbersMatch(string const & houseNumber, string const & query, bool queryIsPrefix) -{ - vector queryParse; - ParseQuery(MakeUniString(query), queryIsPrefix, queryParse); - return search::v2::HouseNumbersMatch(MakeUniString(houseNumber), queryParse); + vector queryParses; + ParseQuery(MakeUniString(query), queryIsPrefix, queryParses); + return search::v2::HouseNumbersMatch(MakeUniString(houseNumber), queryParses); } bool CheckTokenizer(string const & utf8s, vector const & expected) @@ -48,25 +48,26 @@ bool CheckTokenizer(string const & utf8s, vector const & expected) return true; } -bool CheckNormalizer(string const & utf8s, string const & expected) +bool CheckParser(string const & utf8s, string const & expected) { - vector tokens; - NormalizeHouseNumber(utf8s, tokens); + vector> parses; + ParseHouseNumber(utf8s, parses); - string actual; - for (size_t i = 0; i < tokens.size(); ++i) + for (auto const & parse : parses) { - actual.append(tokens[i]); - if (i + 1 != tokens.size()) - actual.push_back(' '); + string actual; + for (size_t i = 0; i < parse.size(); ++i) + { + actual.append(parse[i]); + if (i + 1 != parse.size()) + actual.push_back(' '); + } + if (actual == expected) + return true; } - if (actual != expected) - { - LOG(LINFO, ("actual:", actual, "expected:", expected)); - return false; - } - return true; + LOG(LINFO, ("actual:", parses, "expected:", expected)); + return false; } } // namespace @@ -79,14 +80,14 @@ UNIT_TEST(HouseNumberTokenizer_Smoke) UNIT_TEST(HouseNumberNormalizer_Smoke) { - TEST(CheckNormalizer("123Б", "123б"), ()); - TEST(CheckNormalizer("123/4 Литер А", "123 4 а"), ()); - TEST(CheckNormalizer("123а корп. 2б", "123а 2б"), ()); - TEST(CheckNormalizer("123к4", "123 4"), ()); - TEST(CheckNormalizer("123к Корпус 2", "123к 2"), ()); - TEST(CheckNormalizer("9 литер А корпус 2", "9 2 а"), ()); - TEST(CheckNormalizer("39с79", "39 79"), ()); - TEST(CheckNormalizer("9 литер аб1", "9 аб1"), ()); + TEST(CheckParser("123Б", "123б"), ()); + TEST(CheckParser("123/4 Литер А", "123 4 а"), ()); + TEST(CheckParser("123а корп. 2б", "123а 2б"), ()); + TEST(CheckParser("123к4", "123 4"), ()); + TEST(CheckParser("123к Корпус 2", "123к 2"), ()); + TEST(CheckParser("9 литер А корпус 2", "9 2 а"), ()); + TEST(CheckParser("39с79", "39 79"), ()); + TEST(CheckParser("9 литер аб1", "9 аб1"), ()); } UNIT_TEST(HouseNumbersMatcher_Smoke) diff --git a/search/v2/features_layer_path_finder.cpp b/search/v2/features_layer_path_finder.cpp index 8229e9ca82..c05ba6c8d7 100644 --- a/search/v2/features_layer_path_finder.cpp +++ b/search/v2/features_layer_path_finder.cpp @@ -46,11 +46,18 @@ uint64_t CalcBottomUpPassCost(vector const & layers) return CalcPassCost(layers.begin(), layers.end()); } -bool LooksLikeHouseNumber(strings::UniString const & query) +bool LooksLikeHouseNumber(strings::UniString const & query, bool queryIsPrefix) { - Parse parse; - ParseHouseNumber(query, parse); - return !parse.IsEmpty() && feature::IsHouseNumber(parse.m_parts.front()); + vector parses; + ParseQuery(query, queryIsPrefix, parses); + for (auto const & parse : parses) + { + if (parse.IsEmpty()) + continue; + if (feature::IsHouseNumber(parse.m_parts.front())) + return true; + } + return false; } bool GetPath(uint32_t id, vector const & layers, TParentGraph const & parent, @@ -124,8 +131,8 @@ void FeaturesLayerPathFinder::FindReachableVerticesTopDown( parent.m_hasDelayedFeatures = false; FeaturesLayer child(*layers[i - 1]); - child.m_hasDelayedFeatures = - child.m_type == SearchModel::SEARCH_TYPE_BUILDING && LooksLikeHouseNumber(child.m_subQuery); + child.m_hasDelayedFeatures = child.m_type == SearchModel::SEARCH_TYPE_BUILDING && + LooksLikeHouseNumber(child.m_subQuery, child.m_lastTokenIsPrefix); buffer.clear(); matcher.Match(child, parent, addEdge); @@ -171,8 +178,9 @@ void FeaturesLayerPathFinder::FindReachableVerticesBottomUp( child.m_hasDelayedFeatures = false; FeaturesLayer parent(*layers[i + 1]); - parent.m_hasDelayedFeatures = parent.m_type == SearchModel::SEARCH_TYPE_BUILDING && - LooksLikeHouseNumber(parent.m_subQuery); + parent.m_hasDelayedFeatures = + parent.m_type == SearchModel::SEARCH_TYPE_BUILDING && + LooksLikeHouseNumber(parent.m_subQuery, parent.m_lastTokenIsPrefix); buffer.clear(); matcher.Match(child, parent, addEdge); diff --git a/search/v2/house_numbers_matcher.cpp b/search/v2/house_numbers_matcher.cpp index fce06372a6..3acd0d6341 100644 --- a/search/v2/house_numbers_matcher.cpp +++ b/search/v2/house_numbers_matcher.cpp @@ -65,8 +65,6 @@ size_t GetNumTokensForBuildingPartImpl(vector const { ASSERT_LESS(i, ts.size(), ()); - // TODO (@y, @m, @vng): move these constans out. - auto const & token = ts[i]; if (token.m_klass != HouseNumberTokenizer::CharClass::Other) return 0; @@ -226,13 +224,6 @@ void HouseNumberTokenizer::Tokenize(UniString const & s, vector & ts) } } -void ParseHouseNumber(strings::UniString const & s, Parse & p) -{ - vector tokens; - HouseNumberTokenizer::Tokenize(MakeLowerCase(s), tokens); - MergeTokens(tokens, p.m_parts); -} - void ParseQuery(strings::UniString const & query, bool queryIsPrefix, vector & ps) { vector tokens; @@ -257,28 +248,16 @@ void ParseQuery(strings::UniString const & query, bool queryIsPrefix, vector queryParses; + ParseQuery(query, queryIsPrefix, queryParses); - return HouseNumbersMatch(houseNumber, queryParse); -} - -bool HouseNumbersMatch(strings::UniString const & houseNumber, Parse const & queryParse) -{ - if (houseNumber.empty() || queryParse.IsEmpty()) - return false; - if (queryParse.m_parts[0][0] != houseNumber[0]) - return false; - - Parse houseNumberParse; - ParseHouseNumber(houseNumber, houseNumberParse); - - return ParsesMatch(houseNumberParse, queryParse); + return HouseNumbersMatch(houseNumber, queryParses); } bool HouseNumbersMatch(strings::UniString const & houseNumber, vector const & queryParses) @@ -301,7 +280,12 @@ bool HouseNumbersMatch(strings::UniString const & houseNumber, vector con return false; Parse houseNumberParse; - ParseHouseNumber(houseNumber, houseNumberParse); + { + vector tokens; + HouseNumberTokenizer::Tokenize(MakeLowerCase(houseNumber), tokens); + MergeTokens(tokens, houseNumberParse.m_parts); + } + for (auto const & queryParse : queryParses) { if (ParsesMatch(houseNumberParse, queryParse)) diff --git a/search/v2/house_numbers_matcher.hpp b/search/v2/house_numbers_matcher.hpp index aa22c178f7..53bf7d6bb7 100644 --- a/search/v2/house_numbers_matcher.hpp +++ b/search/v2/house_numbers_matcher.hpp @@ -45,16 +45,13 @@ struct Parse bool m_hasTrailingBuildingPrefixSynonym = false; }; -// Splits house number by tokens, removes blanks and separators. -void ParseHouseNumber(strings::UniString const & s, Parse & p); - +// Parses query for later faster processing, when multiple buildings +// are matched against the query. void ParseQuery(strings::UniString const & query, bool queryIsPrefix, vector & ps); // Returns true when |query| matches to |houseNumber|. -bool HouseNumbersMatch(strings::UniString const & houseNumber, strings::UniString const & query); - -// Returns true when parsed query matches to |houseNumber|. -bool HouseNumbersMatch(strings::UniString const & houseNumber, Parse const & queryParse); +bool HouseNumbersMatch(strings::UniString const & houseNumber, strings::UniString const & query, + bool queryIsPrefix); // Returns true when at least one parse of the query matches to // |houseNumber|.