From 6739a1a74d3e681bf5eca851b959b8e35e24cd29 Mon Sep 17 00:00:00 2001 From: Arsentiy Milchakov Date: Fri, 17 Jul 2020 16:39:49 +0300 Subject: [PATCH] [search_marks] dummies for booking improvements --- map/booking_utils.cpp | 63 +++++++++++++++++-------------- map/booking_utils.hpp | 1 + map/framework.cpp | 29 ++++++++++---- map/place_page_info.hpp | 7 ++++ map/search_mark.cpp | 83 +++++++++++++++++++++++++++++++++++------ map/search_mark.hpp | 23 +++++++++--- 6 files changed, 155 insertions(+), 51 deletions(-) diff --git a/map/booking_utils.cpp b/map/booking_utils.cpp index e39285ccfd..a135b06053 100644 --- a/map/booking_utils.cpp +++ b/map/booking_utils.cpp @@ -16,27 +16,30 @@ namespace booking { namespace { -void Sort(search::Results && results, std::vector && extras, - std::vector & sortedFeatures, std::vector & sortedExtras) +void SortTransform(search::Results && results, std::vector && extras, + std::vector & sortedFeatures, std::vector & sortedPrices) { if (!extras.empty()) { CHECK_EQUAL(results.GetCount(), extras.size(), ()); - std::vector> featuresWithExtras; - featuresWithExtras.reserve(results.GetCount()); + std::vector> featuresWithPrices; + featuresWithPrices.reserve(results.GetCount()); for (size_t i = 0; i < results.GetCount(); ++i) - featuresWithExtras.emplace_back(std::move(results[i].GetFeatureID()), std::move(extras[i])); + { + auto pricesFormatted = FormatPrice(extras[i].m_price, extras[i].m_currency); + featuresWithPrices.emplace_back(std::move(results[i].GetFeatureID()), std::move(pricesFormatted)); + } - std::sort(featuresWithExtras.begin(), featuresWithExtras.end(), - base::LessBy(&std::pair::first)); + std::sort(featuresWithPrices.begin(), featuresWithPrices.end(), + base::LessBy(&std::pair::first)); - sortedFeatures.reserve(featuresWithExtras.size()); - sortedExtras.reserve(featuresWithExtras.size()); - for (auto & item : featuresWithExtras) + sortedFeatures.reserve(featuresWithPrices.size()); + sortedPrices.reserve(featuresWithPrices.size()); + for (auto & item : featuresWithPrices) { sortedFeatures.emplace_back(std::move(item.first)); - sortedExtras.emplace_back(std::move(item.second)); + sortedPrices.emplace_back(std::move(item.second)); } } else @@ -74,16 +77,18 @@ filter::TasksInternal MakeInternalTasks(filter::Tasks const & filterTasks, if (results.GetCount() == 0) return; + if (!inViewport) + extras.clear(); + std::vector sortedFeatures; - std::vector sortedExtras; - Sort(std::move(results), std::move(extras), sortedFeatures, sortedExtras); + std::vector sortedPrices; + + SortTransform(std::move(results), std::move(extras), sortedFeatures, sortedPrices); if (inViewport) { - // TODO(a): add price formatting for array. - // auto const pricesFormatted = FormatPrices(sortedExtras); - - GetPlatform().RunTask(Platform::Thread::Gui, [&searchMarks, type, sortedFeatures]() + GetPlatform().RunTask(Platform::Thread::Gui, [&searchMarks, type, sortedFeatures, + sortedPrices = std::move(sortedPrices)]() mutable { switch (type) { @@ -92,13 +97,10 @@ filter::TasksInternal MakeInternalTasks(filter::Tasks const & filterTasks, break; case Type::Availability: searchMarks.SetPreparingState(sortedFeatures, false /* isPreparing */); + searchMarks.SetPrices(sortedFeatures, std::move(sortedPrices)); break; } }); - - // TODO(a): to add SetPrices method into search marks. - // if (!pricesFormatted.empty()) - // m_searchMarks.SetPrices(sortedFeatures, pricesFormatted) } cb(apiParams, sortedFeatures); } @@ -134,10 +136,13 @@ filter::TasksRawInternal MakeInternalTasks(filter::Tasks const & filterTasks, if (sortedFeatures.empty()) return; - // TODO(a): add price formatting for array. - // auto const pricesFormatted = FormatPrices(extras); + std::vector sortedPrices; + sortedPrices.reserve(extras.size()); + for (size_t i = 0; i < extras.size(); ++i) + sortedPrices.emplace_back(FormatPrice(extras[i].m_price, extras[i].m_currency)); - GetPlatform().RunTask(Platform::Thread::Gui, [&searchMarks, type, sortedFeatures]() + GetPlatform().RunTask(Platform::Thread::Gui, [&searchMarks, type, sortedFeatures, + sortedPrices = std::move(sortedPrices)]() mutable { switch (type) { @@ -146,11 +151,9 @@ filter::TasksRawInternal MakeInternalTasks(filter::Tasks const & filterTasks, break; case Type::Availability: searchMarks.SetPreparingState(sortedFeatures, false /* isPreparing */); + searchMarks.SetPrices(sortedFeatures, std::move(sortedPrices)); break; } - // TODO(a): to add SetPrices method into search marks. - // if (!pricesFormatted.empty()) - // m_searchMarks.SetPrices(sortedFeatures, pricesFormatted) }); cb(apiParams, sortedFeatures); } @@ -161,4 +164,10 @@ filter::TasksRawInternal MakeInternalTasks(filter::Tasks const & filterTasks, return tasksInternal; } + +std::string FormatPrice(double price, std::string const & currency) +{ + // TODO(a): add price formatting. + return std::to_string(static_cast(price)) + " " + currency; +} } // namespace booking diff --git a/map/booking_utils.hpp b/map/booking_utils.hpp index d07bc0e311..46af8d133a 100644 --- a/map/booking_utils.hpp +++ b/map/booking_utils.hpp @@ -10,4 +10,5 @@ filter::TasksInternal MakeInternalTasks(filter::Tasks const & filterTasks, SearchMarks & searchMarks, bool inViewport); filter::TasksRawInternal MakeInternalTasks(filter::Tasks const & filterTasks, SearchMarks & searchMarks); +std::string FormatPrice(double price, std::string const & currency); } // namespace booking diff --git a/map/framework.cpp b/map/framework.cpp index 6863b2f389..f5a6ef58ff 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -1052,6 +1052,8 @@ void Framework::FillApiMarkInfo(ApiMarkPoint const & api, place_page::Info & inf void Framework::FillSearchResultInfo(SearchMarkPoint const & smp, place_page::Info & info) const { + info.SetIsSearchMark(true); + if (smp.GetFeatureID().IsValid()) FillFeatureInfo(smp.GetFeatureID(), info); else @@ -2423,6 +2425,13 @@ void Framework::ActivateMapSelection(std::optional const & inf else GetBookmarkManager().OnTrackDeselected(); + // TODO(a): to replace dummies with correct values. + if (m_currentPlacePageInfo->GetSponsoredType() == place_page::SponsoredType::Booking && + info->IsSearchMark()) + { + m_searchMarks.OnSelected(m_currentPlacePageInfo->GetID(), false /* "Dummy" */, "Dummy reason"); + } + CHECK_NOT_EQUAL(info->GetSelectedObject(), df::SelectionShape::OBJECT_EMPTY, ("Empty selections are impossible.")); if (m_drapeEngine != nullptr) { @@ -2447,11 +2456,18 @@ void Framework::DeactivateMapSelection(bool notifyUI) if (notifyUI && m_onPlacePageClose) m_onPlacePageClose(!somethingWasAlreadySelected); - m_currentPlacePageInfo = {}; - if (somethingWasAlreadySelected) { + if (m_currentPlacePageInfo->GetSponsoredType() == place_page::SponsoredType::Booking && + m_currentPlacePageInfo->IsSearchMark()) + { + m_searchMarks.OnDeselected(m_currentPlacePageInfo->GetID()); + } + GetBookmarkManager().OnTrackDeselected(); + + m_currentPlacePageInfo = {}; + if (m_drapeEngine != nullptr) m_drapeEngine->DeselectObject(); } @@ -3907,11 +3923,10 @@ void Framework::ShowViewportSearchResults(search::Results::ConstIter begin, if (found && !filterResult.m_extras.empty()) { - // auto const index = std::distance(features.cbegin(), it); - // TODO(a): to implement FormatPrice and SetPrice methods. - // auto const price = FormatPrice(filterResult.m_extras[index].m_price, - // filterResult.m_extras[index].m_currency); - // mark.SetPrice(price); + auto const index = std::distance(features.cbegin(), it); + auto price = booking::FormatPrice(filterResult.m_extras[index].m_price, + filterResult.m_extras[index].m_currency); + mark.SetPrice(std::move(price)); } } }; diff --git a/map/place_page_info.hpp b/map/place_page_info.hpp index 40b856a86e..411b4e6158 100644 --- a/map/place_page_info.hpp +++ b/map/place_page_info.hpp @@ -146,6 +146,7 @@ public: /// Place traits bool IsFeature() const { return m_featureID.IsValid(); } bool IsBookmark() const { return m_markGroupId != kml::kInvalidMarkGroupId && m_markId != kml::kInvalidMarkId; } + bool IsSearchMark() const { return m_isSearchMark; } bool IsTrack() const { return m_trackId != kml::kInvalidTrackId; } bool IsMyPosition() const { return m_selectedObject == df::SelectionShape::ESelectedObject::OBJECT_MY_POSITION; } bool IsRoutePoint() const { return m_isRoutePoint; } @@ -210,6 +211,9 @@ public: void SetTrackId(kml::TrackId trackId) { m_trackId = trackId; }; kml::TrackId GetTrackId() const { return m_trackId; }; + /// SearchMark + void SetIsSearchMark(bool isSearchMark) { m_isSearchMark = isSearchMark; }; + /// Guide void SetIsGuide(bool isGuide) { m_isGuide = isGuide; } @@ -359,6 +363,9 @@ private: /// If not invalid, track is bound to this place page. kml::TrackId m_trackId = kml::kInvalidTrackId; + /// SearchMark + kml::MarkId m_isSearchMark = false; + /// Guide bool m_isGuide = false; diff --git a/map/search_mark.cpp b/map/search_mark.cpp index e2e03e5585..730df9392b 100644 --- a/map/search_mark.cpp +++ b/map/search_mark.cpp @@ -492,9 +492,11 @@ void SearchMarkPoint::SetPricing(int pricing) SetAttributeValue(m_pricing, pricing); } -void SearchMarkPoint::SetPrice(std::string const & price) +void SearchMarkPoint::SetPrice(std::string && price) { - SetAttributeValue(m_price, price); + // Dummy. + // TODO: uncomment when drape will be ready. + // SetAttributeValue(m_price, std::move(price)); } void SearchMarkPoint::SetSale(bool hasSale) @@ -502,6 +504,21 @@ void SearchMarkPoint::SetSale(bool hasSale) SetAttributeValue(m_hasSale, hasSale); } +void SearchMarkPoint::SetUsed(bool isUsed) +{ + SetAttributeValue(m_isUsed, isUsed); +} + +void SearchMarkPoint::SetAvailable(bool isAvailable) +{ + SetAttributeValue(m_isAvailable, isAvailable); +} + +void SearchMarkPoint::SetReason(std::string && reason) +{ + SetAttributeValue(m_reason, std::move(reason)); +} + bool SearchMarkPoint::IsBookingSpecialMark() const { return (SMT(m_type) == SearchMarkType::Booking) && !m_isPreparing; @@ -612,33 +629,75 @@ std::optional SearchMarks::GetSize(std::string const & symbolName) void SearchMarks::SetPreparingState(std::vector const & features, bool isPreparing) { - FilterAndProcessMarks(features, [isPreparing](SearchMarkPoint * mark) + ProcessMarks([&features, isPreparing](SearchMarkPoint * mark) { - mark->SetPreparing(isPreparing); + ASSERT(std::is_sorted(features.begin(), features.end()), ()); + if (std::binary_search(features.cbegin(), features.cend(), mark->GetFeatureID())) + mark->SetPreparing(isPreparing); }); } void SearchMarks::SetSales(std::vector const & features, bool hasSale) { - FilterAndProcessMarks(features, [hasSale](SearchMarkPoint * mark) + ProcessMarks([&features, hasSale](SearchMarkPoint * mark) { - mark->SetSale(hasSale); + ASSERT(std::is_sorted(features.begin(), features.end()), ()); + if (std::binary_search(features.cbegin(), features.cend(), mark->GetFeatureID())) + mark->SetSale(hasSale); }); } -void SearchMarks::FilterAndProcessMarks(std::vector const & features, - std::function && processor) +void SearchMarks::SetPrices(std::vector const & features, std::vector && prices) +{ + ProcessMarks([&features, &prices](SearchMarkPoint * mark) + { + ASSERT(std::is_sorted(features.begin(), features.end()), ()); + auto const it = std::lower_bound(features.cbegin(), features.cend(), mark->GetFeatureID()); + + if (it == features.cend()) + return; + + auto const index = std::distance(features.cbegin(), it); + + ASSERT_LESS(index, prices.size(), ()); + mark->SetPrice(std::move(prices[index])); + }); +} + +void SearchMarks::OnSelected(FeatureID const &featureId, bool isAvailable, std::string && reason) +{ + ProcessMarks([&featureId, isAvailable, &reason](SearchMarkPoint * mark) + { + if (featureId != mark->GetFeatureID()) + return; + + mark->SetUsed(true); + mark->SetAvailable(isAvailable); + mark->SetReason(std::move(reason)); + }); +} + +void SearchMarks::OnDeselected(FeatureID const & featureId) +{ + ProcessMarks([&featureId](SearchMarkPoint * mark) + { + if (featureId != mark->GetFeatureID()) + return; + + mark->SetAvailable(true); + mark->SetReason({}); + }); +} + +void SearchMarks::ProcessMarks(std::function && processor) { if (m_bmManager == nullptr || processor == nullptr) return; - ASSERT(std::is_sorted(features.begin(), features.end()), ()); - auto editSession = m_bmManager->GetEditSession(); for (auto markId : m_bmManager->GetUserMarkIds(UserMark::Type::SEARCH)) { auto * mark = editSession.GetMarkForEdit(markId); - if (std::binary_search(features.begin(), features.end(), mark->GetFeatureID())) - processor(mark); + processor(mark); } } diff --git a/map/search_mark.hpp b/map/search_mark.hpp index 97b186ab5e..3e6c6497c9 100644 --- a/map/search_mark.hpp +++ b/map/search_mark.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include class BookmarkManager; @@ -46,17 +47,21 @@ public: void SetPreparing(bool isPreparing); void SetRating(float rating); void SetPricing(int pricing); - void SetPrice(std::string const & price); + void SetPrice(std::string && price); void SetSale(bool hasSale); + void SetUsed(bool isUsed); + void SetAvailable(bool isAvailable); + void SetReason(std::string && reason); protected: - template void SetAttributeValue(T & dst, T const & src) + template + void SetAttributeValue(T & dst, U && src) { if (dst == src) return; SetDirty(); - dst = src; + dst = std::forward(src); } bool IsBookingSpecialMark() const; @@ -76,6 +81,9 @@ protected: bool m_hasSale = false; dp::TitleDecl m_titleDecl; dp::TitleDecl m_ugcTitleDecl; + bool m_isUsed = false; + bool m_isAvailable = true; + std::string m_reason; }; class SearchMarks @@ -94,12 +102,17 @@ public: // NOTE: Vector of features must be sorted. void SetSales(std::vector const & features, bool hasSale); + // NOTE: Vector of features must be sorted. + void SetPrices(std::vector const & features, std::vector && prices); + + void OnSelected(FeatureID const & featureId, bool isAvailable, std::string && reason); + void OnDeselected(FeatureID const & featureId); + static bool HaveSizes() { return !m_searchMarksSizes.empty(); }; static std::optional GetSize(std::string const & symbolName); private: - void FilterAndProcessMarks(std::vector const & features, - std::function && processor); + void ProcessMarks(std::function && processor); BookmarkManager * m_bmManager; df::DrapeEngineSafePtr m_drapeEngine;