diff --git a/search/search_integration_tests/search_query_v2_test.cpp b/search/search_integration_tests/search_query_v2_test.cpp index e85f56a015..f9e799cf2d 100644 --- a/search/search_integration_tests/search_query_v2_test.cpp +++ b/search/search_integration_tests/search_query_v2_test.cpp @@ -69,8 +69,8 @@ public: infoGetter.AddCountry(storage::CountryDef(name, rect)); } - template - MwmSet::MwmId RegisterMwm(string const & name, feature::DataHeader::MapType type, TFn && fn) + template + MwmSet::MwmId BuildMwm(string const & name, feature::DataHeader::MapType type, TBuildFn && fn) { m_files.emplace_back(m_platform.WritableDir(), platform::CountryFile(name), 0 /* version */); auto & file = m_files.back(); @@ -161,39 +161,39 @@ UNIT_CLASS_TEST(SearchQueryV2Test, Smoke) auto const lantern1 = make_shared(m2::PointD(10.0005, 10.0005), "lantern 1", "en"); auto const lantern2 = make_shared(m2::PointD(10.0006, 10.0005), "lantern 2", "en"); - RegisterMwm("testWorld", feature::DataHeader::world, [&](TestMwmBuilder & builder) - { - builder.Add(*wonderlandCountry); - builder.Add(*losAlamosCity); - builder.Add(*mskCity); - }); + BuildMwm("testWorld", feature::DataHeader::world, [&](TestMwmBuilder & builder) + { + builder.Add(*wonderlandCountry); + builder.Add(*losAlamosCity); + builder.Add(*mskCity); + }); auto wonderlandId = - RegisterMwm("wonderland", feature::DataHeader::country, [&](TestMwmBuilder & builder) - { - builder.Add(*losAlamosCity); - builder.Add(*mskCity); - builder.Add(*longPondVillage); + BuildMwm("wonderland", feature::DataHeader::country, [&](TestMwmBuilder & builder) + { + builder.Add(*losAlamosCity); + builder.Add(*mskCity); + builder.Add(*longPondVillage); - builder.Add(*feynmanStreet); - builder.Add(*bohrStreet1); - builder.Add(*bohrStreet2); - builder.Add(*bohrStreet3); - builder.Add(*firstAprilStreet); + builder.Add(*feynmanStreet); + builder.Add(*bohrStreet1); + builder.Add(*bohrStreet2); + builder.Add(*bohrStreet3); + builder.Add(*firstAprilStreet); - builder.Add(*feynmanHouse); - builder.Add(*bohrHouse); - builder.Add(*hilbertHouse); - builder.Add(*descartesHouse); - builder.Add(*bornHouse); + builder.Add(*feynmanHouse); + builder.Add(*bohrHouse); + builder.Add(*hilbertHouse); + builder.Add(*descartesHouse); + builder.Add(*bornHouse); - builder.Add(*busStop); - builder.Add(*tramStop); - builder.Add(*quantumTeleport1); - builder.Add(*quantumTeleport2); - builder.Add(*quantumCafe); - builder.Add(*lantern1); - builder.Add(*lantern2); - }); + builder.Add(*busStop); + builder.Add(*tramStop); + builder.Add(*quantumTeleport1); + builder.Add(*quantumTeleport2); + builder.Add(*quantumCafe); + builder.Add(*lantern1); + builder.Add(*lantern2); + }); RegisterCountry("wonderland", m2::RectD(m2::PointD(-1.0, -1.0), m2::PointD(10.1, 10.1))); @@ -269,12 +269,12 @@ UNIT_CLASS_TEST(SearchQueryV2Test, SearchInWorld) auto const losAlamos = make_shared(m2::PointD(0, 0), "Los Alamos", "en", 100 /* rank */); - auto testWorldId = RegisterMwm("testWorld", feature::DataHeader::world, - [&](TestMwmBuilder & builder) - { - builder.Add(*wonderland); - builder.Add(*losAlamos); - }); + auto testWorldId = BuildMwm("testWorld", feature::DataHeader::world, + [&](TestMwmBuilder & builder) + { + builder.Add(*wonderland); + builder.Add(*losAlamos); + }); RegisterCountry("Wonderland", m2::RectD(m2::PointD(-1.0, -1.0), m2::PointD(1.0, 1.0))); @@ -301,15 +301,15 @@ UNIT_CLASS_TEST(SearchQueryV2Test, SearchByName) m2::PointD(1.5, 1.5), m2::PointD(0.5, 1.5)}, "Hyde Park", "en"); - RegisterMwm("testWorld", feature::DataHeader::world, [&](TestMwmBuilder & builder) - { - builder.Add(*london); - }); - auto wonderlandId = RegisterMwm("wonderland", feature::DataHeader::country, - [&](TestMwmBuilder & builder) - { - builder.Add(*hydePark); - }); + BuildMwm("testWorld", feature::DataHeader::world, [&](TestMwmBuilder & builder) + { + builder.Add(*london); + }); + auto wonderlandId = BuildMwm("wonderland", feature::DataHeader::country, + [&](TestMwmBuilder & builder) + { + builder.Add(*hydePark); + }); RegisterCountry("Wonderland", m2::RectD(m2::PointD(0, 0), m2::PointD(2, 2))); SetViewport(m2::RectD(m2::PointD(-1.0, -1.0), m2::PointD(-0.9, -0.9))); @@ -317,4 +317,5 @@ UNIT_CLASS_TEST(SearchQueryV2Test, SearchByName) TRules rules = {make_shared(wonderlandId, hydePark)}; TEST(ResultsMatch("hyde park", rules), ()); TEST(ResultsMatch("london hyde park", rules), ()); + TEST(ResultsMatch("hyde london park", TRules()), ()); } diff --git a/search/search_tests_support/test_feature.cpp b/search/search_tests_support/test_feature.cpp index d6e77a820e..1c4fb52b61 100644 --- a/search/search_tests_support/test_feature.cpp +++ b/search/search_tests_support/test_feature.cpp @@ -194,8 +194,6 @@ void TestBuilding::Serialize(FeatureBuilder1 & fb) const auto const & classificator = classif(); fb.SetType(classificator.GetTypeByPath({"building"})); - - fb.PreSerialize(); } bool TestBuilding::Matches(FeatureType const & feature) const @@ -229,8 +227,6 @@ void TestPark::Serialize(FeatureBuilder1 & fb) const auto const & classificator = classif(); fb.SetType(classificator.GetTypeByPath({"leisure", "park"})); - - fb.PreSerialize(); } string TestPark::ToString() const diff --git a/search/v2/features_layer_matcher.hpp b/search/v2/features_layer_matcher.hpp index 7c763933fb..c43379a1fc 100644 --- a/search/v2/features_layer_matcher.hpp +++ b/search/v2/features_layer_matcher.hpp @@ -75,7 +75,7 @@ public: case SearchModel::SEARCH_TYPE_STATE: case SearchModel::SEARCH_TYPE_COUNTRY: case SearchModel::SEARCH_TYPE_UNCLASSIFIED: - case SearchModel::SEARCH_TYPE_COUNT: + case SearchModel::SEARCH_TYPE_COUNT: ASSERT(false, ("Invalid parent layer type:", parent.m_type)); break; case SearchModel::SEARCH_TYPE_BUILDING: diff --git a/search/v2/geocoder.cpp b/search/v2/geocoder.cpp index f3e41535aa..499c3c4b3e 100644 --- a/search/v2/geocoder.cpp +++ b/search/v2/geocoder.cpp @@ -1227,6 +1227,14 @@ void Geocoder::FindPaths() void Geocoder::MatchUnclassified(size_t curToken) { ASSERT(m_layers.empty(), ()); + + // We need to match all unused tokens to UNCLASSIFIED features, + // therefore unused tokens must be adjacent to each other. For + // example, as parks are UNCLASSIFIED now, it's ok to match "London + // Hyde Park", because London will be matched as a city and rest + // adjacent tokens will be matched to "Hyde Park", whereas it's not + // ok to match something to "Park London Hyde", because tokens + // "Park" and "Hyde" are not adjacent. if (NumUnusedTokensGroups() != 1) return; @@ -1239,7 +1247,10 @@ void Geocoder::MatchUnclassified(size_t curToken) allFeatures.Intersect(m_addressFeatures[curToken].get()); } - if (coding::CompressedBitVector::IsEmpty(allFeatures.Get())) + if (m_filter.NeedToFilter(*allFeatures)) + allFeatures.Set(m_filter.Filter(*allFeatures).release(), true /* isOwner */); + + if (allFeatures.IsEmpty()) return; auto emitUnclassified = [&](uint32_t featureId) @@ -1352,17 +1363,13 @@ bool Geocoder::HasUsedTokensInRange(size_t from, size_t to) const size_t Geocoder::NumUnusedTokensGroups() const { - if (m_usedTokens.begin() == m_usedTokens.end()) - return 0; - - size_t numBorders = 0; - for (size_t i = 1; i < m_usedTokens.size(); ++i) + size_t numGroups = 0; + for (size_t i = 0; i < m_usedTokens.size(); ++i) { - if (m_usedTokens[i] != m_usedTokens[i - 1]) - ++numBorders; + if (!m_usedTokens[i] && (i == 0 || m_usedTokens[i - 1])) + ++numGroups; } - size_t const numGroups = numBorders + 1; - return m_usedTokens[0] ? numGroups / 2 : (numGroups + 1) / 2; + return numGroups; } size_t Geocoder::SkipUsedTokens(size_t curToken) const diff --git a/search/v2/geocoder.hpp b/search/v2/geocoder.hpp index 907bfa2e4f..8fe56628a4 100644 --- a/search/v2/geocoder.hpp +++ b/search/v2/geocoder.hpp @@ -234,7 +234,7 @@ private: // it uses pre-loaded lists of streets and villages. SearchModel::SearchType GetSearchTypeInGeocoding(uint32_t featureId); - // Returns true if all tokens are used. + // Returns true iff all tokens are used. bool AllTokensUsed() const; // Returns true if there exists at least one used token in [from, @@ -245,7 +245,7 @@ private: size_t NumUnusedTokensGroups() const; // Advances |curToken| to the nearest unused token, or to the end of - // |m_usedTokens| if there're no unused tokens. + // |m_usedTokens| if there are no unused tokens. size_t SkipUsedTokens(size_t curToken) const; Index & m_index; diff --git a/search/v2/intersection_result.cpp b/search/v2/intersection_result.cpp index 02d9d25020..0733ac2e26 100644 --- a/search/v2/intersection_result.cpp +++ b/search/v2/intersection_result.cpp @@ -19,23 +19,15 @@ void IntersectionResult::Set(SearchModel::SearchType type, uint32_t id) { switch (type) { - case SearchModel::SEARCH_TYPE_POI: - m_poi = id; - break; - case SearchModel::SEARCH_TYPE_BUILDING: - m_building = id; - break; - case SearchModel::SEARCH_TYPE_STREET: - m_street = id; - break; + case SearchModel::SEARCH_TYPE_POI: m_poi = id; break; + case SearchModel::SEARCH_TYPE_BUILDING: m_building = id; break; + case SearchModel::SEARCH_TYPE_STREET: m_street = id; break; case SearchModel::SEARCH_TYPE_CITY: case SearchModel::SEARCH_TYPE_VILLAGE: case SearchModel::SEARCH_TYPE_STATE: case SearchModel::SEARCH_TYPE_COUNTRY: case SearchModel::SEARCH_TYPE_UNCLASSIFIED: - case SearchModel::SEARCH_TYPE_COUNT: - ASSERT(false, ("Unsupported types.")); - break; + case SearchModel::SEARCH_TYPE_COUNT: ASSERT(false, ("Unsupported type.")); break; } }