From 67a4781b8ed6dabdaf466369053fe43f48815b37 Mon Sep 17 00:00:00 2001 From: tatiana-yan Date: Wed, 14 Nov 2018 19:32:49 +0300 Subject: [PATCH] [map][search] Show more icons for search results. --- map/framework.cpp | 36 +- map/search_mark.cpp | 317 ++++++++++++++---- map/search_mark.hpp | 29 +- .../assessment_tool/sample_view.cpp | 2 +- 4 files changed, 269 insertions(+), 115 deletions(-) diff --git a/map/framework.cpp b/map/framework.cpp index 184a8a4b25..7f21a7ebac 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1663,7 +1663,7 @@ void Framework::FillSearchResultsMarks(search::Results::ConstIter begin, if (r.m_metadata.m_isSponsoredHotel) { - mark->SetMarkType(SearchMarkType::Booking); + mark->SetBookingType(isFeature && m_localAdsManager.Contains(r.GetFeatureID()) /* hasLocalAds */); mark->SetRating(r.m_metadata.m_hotelRating); mark->SetPricing(r.m_metadata.m_hotelPricing); } @@ -1673,45 +1673,15 @@ void Framework::FillSearchResultsMarks(search::Results::ConstIter begin, auto const type = r.GetFeatureType(); if (product.m_ugcRating != search::ProductInfo::kInvalidRating) { - mark->SetMarkType(SearchMarkType::UGC); + mark->SetUGCType(); mark->SetRating(product.m_ugcRating); } else { - auto const cafeType = ftypes::IsEatChecker::Instance().GetType(type); - switch (cafeType) - { - case ftypes::IsEatChecker::Type::Cafe: - mark->SetMarkType(SearchMarkType::Cafe); - break; - case ftypes::IsEatChecker::Type::Bakery: - mark->SetMarkType(SearchMarkType::Bakery); - break; - case ftypes::IsEatChecker::Type::FastFood: - mark->SetMarkType(SearchMarkType::FastFood); - break; - case ftypes::IsEatChecker::Type::Restaurant: - mark->SetMarkType(SearchMarkType::Restaurant); - break; - case ftypes::IsEatChecker::Type::Bar: - mark->SetMarkType(SearchMarkType::Bar); - break; - case ftypes::IsEatChecker::Type::Pub: - case ftypes::IsEatChecker::Type::Biergarten: - mark->SetMarkType(SearchMarkType::Pub); - break; - case ftypes::IsEatChecker::Type::Count: - break; - } + mark->SetFromType(type, m_localAdsManager.Contains(r.GetFeatureID())); } } - if (isFeature && m_localAdsManager.Contains(r.GetFeatureID())) - { - mark->SetMarkType(r.m_metadata.m_isSponsoredHotel ? SearchMarkType::LocalAdsBooking - : SearchMarkType::LocalAds); - } - if (fn) fn(*mark); } diff --git a/map/search_mark.cpp b/map/search_mark.cpp index 5b7eb0fffb..3a47cfe8bb 100644 --- a/map/search_mark.cpp +++ b/map/search_mark.cpp @@ -7,42 +7,98 @@ #include "platform/platform.hpp" +#include "base/stl_helpers.hpp" + #include +#include +#include namespace { -std::vector const kSymbols = +enum class SearchMarkType { - "search-result", // Default. - "coloredmark-default-l", // Booking. - "search-adv", // Local Ads. - "searchbookingadv-default-l", // Local Ads + Booking. - "coloredmark-default-l", // UGC. - "search-result-cafe", // Cafe. - "search-result-bakery", // Bakery. - "search-result-bar", // Bar. - "search-result-pub", // Pub. - "search-result-restaurant", // Restaurant. - "search-result-fastfood", // FastFood. + Default = 0, + Booking, + UGC, + Cafe, + Bakery, + Bar, + Pub, + Restaurant, + FastFood, + Casino, + Cinema, + Marketplace, + Nightclub, + Playground, + ShopAlcohol, + ShopButcher, + ShopClothes, + ShopConfectionery, + ShopConvenience, + ShopCosmetics, + ShopDepartmentStore, + ShopGift, + ShopGreengrocer, + ShopJewelry, + ShopMall, + ShopSeafood, + ShopShoes, + ShopSports, + ShopSupermarket, + ShopToys, + ThemePark, + WaterPark, + Zoo, - "non-found-search-result", // NotFound. + NotFound, // Service value used in developer tools. + Count }; -std::vector const kPreparingSymbols = -{ - "search-result", // Default. - "coloredmark-inactive", // Booking. - "search-adv", // Local Ads. - "searchbookingadv-default-l", // Local Ads + Booking. - "coloredmark-inactive", // UGC. - "search-result-cafe", // Cafe. - "search-result-bakery", // Bakery. - "search-result-bar", // Bar. - "search-result-pub", // Pub. - "search-result-restaurant", // Restaurant. - "search-result-fastfood", // FastFood. +static_assert(static_cast(SearchMarkType::Count) <= std::numeric_limits::max(), + "Change SearchMarkPoint::m_type type."); - "non-found-search-result", // NotFound. +SearchMarkType SMT(uint8_t type) +{ + return static_cast(type); +} + +std::array(SearchMarkType::Count)> const kSymbols = { + "search-result", // Default. + "coloredmark-default-l", // Booking. + "coloredmark-default-l", // UGC. + "search-result-cafe", // Cafe. + "search-result-bakery", // Bakery. + "search-result-bar", // Bar. + "search-result-pub", // Pub. + "search-result-restaurant", // Restaurant. + "search-result-fastfood", // FastFood. + "search-result-casino", // Casino. + "search-result-cinema", // Cinema. + "search-result-marketplace", // Marketplace. + "search-result-nightclub", // Nightclub. + "search-result-playground", // Playground. + "search-result-shop-alcohol", // ShopAlcohol. + "search-result-shop-butcher", // ShopButcher. + "search-result-shop-clothes", // ShopClothes. + "search-result-shop-confectionery", // ShopConfectionery. + "search-result-shop-convenience", // ShopConvenience. + "search-result-shop-cosmetics", // ShopCosmetics. + "search-result-shop-department_store", // ShopDepartmentStore. + "search-result-shop-gift", // ShopGift. + "search-result-shop-greengrocer", // ShopGreengrocer. + "search-result-shop-jewelry", // ShopJewelry. + "search-result-shop-mall", // ShopMall. + "search-result-shop-seafood", // ShopSeafood. + "search-result-shop-shoes", // ShopShoes. + "search-result-shop-sports", // ShopSports. + "search-result-shop-supermarket", // ShopSupermarket. + "search-result-shop-toys", // ShopToys. + "search-result-theme-park", // ThemePark. + "search-result-water-park", // WaterPark. + "search-result-zoo", // Zoo. + + "non-found-search-result", // NotFound. }; std::string const kSaleBadgeName = "searchbooking-sale-1"; @@ -81,13 +137,131 @@ bool NeedShowBookingBadge(float rating, int pricing) return metric >= kMetricThreshold; } -std::string GetBookingSmallIcon(SearchMarkType type) +std::string GetBookingSmallIcon(SearchMarkType type, bool hasLocalAds) { - if (type == SearchMarkType::Booking) - return "coloredmark-default-s"; - if (type == SearchMarkType::LocalAdsBooking) - return "search-adv"; - return {}; + if (type != SearchMarkType::Booking) + return {}; + + return hasLocalAds ? "search-adv" : "coloredmark-default-s"; +} + +std::string GetSymbol(SearchMarkType searchMarkType, bool hasLocalAds) +{ + auto const index = static_cast(searchMarkType); + ASSERT_LESS(index, kSymbols.size(), ()); + if (!hasLocalAds) + return kSymbols[index]; + + if (searchMarkType == SearchMarkType::Booking) + return "searchbookingadv-default-l"; + + return "local_ads-" + kSymbols[index]; +} + +bool HasLocalAdsVariant(SearchMarkType searchMarkType) +{ + if (searchMarkType == SearchMarkType::UGC || searchMarkType == SearchMarkType::NotFound) + return false; + return true; +} + +std::string GetPreparingSymbol(SearchMarkType searchMarkType, bool hasLocalAds) +{ + if (!hasLocalAds && + (searchMarkType == SearchMarkType::Booking || searchMarkType == SearchMarkType::UGC)) + { + return "coloredmark-inactive"; + } + return GetSymbol(searchMarkType, hasLocalAds); +} + +m2::PointD GetSize(SearchMarkType searchMarkType, bool hasLocalAds, ScreenBase const & modelView) +{ + if (!SearchMarks::HaveSizes()) + return {}; + + auto const pixelSize = + SearchMarks::GetSize(GetSymbol(searchMarkType, hasLocalAds)).get_value_or({}); + double const pixelToMercator = modelView.GetScale(); + return {pixelToMercator * pixelSize.x, pixelToMercator * pixelSize.y}; +} + +class SearchMarkTypeChecker +{ +public: + static SearchMarkTypeChecker & Instance() + { + static SearchMarkTypeChecker checker; + return checker; + } + + SearchMarkType GetSearchMarkType(uint32_t type) const + { + auto const it = std::lower_bound(m_searchMarkTypes.cbegin(), m_searchMarkTypes.cend(), + Type(type, SearchMarkType::Count), base::LessBy(&Type::first)); + if (it == m_searchMarkTypes.cend() || it->first != type) + return SearchMarkType::Default; + + return it->second; + } + +private: + using Type = std::pair; + + SearchMarkTypeChecker() + { + auto const & c = classif(); + std::vector, SearchMarkType>> const table = { + {{"amenity", "cafe"}, SearchMarkType::Cafe}, + {{"shop", "bakery"}, SearchMarkType::Bakery}, + {{"amenity", "bar"}, SearchMarkType::Bar}, + {{"amenity", "pub"}, SearchMarkType::Pub}, + {{"amenity", "biergarten"}, SearchMarkType::Pub}, + {{"amenity", "restaurant"}, SearchMarkType::Restaurant}, + {{"amenity", "fast_food"}, SearchMarkType::FastFood}, + {{"amenity", "casino"}, SearchMarkType::Casino}, + {{"amenity", "cinema"}, SearchMarkType::Cinema}, + {{"amenity", "marketplace"}, SearchMarkType::Marketplace}, + {{"amenity", "nightclub"}, SearchMarkType::Nightclub}, + {{"leisure", "playground"}, SearchMarkType::Playground}, + {{"shop", "alcohol"}, SearchMarkType::ShopAlcohol}, + {{"shop", "beverages"}, SearchMarkType::ShopAlcohol}, + {{"shop", "wine"}, SearchMarkType::ShopAlcohol}, + {{"shop", "butcher"}, SearchMarkType::ShopButcher}, + {{"shop", "clothes"}, SearchMarkType::ShopClothes}, + {{"shop", "confectionery"}, SearchMarkType::ShopConfectionery}, + {{"shop", "convenience"}, SearchMarkType::ShopConvenience}, + {{"shop", "variety_store"}, SearchMarkType::ShopConvenience}, + {{"shop", "cosmetics"}, SearchMarkType::ShopCosmetics}, + {{"shop", "department_store"}, SearchMarkType::ShopDepartmentStore}, + {{"shop", "gift"}, SearchMarkType::ShopGift}, + {{"shop", "greengrocer"}, SearchMarkType::ShopGreengrocer}, + {{"shop", "jewelry"}, SearchMarkType::ShopJewelry}, + {{"shop", "mall"}, SearchMarkType::ShopMall}, + {{"shop", "seafood"}, SearchMarkType::ShopSeafood}, + {{"shop", "shoes"}, SearchMarkType::ShopShoes}, + {{"shop", "sports"}, SearchMarkType::ShopSports}, + {{"shop", "supermarket"}, SearchMarkType::ShopSupermarket}, + {{"shop", "toys"}, SearchMarkType::ShopToys}, + {{"tourism", "theme_park"}, SearchMarkType::ThemePark}, + {{"leisure", "water_park"}, SearchMarkType::WaterPark}, + {{"tourism", "zoo"}, SearchMarkType::Zoo} + }; + + m_searchMarkTypes.reserve(table.size()); + for (auto const & p : table) + m_searchMarkTypes.push_back({c.GetTypeByPath(p.first), p.second}); + + std::sort(m_searchMarkTypes.begin(), m_searchMarkTypes.end(), base::LessBy(&Type::first)); + } + + std::vector m_searchMarkTypes; +}; + +SearchMarkType GetSearchMarkType(uint32_t type) +{ + auto const & checker = SearchMarkTypeChecker::Instance(); + return checker.GetSearchMarkType(type); } } // namespace @@ -103,25 +277,26 @@ SearchMarkPoint::SearchMarkPoint(m2::PointD const & ptOrg) drape_ptr SearchMarkPoint::GetSymbolNames() const { std::string name; - if (m_type >= SearchMarkType::Count) + if (m_type >= static_cast(SearchMarkType::Count)) { ASSERT(false, ("Unknown search mark symbol.")); - name = kSymbols[static_cast(SearchMarkType::Default)]; + name = GetSymbol(SearchMarkType::Default, false /* hasLocalAds */); } else if (m_isPreparing) { - name = kPreparingSymbols[static_cast(m_type)]; + name = GetPreparingSymbol(SMT(m_type), m_hasLocalAds); } else { - name = kSymbols[static_cast(m_type)]; + name = GetSymbol(SMT(m_type), m_hasLocalAds); } auto symbol = make_unique_dp(); if (IsMarkWithRating()) { - symbol->insert(std::make_pair(1 /* zoomLevel */, m_rating < kRatingThreshold ? - GetBookingSmallIcon(m_type) : name)); + symbol->insert(std::make_pair( + 1 /* zoomLevel */, + m_rating < kRatingThreshold ? GetBookingSmallIcon(SMT(m_type), m_hasLocalAds) : name)); symbol->insert(std::make_pair(17 /* zoomLevel */, name)); } else @@ -157,7 +332,7 @@ drape_ptr SearchMarkPoint::GetSymbolOffsets() if (badgeName.empty() || !SearchMarks::GetSize(badgeName)) return nullptr; - auto const name = kSymbols[static_cast(SearchMarkType::Booking)]; + auto const name = GetSymbol(SearchMarkType::Booking, false /* hasLocalAds */); auto const iconSz = SearchMarks::GetSize(name).get_value_or({}); SymbolOffsets offsets(scales::UPPER_STYLE_SCALE); @@ -175,7 +350,7 @@ df::ColorConstant SearchMarkPoint::GetColorConstant() const if (!IsMarkWithRating()) return {}; - if (m_type == SearchMarkType::LocalAdsBooking) + if (SMT(m_type) == SearchMarkType::Booking && m_hasLocalAds) return "RatingLocalAds"; if (HasNoRating(m_rating)) @@ -223,9 +398,28 @@ void SearchMarkPoint::SetMatchedName(std::string const & name) SetAttributeValue(m_matchedName, name); } -void SearchMarkPoint::SetMarkType(SearchMarkType type) +void SearchMarkPoint::SetFromType(uint32_t type, bool hasLocalAds) { - SetAttributeValue(m_type, type); + SetAttributeValue(m_hasLocalAds, hasLocalAds); + SetAttributeValue(m_type, static_cast(GetSearchMarkType(type))); +} + +void SearchMarkPoint::SetBookingType(bool hasLocalAds) +{ + SetAttributeValue(m_hasLocalAds, hasLocalAds); + SetAttributeValue(m_type, static_cast(SearchMarkType::Booking)); +} + +void SearchMarkPoint::SetUGCType() +{ + SetAttributeValue(m_hasLocalAds, false); + SetAttributeValue(m_type, static_cast(SearchMarkType::UGC)); +} + +void SearchMarkPoint::SetNotFoundType() +{ + SetAttributeValue(m_hasLocalAds, false); + SetAttributeValue(m_type, static_cast(SearchMarkType::NotFound)); } void SearchMarkPoint::SetPreparing(bool isPreparing) @@ -251,13 +445,12 @@ void SearchMarkPoint::SetSale(bool hasSale) bool SearchMarkPoint::IsBookingSpecialMark() const { - return (m_type == SearchMarkType::Booking || m_type == SearchMarkType::LocalAdsBooking) && - !m_isPreparing; + return (SMT(m_type) == SearchMarkType::Booking) && !m_isPreparing; } bool SearchMarkPoint::IsUGCMark() const { - return m_type == SearchMarkType::UGC; + return SMT(m_type) == SearchMarkType::UGC; } bool SearchMarkPoint::IsMarkWithRating() const @@ -279,7 +472,16 @@ void SearchMarks::SetDrapeEngine(ref_ptr engine) return; std::vector symbols; - symbols.insert(symbols.end(), kSymbols.begin(), kSymbols.end()); + auto const searchMarkTypesCount = static_cast(SearchMarkType::Count); + symbols.reserve(searchMarkTypesCount * 2); + for (size_t t = 0; t < searchMarkTypesCount; ++t) + { + auto const searchMarkType = SMT(t); + symbols.push_back(GetSymbol(searchMarkType, false /* hasLocalAds */)); + if (HasLocalAdsVariant(searchMarkType)) + symbols.push_back(GetSymbol(searchMarkType, true /* hasLocalAds */)); + } + for (int pricing = 1; pricing <= 3; pricing++) symbols.push_back(GetBookingBadgeName(pricing)); symbols.push_back(kSaleBadgeName); @@ -304,25 +506,18 @@ double SearchMarks::GetMaxDimension(ScreenBase const & modelView) const double dimension = 0.0; for (size_t i = 0; i < static_cast(SearchMarkType::Count); ++i) { - m2::PointD const markSize = GetSize(static_cast(i), modelView); + auto const searchMarkType = SMT(i); + m2::PointD markSize = ::GetSize(searchMarkType, false /* hasLocalAds */, modelView); dimension = std::max(dimension, std::max(markSize.x, markSize.y)); + if (HasLocalAdsVariant(searchMarkType)) + { + markSize = ::GetSize(searchMarkType, true /* hasLocalAds */, modelView); + dimension = std::max(dimension, std::max(markSize.x, markSize.y)); + } } return dimension; } -// static -m2::PointD SearchMarks::GetSize(SearchMarkType searchMarkType, ScreenBase const & modelView) -{ - if (m_searchMarksSizes.empty()) - return {}; - - auto const index = static_cast(searchMarkType); - ASSERT_LESS(index, kSymbols.size(), ()); - auto const pixelSize = GetSize(kSymbols[index]).get_value_or({}); - double const pixelToMercator = modelView.GetScale(); - return {pixelToMercator * pixelSize.x, pixelToMercator * pixelSize.y}; -} - // static boost::optional SearchMarks::GetSize(std::string const & symbolName) { diff --git a/map/search_mark.hpp b/map/search_mark.hpp index 06b2ad0a0f..5ff40af62d 100644 --- a/map/search_mark.hpp +++ b/map/search_mark.hpp @@ -11,28 +11,12 @@ #include +#include #include #include #include #include -enum class SearchMarkType -{ - Default = 0, - Booking, - LocalAds, - LocalAdsBooking, - UGC, - Cafe, - Bakery, - Bar, - Pub, - Restaurant, - FastFood, - NotFound, // Service value used in developer tools. - Count -}; - class BookmarkManager; class SearchMarkPoint : public UserMark @@ -55,7 +39,11 @@ public: std::string const & GetMatchedName() const { return m_matchedName; } void SetMatchedName(std::string const & name); - void SetMarkType(SearchMarkType type); + void SetFromType(uint32_t type, bool hasLocalAds); + void SetBookingType(bool hasLocalAds); + void SetUGCType(); + void SetNotFoundType(); + void SetPreparing(bool isPreparing); void SetRating(float rating); void SetPricing(int pricing); @@ -75,7 +63,8 @@ protected: bool IsUGCMark() const; bool IsMarkWithRating() const; - SearchMarkType m_type = SearchMarkType::Default; + uint8_t m_type = 0; + bool m_hasLocalAds = false; FeatureID m_featureID; // Used to pass exact search result matched string into a place page. std::string m_matchedName; @@ -102,7 +91,7 @@ public: // NOTE: Vector of features must be sorted. void SetSales(std::vector const & features, bool hasSale); - static m2::PointD GetSize(SearchMarkType searchMarkType, ScreenBase const & modelView); + static bool HaveSizes() { return !m_searchMarksSizes.empty(); }; static boost::optional GetSize(std::string const & symbolName); private: diff --git a/search/search_quality/assessment_tool/sample_view.cpp b/search/search_quality/assessment_tool/sample_view.cpp index a7dba75347..0a8418e1ef 100644 --- a/search/search_quality/assessment_tool/sample_view.cpp +++ b/search/search_quality/assessment_tool/sample_view.cpp @@ -280,7 +280,7 @@ void SampleView::ShowNonFoundResultsMarks(std::vector co continue; auto * mark = editSession.CreateUserMark(result.m_pos); - mark->SetMarkType(SearchMarkType::NotFound); + mark->SetNotFoundType(); } }