diff --git a/indexer/CMakeLists.txt b/indexer/CMakeLists.txt index e3f074ff67..8dd95d83c2 100644 --- a/indexer/CMakeLists.txt +++ b/indexer/CMakeLists.txt @@ -70,6 +70,7 @@ set( features_offsets_table.hpp features_vector.cpp features_vector.hpp + ftypes_mapping.cpp ftypes_matcher.cpp ftypes_matcher.hpp geometry_coding.cpp diff --git a/indexer/ftypes_mapping.hpp b/indexer/ftypes_mapping.hpp new file mode 100644 index 0000000000..715afc8e9d --- /dev/null +++ b/indexer/ftypes_mapping.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "indexer/classificator.hpp" +#include "indexer/feature_data.hpp" + +#include +#include +#include +#include +#include + +namespace ftypes +{ +template +class Matcher +{ +public: + typename Container::const_iterator + Find(feature::TypesHolder const & types) const + { + for (auto const t : types) + { + for (auto level = ftype::GetLevel(t); level; --level) + { + auto truncatedType = t; + ftype::TruncValue(truncatedType, level); + auto const it = m_mapping.find(truncatedType); + + if (it != m_mapping.cend()) + return it; + } + } + + return m_mapping.cend(); + } + + bool IsValid(typename Container::const_iterator it) const + { + return it != m_mapping.cend(); + } + + bool Contains(feature::TypesHolder const & types) const + { + return IsValid(Find(types)); + } + + template + void Append(std::vector> const & types, Args ... args) + { + for (auto const & type : types) + { +#if defined(DEBUG) + feature::TypesHolder holder; + holder.Assign(classif().GetTypeByPath(type)); + ASSERT(Find(holder) == m_mapping.cend(), ("This type already exists", type)); +#endif + m_mapping.emplace(classif().GetTypeByPath(type), std::forward(args)...); + } + } + +private: + Container m_mapping; +}; + +template +using HashMap = Matcher>; + +template +using HashSet = Matcher>; +} // namespace ftypes diff --git a/indexer/ftypes_matcher.hpp b/indexer/ftypes_matcher.hpp index 763d8eeca4..2c42cd1f22 100644 --- a/indexer/ftypes_matcher.hpp +++ b/indexer/ftypes_matcher.hpp @@ -15,7 +15,6 @@ class FeatureType; namespace ftypes { - class BaseChecker { size_t const m_level; diff --git a/indexer/indexer.pro b/indexer/indexer.pro index 87345a9f12..2dfa56dbc6 100644 --- a/indexer/indexer.pro +++ b/indexer/indexer.pro @@ -97,6 +97,7 @@ HEADERS += \ feature_visibility.hpp \ features_offsets_table.hpp \ features_vector.hpp \ + ftypes_mapping.hpp \ ftypes_matcher.hpp \ geometry_coding.hpp \ geometry_serialization.hpp \ @@ -134,7 +135,6 @@ HEADERS += \ types_mapping.hpp \ unique_index.hpp \ - OTHER_FILES += drules_struct.proto SOURCES += drules_struct.pb.cc diff --git a/map/framework.cpp b/map/framework.cpp index 4abd9a1a4d..5b427920e2 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -415,9 +415,6 @@ Framework::Framework(FrameworkParams const & params) }) , m_lastReportedCountry(kInvalidCountryId) { - if (!params.m_disableLocalAds) - m_localAdsManager.Startup(); - m_startBackgroundTime = my::Timer::LocalTime(); // Restore map style before classificator loading @@ -451,6 +448,9 @@ Framework::Framework(FrameworkParams const & params) m_model.SetOnMapDeregisteredCallback(bind(&Framework::OnMapDeregistered, this, _1)); LOG(LDEBUG, ("Classificator initialized")); + if (!params.m_disableLocalAds) + m_localAdsManager.Startup(); + m_displayedCategories = make_unique(GetDefaultCategories()); // To avoid possible races - init country info getter once in constructor. @@ -932,6 +932,17 @@ void Framework::FillInfoFromFeatureType(FeatureType const & ft, place_page::Info info.m_localizedWifiString = m_stringsBundle.GetString("wifi"); info.m_localizedRatingString = m_stringsBundle.GetString("place_page_booking_rating"); + + if (m_localAdsManager.IsSupportedType(info.GetTypes())) + { + info.m_localAdsStatus = m_localAdsManager.Contains(ft.GetID()) + ? place_page::LocalAdsStatus::Customer + : place_page::LocalAdsStatus::Candidate; + } + else + { + info.m_localAdsStatus = place_page::LocalAdsStatus::Unavailable; + } } void Framework::FillApiMarkInfo(ApiMarkPoint const & api, place_page::Info & info) const diff --git a/map/local_ads_manager.cpp b/map/local_ads_manager.cpp index 1443cdf7c5..801fca7c63 100644 --- a/map/local_ads_manager.cpp +++ b/map/local_ads_manager.cpp @@ -8,6 +8,7 @@ #include "drape_frontend/drape_engine.hpp" #include "drape_frontend/visual_params.hpp" +#include "indexer/feature_data.hpp" #include "indexer/scales.hpp" #include "platform/http_client.hpp" @@ -141,6 +142,11 @@ std::vector SerializeLocalAdsToJSON(std::list const & return result; } #endif + +void FillExcludeTypes(ftypes::HashSet & excludeTypes) +{ + excludeTypes.Append({{"amenity", "bench"}}); +} } // namespace LocalAdsManager::LocalAdsManager(GetMwmsByRectFn const & getMwmsByRectFn, @@ -176,6 +182,7 @@ void LocalAdsManager::Startup() m_thread = threads::SimpleThread(&LocalAdsManager::ThreadRoutine, this); m_statistics.Startup(); + FillExcludeTypes(m_excludeTypes); } void LocalAdsManager::Teardown() @@ -449,3 +456,8 @@ bool LocalAdsManager::Contains(FeatureID const & featureId) const std::lock_guard lock(m_featuresCacheMutex); return m_featuresCache.find(featureId) != m_featuresCache.cend(); } + +bool LocalAdsManager::IsSupportedType(feature::TypesHolder const & types) const +{ + return !m_excludeTypes.Contains(types); +} diff --git a/map/local_ads_manager.hpp b/map/local_ads_manager.hpp index 97ac0c6958..cf6f801c9a 100644 --- a/map/local_ads_manager.hpp +++ b/map/local_ads_manager.hpp @@ -9,6 +9,7 @@ #include "geometry/rect2d.hpp" #include "geometry/screenbase.hpp" +#include "indexer/ftypes_mapping.hpp" #include "indexer/index.hpp" #include "indexer/mwm_set.hpp" @@ -24,7 +25,12 @@ namespace df { class DrapeEngine; -} // namespace df +} + +namespace feature +{ +class TypesHolder; +} class LocalAdsManager final { @@ -51,6 +57,7 @@ public: local_ads::Statistics const & GetStatistics() const { return m_statistics; } bool Contains(FeatureID const & featureId) const; + bool IsSupportedType(feature::TypesHolder const & types) const; private: enum class RequestType @@ -97,4 +104,6 @@ private: std::set m_featuresCache; mutable std::mutex m_featuresCacheMutex; + + ftypes::HashSet m_excludeTypes; }; diff --git a/map/place_page_info.cpp b/map/place_page_info.cpp index dbae446838..eed0db0662 100644 --- a/map/place_page_info.cpp +++ b/map/place_page_info.cpp @@ -215,4 +215,6 @@ bool Info::IsReachableByTaxi() const void Info::SetMercator(m2::PointD const & mercator) { m_mercator = mercator; } vector Info::GetRawTypes() const { return m_types.ToObjectNames(); } string const & Info::GetBookingSearchUrl() const { return m_bookingSearchUrl; } +LocalAdsStatus Info::GetLocalAdsStatus() const { return m_localAdsStatus; } +string const & Info::GetLocalAdsUrl() const { return m_localAdsUrl; } } // namespace place_page diff --git a/map/place_page_info.hpp b/map/place_page_info.hpp index 83098bfa5d..6681303a6d 100644 --- a/map/place_page_info.hpp +++ b/map/place_page_info.hpp @@ -32,6 +32,13 @@ enum class SponsoredType Geochat }; +enum class LocalAdsStatus +{ + Unavailable, + Candidate, + Customer +}; + class Info : public osm::MapObject { public: @@ -100,6 +107,10 @@ public: string const & GetBookingSearchUrl() const; + LocalAdsStatus GetLocalAdsStatus() const; + + string const & GetLocalAdsUrl() const; + /// Comes from API, shared links etc. string m_customName; /// If not empty, bookmark is bound to this place page. @@ -148,5 +159,8 @@ public: string m_bookingSearchUrl; /// Ads source. ads::Engine * m_adsEngine = nullptr; + + LocalAdsStatus m_localAdsStatus = LocalAdsStatus::Unavailable; + string m_localAdsUrl; }; } // namespace place_page diff --git a/partners_api/ads_base.cpp b/partners_api/ads_base.cpp index 0bb98c0483..0f8633b9b3 100644 --- a/partners_api/ads_base.cpp +++ b/partners_api/ads_base.cpp @@ -5,29 +5,6 @@ #include -namespace -{ -template -typename Container::const_iterator -FindType(feature::TypesHolder const & types, Container const & cont) -{ - for (auto const t : types) - { - for (auto level = ftype::GetLevel(t); level; --level) - { - auto truncatedType = t; - ftype::TruncValue(truncatedType, level); - auto const it = cont.find(truncatedType); - - if (it != cont.end()) - return it; - } - } - - return cont.cend(); -} -} // namespace - namespace ads { Container::Container() { AppendExcludedTypes({{"sponsored", "booking"}}); } @@ -35,30 +12,12 @@ Container::Container() { AppendExcludedTypes({{"sponsored", "booking"}}); } void Container::AppendEntry(std::vector> const & types, std::string const & id) { - for (auto const & type : types) - { -#if defined(DEBUG) - feature::TypesHolder holder; - holder.Assign(classif().GetTypeByPath(type)); - ASSERT(FindType(holder, m_typesToBanners) == m_typesToBanners.cend(), - ("Banner id for this type already exists", type)); -#endif - m_typesToBanners.emplace(classif().GetTypeByPath(type), id); - } + m_typesToBanners.Append(types, id); } void Container::AppendExcludedTypes(std::vector> const & types) { - for (auto const & type : types) - { -#if defined(DEBUG) - feature::TypesHolder holder; - holder.Assign(classif().GetTypeByPath(type)); - ASSERT(FindType(holder, m_excludedTypes) == m_excludedTypes.cend(), - ("Excluded banner type already exists")); -#endif - m_excludedTypes.emplace(classif().GetTypeByPath(type)); - } + m_excludedTypes.Append(types); } void Container::AppendSupportedCountries(std::vector const & countries) @@ -75,7 +34,7 @@ bool Container::HasBanner(feature::TypesHolder const & types, return false; } - return FindType(types, m_excludedTypes) == m_excludedTypes.cend(); + return !m_excludedTypes.Contains(types); } std::string Container::GetBannerId(feature::TypesHolder const & types, @@ -84,8 +43,8 @@ std::string Container::GetBannerId(feature::TypesHolder const & types, if (!HasBanner(types, countryId)) return {}; - auto const it = FindType(types, m_typesToBanners); - if (it != m_typesToBanners.cend()) + auto const it = m_typesToBanners.Find(types); + if (m_typesToBanners.IsValid(it)) return it->second; return GetBannerIdForOtherTypes(); diff --git a/partners_api/ads_base.hpp b/partners_api/ads_base.hpp index 69e228f35a..023439b43e 100644 --- a/partners_api/ads_base.hpp +++ b/partners_api/ads_base.hpp @@ -1,12 +1,13 @@ #pragma once +#include "indexer/ftypes_mapping.hpp" + #include "storage/index.hpp" #include "base/macros.hpp" #include #include -#include #include #include @@ -51,8 +52,8 @@ protected: void AppendSupportedCountries(std::vector const & countries); private: - std::unordered_map m_typesToBanners; - std::unordered_set m_excludedTypes; + ftypes::HashMap m_typesToBanners; + ftypes::HashSet m_excludedTypes; // All countries are supported when empty. std::unordered_set m_supportedCountries; diff --git a/xcode/indexer/indexer.xcodeproj/project.pbxproj b/xcode/indexer/indexer.xcodeproj/project.pbxproj index 721d9382d8..71ca52b3b3 100644 --- a/xcode/indexer/indexer.xcodeproj/project.pbxproj +++ b/xcode/indexer/indexer.xcodeproj/project.pbxproj @@ -58,6 +58,7 @@ 3D51BC421D5E4D3800F1FA8D /* libgenerator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D51BC381D5E4C4300F1FA8D /* libgenerator.a */; }; 3D51BC431D5E4E2B00F1FA8D /* test_mwm_set.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 56C74C2D1C749E8100B71B9F /* test_mwm_set.hpp */; }; 3D51BC451D5E4EBF00F1FA8D /* libsearch_tests_support.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3D51BC441D5E4EBF00F1FA8D /* libsearch_tests_support.a */; }; + 3D74ABBC1EA67C1E0063A898 /* ftypes_mapping.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D74ABBB1EA67C1E0063A898 /* ftypes_mapping.hpp */; }; 3D928F671D50F9FE001670E0 /* index_helpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3D928F651D50F9FE001670E0 /* index_helpers.cpp */; }; 3D928F681D50F9FE001670E0 /* index_helpers.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3D928F661D50F9FE001670E0 /* index_helpers.hpp */; }; 45C108B11E9CFE41000FE1F6 /* polyline_point_to_int64_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45C108AF1E9CFE3E000FE1F6 /* polyline_point_to_int64_test.cpp */; }; @@ -275,6 +276,7 @@ 3D51BC3E1D5E4C8800F1FA8D /* librouting.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = librouting.a; path = "../../../omim-xcode-build/Debug/librouting.a"; sourceTree = ""; }; 3D51BC401D5E4CFA00F1FA8D /* libtess2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libtess2.a; path = "../../../omim-xcode-build/Debug/libtess2.a"; sourceTree = ""; }; 3D51BC441D5E4EBF00F1FA8D /* libsearch_tests_support.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libsearch_tests_support.a; path = "../../../omim-xcode-build/Debug/libsearch_tests_support.a"; sourceTree = ""; }; + 3D74ABBB1EA67C1E0063A898 /* ftypes_mapping.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = ftypes_mapping.hpp; sourceTree = ""; }; 3D928F651D50F9FE001670E0 /* index_helpers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = index_helpers.cpp; sourceTree = ""; }; 3D928F661D50F9FE001670E0 /* index_helpers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = index_helpers.hpp; sourceTree = ""; }; 45C108AF1E9CFE3E000FE1F6 /* polyline_point_to_int64_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = polyline_point_to_int64_test.cpp; sourceTree = ""; }; @@ -637,6 +639,7 @@ 6753409C1A3F53CB00A0A8C3 /* indexer */ = { isa = PBXGroup; children = ( + 3D74ABBB1EA67C1E0063A898 /* ftypes_mapping.hpp */, 3D928F651D50F9FE001670E0 /* index_helpers.cpp */, 3D928F661D50F9FE001670E0 /* index_helpers.hpp */, 34664CEE1D49FEC1003D7096 /* altitude_loader.cpp */, @@ -818,6 +821,7 @@ 56C74C251C749E4700B71B9F /* search_string_utils.hpp in Headers */, 6753410C1A3F540F00A0A8C3 /* drawing_rule_def.hpp in Headers */, 675341001A3F540F00A0A8C3 /* cell_id.hpp in Headers */, + 3D74ABBC1EA67C1E0063A898 /* ftypes_mapping.hpp in Headers */, 670D04AD1B0BA8580013A7AC /* interval_index_101.hpp in Headers */, 67BC92F51D21476500A4A378 /* string_slice.hpp in Headers */, 675341271A3F540F00A0A8C3 /* features_vector.hpp in Headers */,