diff --git a/generator/search_index_builder.cpp b/generator/search_index_builder.cpp index a3366e07fe..5556d8d586 100644 --- a/generator/search_index_builder.cpp +++ b/generator/search_index_builder.cpp @@ -364,7 +364,10 @@ void BuildAddressTable(FilesContainerR & container, Writer & writer) LOG(LINFO, ("Address: Building -> Street (opt, all)", building2Street.GetCount())); } - LOG(LINFO, ("Address: Matched percent", 100 * (1.0 - missing/double(address)))); + double matchedPercent = 100; + if (address > 0) + matchedPercent = 100.0 * (1.0 - static_cast(missing) / static_cast(address)); + LOG(LINFO, ("Address: Matched percent", matchedPercent)); LOG(LINFO, ("Address: Upper bounds", bounds)); } } // namespace diff --git a/search/search_integration_tests/search_query_v2_test.cpp b/search/search_integration_tests/search_query_v2_test.cpp index cd989b7427..7bd5fe2764 100644 --- a/search/search_integration_tests/search_query_v2_test.cpp +++ b/search/search_integration_tests/search_query_v2_test.cpp @@ -76,16 +76,12 @@ UNIT_TEST(SearchQueryV2_Smoke) make_unique()); auto const wonderlandCountry = make_shared(m2::PointD(10, 10), "Wonderland", "en"); + auto const losAlamosCity = make_shared(m2::PointD(10, 10), "Los Alamos", "en", 100 /* rank */); auto const mskCity = make_shared(m2::PointD(0, 0), "Moscow", "en", 100 /* rank */); - auto const busStop = make_shared(m2::PointD(0, 0), "Bus stop", "en"); - auto const tramStop = make_shared(m2::PointD(0.0001, 0.0001), "Tram stop", "en"); - auto const quantumTeleport1 = - make_shared(m2::PointD(0.0002, 0.0002), "Quantum teleport 1", "en"); - auto const quantumTeleport2 = - make_shared(m2::PointD(10, 10), "Quantum teleport 2", "en"); - auto const quantumCafe = make_shared(m2::PointD(-0.0002, -0.0002), "Quantum cafe", "en"); + auto const longPondVillage = make_shared(m2::PointD(15, 15), "Long Pond Village", "en", 10 /* rank */); + auto const feynmanStreet = make_shared( vector{m2::PointD(9.999, 9.999), m2::PointD(10, 10), m2::PointD(10.001, 10.001)}, "Feynman street", "en"); @@ -98,17 +94,29 @@ UNIT_TEST(SearchQueryV2_Smoke) auto const bohrStreet3 = make_shared( vector{m2::PointD(10.002, 9.998), m2::PointD(10.003, 9.997)}, "Bohr street", "en"); + auto const firstAprilStreet = make_shared( + vector{m2::PointD(14.998, 15), m2::PointD(15.002, 15)}, "1st April street", + "en"); + auto const feynmanHouse = make_shared(m2::PointD(10, 10), "Feynman house", "1 unit 1", *feynmanStreet, "en"); auto const bohrHouse = make_shared(m2::PointD(10, 10), "Bohr house", "1 unit 1", *bohrStreet1, "en"); - auto const hilbertHouse = make_shared( vector{ {10.0005, 10.0005}, {10.0006, 10.0005}, {10.0006, 10.0006}, {10.0005, 10.0006}}, "Hilbert house", "1 unit 2", *bohrStreet1, "en"); auto const descartesHouse = make_shared(m2::PointD(10, 10), "Descartes house", "2", "en"); + auto const bornHouse = make_shared(m2::PointD(14.999, 15), "Born house", "8", *firstAprilStreet, "en"); + + auto const busStop = make_shared(m2::PointD(0, 0), "Bus stop", "en"); + auto const tramStop = make_shared(m2::PointD(0.0001, 0.0001), "Tram stop", "en"); + auto const quantumTeleport1 = + make_shared(m2::PointD(0.0002, 0.0002), "Quantum teleport 1", "en"); + auto const quantumTeleport2 = + make_shared(m2::PointD(10, 10), "Quantum teleport 2", "en"); + auto const quantumCafe = make_shared(m2::PointD(-0.0002, -0.0002), "Quantum cafe", "en"); 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"); @@ -116,23 +124,27 @@ UNIT_TEST(SearchQueryV2_Smoke) TestMwmBuilder builder(wonderland, feature::DataHeader::country); 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(*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(*feynmanStreet); - builder.Add(*bohrStreet1); - builder.Add(*bohrStreet2); - builder.Add(*bohrStreet3); - builder.Add(*feynmanHouse); - builder.Add(*bohrHouse); - - builder.Add(*hilbertHouse); builder.Add(*lantern1); builder.Add(*lantern2); - - builder.Add(*descartesHouse); } { @@ -140,6 +152,7 @@ UNIT_TEST(SearchQueryV2_Smoke) builder.Add(*wonderlandCountry); builder.Add(*losAlamosCity); builder.Add(*mskCity); + builder.Add(*longPondVillage); } auto const wonderlandResult = engine.RegisterMap(wonderland); @@ -254,4 +267,11 @@ UNIT_TEST(SearchQueryV2_Smoke) make_shared(wonderlandId, quantumTeleport2)}; TEST(MatchResults(engine, rules, request.Results()), ()); } + + { + TestSearchRequest request(engine, "long pond 1st april street 8", "en", search::SearchParams::ALL, viewport); + request.Wait(); + vector> rules = {make_shared(wonderlandId, bornHouse)}; + TEST(MatchResults(engine, rules, request.Results()), ()); + } } diff --git a/search/search_tests_support/test_feature.cpp b/search/search_tests_support/test_feature.cpp index 9a9788c3d3..fb50767461 100644 --- a/search/search_tests_support/test_feature.cpp +++ b/search/search_tests_support/test_feature.cpp @@ -103,6 +103,28 @@ string TestCity::ToString() const return os.str(); } +// TestVillage ---------------------------------------------------------------------------------------- +TestVillage::TestVillage(m2::PointD const & center, string const & name, string const & lang, + uint8_t rank) + : TestFeature(center, name, lang), m_rank(rank) +{ +} + +void TestVillage::Serialize(FeatureBuilder1 & fb) const +{ + TestFeature::Serialize(fb); + auto const & classificator = classif(); + fb.SetType(classificator.GetTypeByPath({"place", "village"})); + fb.SetRank(m_rank); +} + +string TestVillage::ToString() const +{ + ostringstream os; + os << "TestVillage [" << m_name << ", " << m_lang << ", " << DebugPrint(m_center) << "]"; + return os.str(); +} + // TestStreet -------------------------------------------------------------------------------------- TestStreet::TestStreet(vector const & points, string const & name, string const & lang) : TestFeature(name, lang), m_points(points) diff --git a/search/search_tests_support/test_feature.hpp b/search/search_tests_support/test_feature.hpp index d6341f8967..a3e14c8823 100644 --- a/search/search_tests_support/test_feature.hpp +++ b/search/search_tests_support/test_feature.hpp @@ -66,6 +66,19 @@ private: uint8_t const m_rank; }; +class TestVillage : public TestFeature +{ +public: + TestVillage(m2::PointD const & center, string const & name, string const & lang, uint8_t rank); + + // TestFeature overrides: + void Serialize(FeatureBuilder1 & fb) const override; + string ToString() const override; + +private: + uint8_t const m_rank; +}; + class TestStreet : public TestFeature { public: diff --git a/search/v2/features_layer_matcher.hpp b/search/v2/features_layer_matcher.hpp index 9fee53fe76..822680257f 100644 --- a/search/v2/features_layer_matcher.hpp +++ b/search/v2/features_layer_matcher.hpp @@ -70,6 +70,7 @@ public: { case SearchModel::SEARCH_TYPE_POI: case SearchModel::SEARCH_TYPE_CITY: + case SearchModel::SEARCH_TYPE_VILLAGE: case SearchModel::SEARCH_TYPE_STATE: case SearchModel::SEARCH_TYPE_COUNTRY: case SearchModel::SEARCH_TYPE_COUNT: diff --git a/search/v2/geocoder.cpp b/search/v2/geocoder.cpp index 76a26f1e59..6b2d199edb 100644 --- a/search/v2/geocoder.cpp +++ b/search/v2/geocoder.cpp @@ -551,7 +551,7 @@ void Geocoder::ClearCaches() m_addressFeatures.clear(); m_matchersCache.clear(); m_streetsCache.clear(); - m_villagesCache.clear(); + m_villages.reset(); } void Geocoder::PrepareRetrievalParams(size_t curToken, size_t endToken) @@ -758,7 +758,7 @@ void Geocoder::FillLocalitiesTable() void Geocoder::FillVillageLocalities() { vector preLocalities; - FillLocalityCandidates(m_villages, kMaxNumVillages, preLocalities); + FillLocalityCandidates(m_villages.get(), kMaxNumVillages, preLocalities); size_t numVillages = 0; @@ -1240,21 +1240,12 @@ coding::CompressedBitVector const * Geocoder::LoadStreets(MwmContext & context) return result; } -coding::CompressedBitVector const * Geocoder::LoadVillages(MwmContext & context) +unique_ptr Geocoder::LoadVillages(MwmContext & context) { if (!context.m_handle.IsAlive() || !HasSearchIndex(context.m_value)) - return nullptr; + return make_unique(); - auto mwmId = context.m_handle.GetId(); - auto const it = m_villagesCache.find(mwmId); - if (it != m_villagesCache.cend()) - return it->second.get(); - - auto villages = LoadCategories(context, GetVillageCategories()); - - auto const * result = villages.get(); - m_villagesCache[mwmId] = move(villages); - return result; + return LoadCategories(context, GetVillageCategories()); } coding::CompressedBitVector const * Geocoder::RetrieveGeometryFeatures(MwmContext const & context, diff --git a/search/v2/geocoder.hpp b/search/v2/geocoder.hpp index 35113750fb..7cbe2bb65c 100644 --- a/search/v2/geocoder.hpp +++ b/search/v2/geocoder.hpp @@ -118,8 +118,11 @@ private: RegionType m_type; }; - // This struct represents a city. It is used to filter features + // This struct represents a city or a village. It is used to filter features // during search. + // todo(@m) It works well as is, but consider a new naming scheme + // when counties etc. are added. E.g., Region for countries and + // states and Locality for smaller settlements. struct City : public Locality { City(Locality const & l): Locality(l) {} @@ -197,7 +200,7 @@ private: coding::CompressedBitVector const * LoadStreets(MwmContext & context); - coding::CompressedBitVector const * LoadVillages(MwmContext & context); + unique_ptr LoadVillages(MwmContext & context); /// A caching wrapper around Retrieval::RetrieveGeometryFeatures. /// param[in] Optional query id. Use VIEWPORT_ID, POSITION_ID or feature index for locality. @@ -252,14 +255,11 @@ private: // Cache of street ids in mwms. map> m_streetsCache; - // Cache of village ids in mwms. - map> m_villagesCache; - // Street features in the mwm that is currently being processed. coding::CompressedBitVector const * m_streets; // Village features in the mwm that is currently being processed. - coding::CompressedBitVector const * m_villages; + unique_ptr m_villages; // This vector is used to indicate what tokens were matched by // locality and can't be re-used during the geocoding process. diff --git a/search/v2/intersection_result.cpp b/search/v2/intersection_result.cpp index 14e1acb4b8..1d693ed325 100644 --- a/search/v2/intersection_result.cpp +++ b/search/v2/intersection_result.cpp @@ -29,6 +29,7 @@ void IntersectionResult::Set(SearchModel::SearchType type, uint32_t id) 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_COUNT: diff --git a/search/v2/search_model.cpp b/search/v2/search_model.cpp index 51f6077ad2..a4ad3473a5 100644 --- a/search/v2/search_model.cpp +++ b/search/v2/search_model.cpp @@ -115,6 +115,8 @@ string DebugPrint(SearchModel::SearchType type) return "STREET"; case SearchModel::SEARCH_TYPE_CITY: return "CITY"; + case SearchModel::SEARCH_TYPE_VILLAGE: + return "VILLAGE"; case SearchModel::SEARCH_TYPE_STATE: return "STATE"; case SearchModel::SEARCH_TYPE_COUNTRY: