diff --git a/map/framework.cpp b/map/framework.cpp index 19c6196471..29e0df178d 100644 --- a/map/framework.cpp +++ b/map/framework.cpp @@ -363,7 +363,6 @@ Framework::Framework(FrameworkParams const & params) bind(&Framework::GetMwmIdByName, this, _1), bind(&Framework::ReadFeatures, this, _1, _2), bind(&Framework::GetFeatureByID, this, _1, _2)) - , m_startForegroundTime(0.0) , m_storage(platform::migrate::NeedMigrate() ? COUNTRIES_OBSOLETE_FILE : COUNTRIES_FILE) , m_enabledDiffs(params.m_enableDiffs) , m_isRenderingEnabled(true) @@ -392,8 +391,6 @@ Framework::Framework(FrameworkParams const & params) , m_subscription(std::make_unique()) , m_tipsApi(static_cast(*this)) { - m_startBackgroundTime = my::Timer::LocalTime(); - // Editor should be initialized from the main thread to set its ThreadChecker. // However, search calls editor upon initialization thus setting the lazy editor's ThreadChecker // to a wrong thread. So editor should be initialiazed before serach. @@ -1353,7 +1350,7 @@ void Framework::EnterBackground() void Framework::EnterForeground() { m_startForegroundTime = my::Timer::LocalTime(); - if (m_drapeEngine != nullptr) + if (m_drapeEngine != nullptr && m_startBackgroundTime != 0.0) { auto const timeInBackground = m_startForegroundTime - m_startBackgroundTime; m_drapeEngine->SetTimeInBackground(timeInBackground); @@ -3680,3 +3677,8 @@ bool Framework::HaveTransit(m2::PointD const & pt) const return handle.GetValue()->m_cont.IsExist(TRANSIT_FILE_TAG); } + +double Framework::GetLastBackgroundTime() const +{ + return m_startBackgroundTime; +} diff --git a/map/framework.hpp b/map/framework.hpp index a55b64defe..f962b5a8e9 100644 --- a/map/framework.hpp +++ b/map/framework.hpp @@ -193,8 +193,8 @@ protected: drape_ptr m_drapeEngine; - double m_startForegroundTime; - double m_startBackgroundTime; + double m_startForegroundTime = 0.0; + double m_startBackgroundTime = 0.0; StorageDownloadingPolicy m_storageDownloadingPolicy; storage::Storage m_storage; @@ -890,4 +890,5 @@ public: // TipsApi::Delegate override. bool HaveTransit(m2::PointD const & pt) const override; + double GetLastBackgroundTime() const override; }; diff --git a/map/map_tests/tips_tests.cpp b/map/map_tests/tips_tests.cpp index 2bd615b31a..35ca5f9d5b 100644 --- a/map/map_tests/tips_tests.cpp +++ b/map/map_tests/tips_tests.cpp @@ -5,6 +5,9 @@ #include "metrics/metrics_tests_support/eye_for_testing.hpp" #include "metrics/eye.hpp" +#include "metrics/eye_info.hpp" + +#include "base/timer.hpp" #include #include @@ -15,6 +18,30 @@ using namespace eye; namespace { +class TipsApiDelegate : public TipsApi::Delegate +{ +public: + void SetLastBackgroundTime(double lastBackgroundTime) + { + m_lastBackgroundTime = lastBackgroundTime; + } + + // TipsApi::Delegate overrides: + boost::optional GetCurrentPosition() const override + { + return boost::optional(); + } + + bool IsCountryLoaded(m2::PointD const & pt) const override { return false; } + + bool HaveTransit(m2::PointD const & pt) const override { return false; } + + double GetLastBackgroundTime() const override { return m_lastBackgroundTime; } + +private: + double m_lastBackgroundTime = 0.0; +}; + void MakeLastShownTipAvailableByTime() { auto const info = Eye::Instance().GetInfo(); @@ -26,26 +53,27 @@ void MakeLastShownTipAvailableByTime() } boost::optional GetTipForTesting(TipsApi::Duration showAnyTipPeriod, - TipsApi::Duration showSameTipPeriod) + TipsApi::Duration showSameTipPeriod, + TipsApiDelegate const & delegate) { // Do not use additional conditions for testing. TipsApi::Conditions conditions = {{ // Condition for Tips::Type::BookmarksCatalog type. - [] { return true; }, + [] (eye::Info const & info) { return true; }, // Condition for Tips::Type::BookingHotels type. - [] { return true; }, + [] (eye::Info const & info) { return true; }, // Condition for Tips::Type::DiscoverButton type. - [] { return true; }, + [] (eye::Info const & info) { return true; }, // Condition for Tips::Type::MapsLayers type. - [] { return true; } + [] (eye::Info const & info) { return true; } }}; - return TipsApi::GetTipForTesting(showAnyTipPeriod, showSameTipPeriod, conditions); + return TipsApi::GetTipForTesting(showAnyTipPeriod, showSameTipPeriod, delegate, conditions); } boost::optional GetTipForTesting() { - return GetTipForTesting(TipsApi::GetShowAnyTipPeriod(), TipsApi::GetShowSameTipPeriod()); + return GetTipForTesting(TipsApi::GetShowAnyTipPeriod(), TipsApi::GetShowSameTipPeriod(), {}); } void ShowTipWithClickCountTest(Tip::Event eventType, size_t maxClickCount) @@ -114,7 +142,7 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, ShowFirstTip_Test) for (size_t i = 0; i < totalTipsCount; ++i) { - auto tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod()); + auto tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod(), {}); TEST(tip.is_initialized(), ()); TEST_NOT_EQUAL(tip.get(), Tip::Type::Count, ()); @@ -145,4 +173,15 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, ShowTipAndGotitClicked_Test) { ShowTipWithClickCountTest(Tip::Event::GotitClicked, TipsApi::GetGotitClicksCountToDisable()); } + +UNIT_CLASS_TEST(ScopedEyeForTesting, ShowTipAfterWarmStart) +{ + TipsApiDelegate d; + d.SetLastBackgroundTime(my::Timer::LocalTime()); + auto tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod(), d); + TEST(!tip.is_initialized(), ()); + d.SetLastBackgroundTime(my::Timer::LocalTime() - TipsApi::ShowTipAfterCollapsingPeriod().count()); + tip = GetTipForTesting({}, TipsApi::GetShowSameTipPeriod(), d); + TEST(tip.is_initialized(), ()); +} } // namespace diff --git a/map/tips_api.cpp b/map/tips_api.cpp index 09ce43cf20..5f04b9db30 100644 --- a/map/tips_api.cpp +++ b/map/tips_api.cpp @@ -4,6 +4,9 @@ #include "platform/platform.hpp" +#include "base/timer.hpp" + +#include #include using namespace eye; @@ -14,21 +17,35 @@ namespace auto constexpr kShowAnyTipPeriod = std::chrono::hours(24) * 3; // The app shouldn't show the same screen more frequently than 1 month. auto constexpr kShowSameTipPeriod = std::chrono::hours(24) * 30; +// Every current trigger for a tips screen can be activated at the start of the application by +// default and if the app was inactive more then 12 hours. +auto constexpr kShowTipAfterCollapsingPeriod = std::chrono::seconds(12 * 60 * 60); // If a user clicks on the action areas (highlighted or blue button) // the appropriate screen will never be shown again. size_t constexpr kActionClicksCountToDisable = 1; // If a user clicks 3 times on the button GOT IT the appropriate screen will never be shown again. size_t constexpr kGotitClicksCountToDisable = 3; -size_t ToIndex(Tip::Type type) +template ::value> * = nullptr> +size_t ToIndex(T type) { return static_cast(type); } boost::optional GetTipImpl(TipsApi::Duration showAnyTipPeriod, TipsApi::Duration showSameTipPeriod, - TipsApi::Conditions const & triggers) + TipsApi::Delegate const & delegate, + TipsApi::Conditions const & conditions) { + auto const lastBackgroundTime = delegate.GetLastBackgroundTime(); + if (lastBackgroundTime != 0.0) + { + auto const timeInBackground = + static_cast(my::Timer::LocalTime() - lastBackgroundTime); + if (timeInBackground < kShowTipAfterCollapsingPeriod.count()) + return {}; + } + auto const info = Eye::Instance().GetInfo(); auto const & tips = info->m_tips; auto constexpr totalTipsCount = static_cast(Tip::Type::Count); @@ -60,7 +77,7 @@ boost::optional GetTipImpl(TipsApi::Duration showAnyTipPeriod, for (auto const & c : candidates) { - if (c.second && triggers[ToIndex(c.first)]()) + if (c.second && conditions[ToIndex(c.first)](*info)) return c.first; } } @@ -70,7 +87,7 @@ boost::optional GetTipImpl(TipsApi::Duration showAnyTipPeriod, if (shownTip.m_eventCounters.Get(Tip::Event::ActionClicked) < kActionClicksCountToDisable && shownTip.m_eventCounters.Get(Tip::Event::GotitClicked) < kGotitClicksCountToDisable && Clock::now() - shownTip.m_lastShownTime > showSameTipPeriod && - triggers[ToIndex(shownTip.m_type)]()) + conditions[ToIndex(shownTip.m_type)](*info)) { return shownTip.m_type; } @@ -92,6 +109,12 @@ TipsApi::Duration TipsApi::GetShowSameTipPeriod() return kShowSameTipPeriod; } +// static +TipsApi::Duration TipsApi::ShowTipAfterCollapsingPeriod() +{ + return kShowTipAfterCollapsingPeriod; +}; + // static size_t TipsApi::GetActionClicksCountToDisable() { @@ -110,12 +133,26 @@ TipsApi::TipsApi(Delegate const & delegate) m_conditions = {{ // Condition for Tips::Type::BookmarksCatalog type. - [] { return GetPlatform().ConnectionStatus() != Platform::EConnectionType::CONNECTION_NONE; }, - // Condition for Tips::Type::BookingHotels type. - [] { return true; }, - // Condition for Tips::Type::DiscoverButton type. - [this] + [] (eye::Info const & info) { + return info.m_bookmarks.m_lastOpenedTime.time_since_epoch().count() == 0 && + GetPlatform().ConnectionStatus() != Platform::EConnectionType::CONNECTION_NONE; + }, + // Condition for Tips::Type::BookingHotels type. + [] (eye::Info const & info) + { + return info.m_booking.m_lastFilterUsedTime.time_since_epoch().count() == 0; + }, + // Condition for Tips::Type::DiscoverButton type. + [this] (eye::Info const & info) + { + auto const eventsCount = ToIndex(Discovery::Event::Count); + for (size_t i = 0; i < eventsCount; ++i) + { + if (info.m_discovery.m_eventCounters.Get(static_cast(i)) != 0) + return false; + } + auto const pos = m_delegate.GetCurrentPosition(); if (!pos.is_initialized()) return false; @@ -123,8 +160,17 @@ TipsApi::TipsApi(Delegate const & delegate) return m_delegate.IsCountryLoaded(pos.get()); }, // Condition for Tips::Type::MapsLayers type. - [this] + [this] (eye::Info const & info) { + for (auto const & layer : info.m_layers) + { + if (layer.m_type == Layer::PublicTransport && + layer.m_lastTimeUsed.time_since_epoch().count() != 0) + { + return false; + } + } + auto const pos = m_delegate.GetCurrentPosition(); if (!pos.is_initialized()) return false; @@ -136,13 +182,14 @@ TipsApi::TipsApi(Delegate const & delegate) boost::optional TipsApi::GetTip() const { - return GetTipImpl(GetShowAnyTipPeriod(), GetShowSameTipPeriod(), m_conditions); + return GetTipImpl(GetShowAnyTipPeriod(), GetShowSameTipPeriod(), m_delegate, m_conditions); } // static boost::optional TipsApi::GetTipForTesting(Duration showAnyTipPeriod, Duration showSameTipPeriod, + TipsApi::Delegate const & delegate, Conditions const & triggers) { - return GetTipImpl(showAnyTipPeriod, showSameTipPeriod, triggers); + return GetTipImpl(showAnyTipPeriod, showSameTipPeriod, delegate, triggers); } diff --git a/map/tips_api.hpp b/map/tips_api.hpp index 0eaec73eea..d7669659c6 100644 --- a/map/tips_api.hpp +++ b/map/tips_api.hpp @@ -16,7 +16,7 @@ class TipsApi { public: using Duration = std::chrono::duration; - using Condition = std::function; + using Condition = std::function; using Conditions = std::array(eye::Tip::Type::Count)>; class Delegate @@ -27,10 +27,12 @@ public: virtual boost::optional GetCurrentPosition() const = 0; virtual bool IsCountryLoaded(m2::PointD const & pt) const = 0; virtual bool HaveTransit(m2::PointD const & pt) const = 0; + virtual double GetLastBackgroundTime() const = 0; }; static Duration GetShowAnyTipPeriod(); static Duration GetShowSameTipPeriod(); + static Duration ShowTipAfterCollapsingPeriod(); static size_t GetActionClicksCountToDisable(); static size_t GetGotitClicksCountToDisable(); @@ -40,6 +42,7 @@ public: static boost::optional GetTipForTesting(Duration showAnyTipPeriod, Duration showSameTipPeriod, + TipsApi::Delegate const & delegate, Conditions const & triggers); private: diff --git a/metrics/eye.cpp b/metrics/eye.cpp index 939a95c311..b32aecb82a 100644 --- a/metrics/eye.cpp +++ b/metrics/eye.cpp @@ -100,6 +100,76 @@ void Eye::AppendTip(Tip::Type type, Tip::Event event) Save(editableInfo); } +void Eye::UpdateBookingFilterUsedTime() +{ + auto const info = m_info.Get(); + auto editableInfo = std::make_shared(*info); + + editableInfo->m_booking.m_lastFilterUsedTime = Clock::now(); + + Save(editableInfo); +} + +void Eye::UpdateBoomarksCatalogShownTime() +{ + auto const info = m_info.Get(); + auto editableInfo = std::make_shared(*info); + + editableInfo->m_bookmarks.m_lastOpenedTime = Clock::now(); + + Save(editableInfo); +} + +void Eye::UpdateDiscoveryShownTime() +{ + auto const info = m_info.Get(); + auto editableInfo = std::make_shared(*info); + + editableInfo->m_discovery.m_lastOpenedTime = Clock::now(); + + Save(editableInfo); +} + +void Eye::IncrementDiscoveryItem(Discovery::Event event) +{ + auto const info = m_info.Get(); + auto editableInfo = std::make_shared(*info); + + editableInfo->m_discovery.m_lastClickedTime = Clock::now(); + editableInfo->m_discovery.m_eventCounters.Increment(event); + + Save(editableInfo); +} + +void Eye::AppendLayer(Layer::Type type) +{ + auto const info = m_info.Get(); + auto editableInfo = std::make_shared(*info); + auto & editableLayers = editableInfo->m_layers; + + auto it = std::find_if(editableLayers.begin(), editableLayers.end(), [type](Layer const & layer) + { + return layer.m_type == type; + }); + + if (it != editableLayers.end()) + { + ++it->m_useCount; + it->m_lastTimeUsed = Clock::now(); + } + else + { + Layer layer; + layer.m_type = type; + + ++layer.m_useCount; + layer.m_lastTimeUsed = Clock::now(); + editableLayers.emplace_back(std::move(layer)); + } + + Save(editableInfo); +} + // Eye::Event methods ------------------------------------------------------------------------------ // static void Eye::Event::TipShown(Tip::Type type, Tip::Event event) @@ -109,4 +179,49 @@ void Eye::Event::TipShown(Tip::Type type, Tip::Event event) Instance().AppendTip(type, event); }); } + +// static +void Eye::Event::BookingFilterUsed() +{ + GetPlatform().RunTask(Platform::Thread::File, [] + { + Instance().UpdateBookingFilterUsedTime(); + }); +} + +// static +void Eye::Event::BoomarksCatalogShown() +{ + GetPlatform().RunTask(Platform::Thread::File, [] + { + Instance().UpdateBoomarksCatalogShownTime(); + }); +} + +// static +void Eye::Event::DiscoveryShown() +{ + GetPlatform().RunTask(Platform::Thread::File, [] + { + Instance().UpdateDiscoveryShownTime(); + }); +} + +// static +void Eye::Event::DiscoveryItemClicked(Discovery::Event event) +{ + GetPlatform().RunTask(Platform::Thread::File, [event] + { + Instance().IncrementDiscoveryItem(event); + }); +} + +// static +void Eye::Event::LayerUsed(Layer::Type type) +{ + GetPlatform().RunTask(Platform::Thread::File, [type] + { + Instance().AppendLayer(type); + }); +} } // namespace eye diff --git a/metrics/eye.hpp b/metrics/eye.hpp index 06d0b2b5a8..2268cf616d 100644 --- a/metrics/eye.hpp +++ b/metrics/eye.hpp @@ -21,6 +21,11 @@ public: { public: static void TipShown(Tip::Type type, Tip::Event event); + static void BookingFilterUsed(); + static void BoomarksCatalogShown(); + static void DiscoveryShown(); + static void DiscoveryItemClicked(Discovery::Event event); + static void LayerUsed(Layer::Type type); }; static Eye & Instance(); @@ -34,6 +39,11 @@ private: // Event processing: void AppendTip(Tip::Type type, Tip::Event event); + void UpdateBookingFilterUsedTime(); + void UpdateBoomarksCatalogShownTime(); + void UpdateDiscoveryShownTime(); + void IncrementDiscoveryItem(Discovery::Event event); + void AppendLayer(Layer::Type type); base::AtomicSharedPtr m_info; diff --git a/metrics/eye_info.hpp b/metrics/eye_info.hpp index eb51753778..66e67592e4 100644 --- a/metrics/eye_info.hpp +++ b/metrics/eye_info.hpp @@ -7,9 +7,10 @@ #include "base/visitor.hpp" #include +#include #include #include -#include +#include #include namespace eye @@ -67,6 +68,64 @@ enum class Version : int8_t using Clock = std::chrono::system_clock; using Time = Clock::time_point; +struct Booking +{ + DECLARE_VISITOR(visitor(m_lastFilterUsedTime, "last_filter_used_time")) + + Time m_lastFilterUsedTime; +}; + +struct Bookmarks +{ + DECLARE_VISITOR(visitor(m_lastOpenedTime, "last_use_time")) + + Time m_lastOpenedTime; +}; + +struct Discovery +{ + enum class Event + { + HotelsClicked, + AttractionsClicked, + CafesClicked, + LocalsClicked, + + MoreHotelsClicked, + MoreAttractionsClicked, + MoreCafesClicked, + MoreLocalsClicked, + + Count + }; + + DECLARE_VISITOR(visitor(m_eventCounters, "event_counters"), + visitor(m_lastOpenedTime, "last_opened_time"), + visitor(m_lastClickedTime, "last_clicked_time")) + + Counters m_eventCounters; + Time m_lastOpenedTime; + Time m_lastClickedTime; +}; + +struct Layer +{ + enum Type + { + TrafficJams, + PublicTransport + }; + + DECLARE_VISITOR(visitor(m_type, "type"), visitor(m_useCount, "use_count"), + visitor(m_lastTimeUsed, "last_time_used")) + + Type m_type; + uint64_t m_useCount = 0; + Time m_lastTimeUsed; +}; + +using Layers = std::vector; + struct Tip { // The order is important. @@ -102,8 +161,14 @@ using Tips = std::vector; struct InfoV0 { static Version GetVersion() { return Version::V0; } - DECLARE_VISITOR(visitor(m_tips, "tips")) + DECLARE_VISITOR(visitor(m_booking, "booking"), visitor(m_bookmarks, "bookmarks"), + visitor(m_discovery, "discovery"), visitor(m_layers, "layers"), + visitor(m_tips, "tips")) + Booking m_booking; + Bookmarks m_bookmarks; + Discovery m_discovery; + Layers m_layers; Tips m_tips; }; diff --git a/metrics/metrics_tests/eye_tests.cpp b/metrics/metrics_tests/eye_tests.cpp index 2c51f8473a..6e01004c41 100644 --- a/metrics/metrics_tests/eye_tests.cpp +++ b/metrics/metrics_tests/eye_tests.cpp @@ -50,6 +50,18 @@ Time GetLastShownTipTime(Tips const & tips) return lastShownTime; } + +Time GetLastShownLayerTime(Layers const & layers) +{ + Time lastUsedTime; + for (auto const & layer : layers) + { + if (lastUsedTime < layer.m_lastTimeUsed) + lastUsedTime = layer.m_lastTimeUsed; + } + + return lastUsedTime; +} } // namespace UNIT_TEST(Eye_SerdesTest) @@ -139,3 +151,175 @@ UNIT_CLASS_TEST(ScopedEyeForTesting, AppendTipTest) TEST_NOT_EQUAL(prevShowTime, lastShownTipTime, ()); } } + +UNIT_CLASS_TEST(ScopedEyeForTesting, UpdateBookingFilterUsedTimeTest) +{ + auto const initialInfo = Eye::Instance().GetInfo(); + auto const & initialBooking = initialInfo->m_booking; + + TEST_EQUAL(initialBooking.m_lastFilterUsedTime, Time(), ()); + + EyeForTesting::UpdateBookingFilterUsedTime(); + + auto const info = Eye::Instance().GetInfo(); + auto const & booking = info->m_booking; + + TEST_NOT_EQUAL(initialBooking.m_lastFilterUsedTime, booking.m_lastFilterUsedTime, ()); +} + +UNIT_CLASS_TEST(ScopedEyeForTesting, UpdateBoomarksCatalogShownTimeTest) +{ + auto const initialInfo = Eye::Instance().GetInfo(); + auto const & initialBookmarks = initialInfo->m_bookmarks; + + TEST_EQUAL(initialBookmarks.m_lastOpenedTime, Time(), ()); + + EyeForTesting::UpdateBoomarksCatalogShownTime(); + + auto const info = Eye::Instance().GetInfo(); + auto const & bookmarks = info->m_bookmarks; + + TEST_NOT_EQUAL(initialBookmarks.m_lastOpenedTime, bookmarks.m_lastOpenedTime, ()); +} + +UNIT_CLASS_TEST(ScopedEyeForTesting, UpdateDiscoveryShownTimeTest) +{ + auto const initialInfo = Eye::Instance().GetInfo(); + auto const & initialDiscovery = initialInfo->m_discovery; + + TEST_EQUAL(initialDiscovery.m_lastOpenedTime, Time(), ()); + + EyeForTesting::UpdateDiscoveryShownTime(); + + auto const info = Eye::Instance().GetInfo(); + auto const & discovery = info->m_discovery; + + TEST_NOT_EQUAL(initialDiscovery.m_lastOpenedTime, discovery.m_lastOpenedTime, ()); +} + +UNIT_CLASS_TEST(ScopedEyeForTesting, IncrementDiscoveryItemTest) +{ + auto const initialInfo = Eye::Instance().GetInfo(); + auto const & initialDiscovery = initialInfo->m_discovery; + + TEST_EQUAL(initialDiscovery.m_lastClickedTime, Time(), ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 0, ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 0, ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 0, ()); + TEST_EQUAL(initialDiscovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 0, ()); + + { + EyeForTesting::IncrementDiscoveryItem(Discovery::Event::CafesClicked); + + auto const info = Eye::Instance().GetInfo(); + auto const & discovery = info->m_discovery; + + TEST_NOT_EQUAL(initialDiscovery.m_lastClickedTime, discovery.m_lastClickedTime, ()); + + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 1, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 0, ()); + } + + { + EyeForTesting::IncrementDiscoveryItem(Discovery::Event::CafesClicked); + + auto const info = Eye::Instance().GetInfo(); + auto const & discovery = info->m_discovery; + + TEST_NOT_EQUAL(initialDiscovery.m_lastClickedTime, discovery.m_lastClickedTime, ()); + + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 2, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 0, ()); + } + + { + EyeForTesting::IncrementDiscoveryItem(Discovery::Event::CafesClicked); + EyeForTesting::IncrementDiscoveryItem(Discovery::Event::HotelsClicked); + EyeForTesting::IncrementDiscoveryItem(Discovery::Event::MoreLocalsClicked); + EyeForTesting::IncrementDiscoveryItem(Discovery::Event::MoreHotelsClicked); + + auto const info = Eye::Instance().GetInfo(); + auto const & discovery = info->m_discovery; + + TEST_NOT_EQUAL(initialDiscovery.m_lastClickedTime, discovery.m_lastClickedTime, ()); + + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::AttractionsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::CafesClicked), 3, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::HotelsClicked), 1, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::LocalsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreAttractionsClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreCafesClicked), 0, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreHotelsClicked), 1, ()); + TEST_EQUAL(discovery.m_eventCounters.Get(Discovery::Event::MoreLocalsClicked), 1, ()); + } +} + +UNIT_CLASS_TEST(ScopedEyeForTesting, AppendLayerTest) +{ + { + auto const initialInfo = Eye::Instance().GetInfo(); + auto const & initialLayers = initialInfo->m_layers; + + TEST(initialLayers.empty(), ()); + TEST_EQUAL(GetLastShownLayerTime(initialLayers), Time(), ()); + } + Time prevShowTime; + { + EyeForTesting::AppendLayer(Layer::Type::PublicTransport); + + auto const info = Eye::Instance().GetInfo(); + auto const & layers = info->m_layers; + auto const prevShowTime = GetLastShownLayerTime(layers); + + TEST_EQUAL(layers.size(), 1, ()); + TEST_NOT_EQUAL(layers[0].m_lastTimeUsed, Time(), ()); + TEST_EQUAL(layers[0].m_type, Layer::Type::PublicTransport, ()); + TEST_EQUAL(layers[0].m_useCount, 1, ()); + TEST_NOT_EQUAL(prevShowTime, Time(), ()); + } + { + EyeForTesting::AppendLayer(Layer::Type::TrafficJams); + + auto const info = Eye::Instance().GetInfo(); + auto const & layers = info->m_layers; + auto const lastShownLayerTime = GetLastShownLayerTime(layers); + + TEST_EQUAL(layers.size(), 2, ()); + TEST_NOT_EQUAL(layers[1].m_lastTimeUsed, Time(), ()); + TEST_EQUAL(layers[1].m_type, Layer::Type::TrafficJams, ()); + TEST_EQUAL(layers[1].m_useCount, 1, ()); + TEST_EQUAL(layers[1].m_lastTimeUsed, lastShownLayerTime, ()); + TEST_NOT_EQUAL(prevShowTime, lastShownLayerTime, ()); + prevShowTime = lastShownLayerTime; + } + { + EyeForTesting::AppendLayer(Layer::Type::TrafficJams); + + auto const info = Eye::Instance().GetInfo(); + auto const & layers = info->m_layers; + auto const lastShownLayerTime = GetLastShownLayerTime(layers); + + TEST_EQUAL(layers.size(), 2, ()); + TEST_NOT_EQUAL(layers[1].m_lastTimeUsed, Time(), ()); + TEST_EQUAL(layers[1].m_type, Layer::Type::TrafficJams, ()); + TEST_EQUAL(layers[1].m_useCount, 2, ()); + TEST_EQUAL(layers[1].m_lastTimeUsed, lastShownLayerTime, ()); + TEST_NOT_EQUAL(prevShowTime, lastShownLayerTime, ()); + } +} diff --git a/metrics/metrics_tests_support/eye_for_testing.cpp b/metrics/metrics_tests_support/eye_for_testing.cpp index 8411811391..97c294ead1 100644 --- a/metrics/metrics_tests_support/eye_for_testing.cpp +++ b/metrics/metrics_tests_support/eye_for_testing.cpp @@ -20,6 +20,12 @@ void EyeForTesting::ResetEye() my::DeleteFileX(path); } +// static +void EyeForTesting::SetInfo(Info const & info) +{ + Eye::Instance().m_info.Set(std::make_shared(info)); +} + // static void EyeForTesting::AppendTip(Tip::Type type, Tip::Event event) { @@ -27,8 +33,32 @@ void EyeForTesting::AppendTip(Tip::Type type, Tip::Event event) } // static -void EyeForTesting::SetInfo(Info const & info) +void EyeForTesting::UpdateBookingFilterUsedTime() { - Eye::Instance().m_info.Set(std::make_shared(info)); + Eye::Instance().UpdateBookingFilterUsedTime(); +} + +// static +void EyeForTesting::UpdateBoomarksCatalogShownTime() +{ + Eye::Instance().UpdateBoomarksCatalogShownTime(); +} + +// static +void EyeForTesting::UpdateDiscoveryShownTime() +{ + Eye::Instance().UpdateDiscoveryShownTime(); +} + +// static +void EyeForTesting::IncrementDiscoveryItem(Discovery::Event event) +{ + Eye::Instance().IncrementDiscoveryItem(event); +} + +// static +void EyeForTesting::AppendLayer(Layer::Type type) +{ + Eye::Instance().AppendLayer(type); } } // namespace eye diff --git a/metrics/metrics_tests_support/eye_for_testing.hpp b/metrics/metrics_tests_support/eye_for_testing.hpp index 09c515c463..87795d9692 100644 --- a/metrics/metrics_tests_support/eye_for_testing.hpp +++ b/metrics/metrics_tests_support/eye_for_testing.hpp @@ -8,8 +8,13 @@ class EyeForTesting { public: static void ResetEye(); - static void AppendTip(Tip::Type type, Tip::Event event); static void SetInfo(Info const & info); + static void AppendTip(Tip::Type type, Tip::Event event); + static void UpdateBookingFilterUsedTime(); + static void UpdateBoomarksCatalogShownTime(); + static void UpdateDiscoveryShownTime(); + static void IncrementDiscoveryItem(Discovery::Event event); + static void AppendLayer(Layer::Type type); }; class ScopedEyeForTesting