[tips] Tips are added

This commit is contained in:
Arsentiy Milchakov 2018-08-28 13:26:51 +03:00 committed by Tatiana Yan
parent 6e77783f85
commit 856f90dd0c
5 changed files with 221 additions and 2 deletions

View file

@ -94,6 +94,8 @@ set(
subscription.hpp
taxi_delegate.cpp
taxi_delegate.hpp
tips_api.cpp
tips_api.hpp
track.cpp
track.hpp
traffic_manager.cpp

View file

@ -3660,3 +3660,21 @@ booking::AvailabilityParams Framework::GetLastBookingAvailabilityParams() const
{
return m_bookingAvailabilityParams;
}
TipsApi const & Framework::GetTipsApi() const
{
return m_tipsApi;
}
bool Framework::HaveTransit(m2::PointD const & pt) const
{
auto const & dataSource = m_model.GetDataSource();
MwmSet::MwmId const mwmId =
dataSource.GetMwmIdByCountryFile(platform::CountryFile(m_infoGetter->GetRegionCountryId(pt)));
MwmSet::MwmHandle handle = m_model.GetDataSource().GetMwmHandleById(mwmId);
if (!handle.IsAlive())
return false;
return handle.GetValue<MwmValue>()->m_cont.IsExist(TRANSIT_FILE_TAG);
}

View file

@ -16,6 +16,7 @@
#include "map/search_api.hpp"
#include "map/search_mark.hpp"
#include "map/subscription.hpp"
#include "map/tips_api.hpp"
#include "map/track.hpp"
#include "map/traffic_manager.hpp"
#include "map/transit/transit_reader.hpp"
@ -57,6 +58,8 @@
#include "partners_api/taxi_engine.hpp"
#include "partners_api/viator_api.hpp"
#include "eye/eye_info.hpp"
#include "platform/country_defines.hpp"
#include "platform/location.hpp"
#include "platform/platform.hpp"
@ -129,7 +132,9 @@ struct FrameworkParams
{}
};
class Framework : public SearchAPI::Delegate, public RoutingManager::Delegate
class Framework : public SearchAPI::Delegate,
public RoutingManager::Delegate,
public TipsApi::Delegate
{
DISALLOW_COPY(Framework);
@ -283,7 +288,7 @@ public:
void ShowNode(storage::TCountryId const & countryId);
/// Checks, whether the country which contains the specified point is loaded.
bool IsCountryLoaded(m2::PointD const & pt) const;
bool IsCountryLoaded(m2::PointD const & pt) const override;
/// Checks, whether the country is loaded.
bool IsCountryLoadedByName(string const & name) const;
//@}
@ -876,4 +881,10 @@ public:
private:
std::unique_ptr<Subscription> m_subscription;
TipsApi m_tipsApi;
public:
TipsApi const & GetTipsApi() const;
bool HaveTransit(m2::PointD const & pt) const override;
};

144
map/tips_api.cpp Normal file
View file

@ -0,0 +1,144 @@
#include "map/tips_api.hpp"
#include "eye/eye.hpp"
#include "platform/platform.hpp"
#include <array>
#include <utility>
using namespace eye;
namespace
{
// The app shouldn't show any screen at all more frequently than once in 3 days.
auto const kShowAnyTipPeriod = std::chrono::hours(24) * 3;
// The app shouldn't show the same screen more frequently than 1 month.
auto const kShowSameTipPeriod = std::chrono::hours(24) * 30;
// If a user clicks on the action areas (highlighted or blue button)
// the appropriate screen will never be shown again.
size_t const kActionClicksCountToDisable = 1;
// If a user clicks 3 times on the button GOT IT the appropriate screen will never be shown again.
size_t const kGotitClicksCountToDisable = 3;
size_t ToIndex(Tips::Type type)
{
return static_cast<size_t>(type);
}
TipsApi::Tip GetTipImpl(TipsApi::Duration showAnyTipPeriod, TipsApi::Duration showSameTipPeriod,
TipsApi::Conditions const & triggers)
{
auto const info = Eye::Instance().GetInfo();
auto const & tips = info->m_tips;
auto const totalTipsCount = static_cast<size_t>(Tips::Type::Count);
if (Clock::now() - tips.m_lastShown <= showAnyTipPeriod)
return {};
// If some tips are never shown.
if (tips.m_shownTips.size() < totalTipsCount)
{
using Candidate = std::pair<Tips::Type, bool>;
std::array<Candidate, totalTipsCount> candidates;
for (size_t i = 0; i < totalTipsCount; ++i)
{
candidates[i] = {static_cast<Tips::Type>(i), true};
}
for (auto const & shownTip : tips.m_shownTips)
{
candidates[ToIndex(shownTip.m_type)].second = false;
}
for (auto const & c : candidates)
{
if (c.second && triggers[ToIndex(c.first)]())
return c.first;
}
}
for (auto const & shownTip : tips.m_shownTips)
{
if (shownTip.m_eventCounters.Get(Tips::Event::ActionClicked) < kActionClicksCountToDisable &&
shownTip.m_eventCounters.Get(Tips::Event::GotitClicked) < kGotitClicksCountToDisable &&
Clock::now() - shownTip.m_lastShown > showSameTipPeriod &&
triggers[ToIndex(shownTip.m_type)]())
{
return shownTip.m_type;
}
}
return {};
}
} // namespace
// static
TipsApi::Duration TipsApi::GetShowAnyTipPeriod()
{
return kShowAnyTipPeriod;
}
// static
TipsApi::Duration TipsApi::GetShowSameTipPeriod()
{
return kShowSameTipPeriod;
}
// static
size_t TipsApi::GetActionClicksCountToDisable()
{
return kActionClicksCountToDisable;
}
// static
size_t TipsApi::GetGotitClicksCountToDisable()
{
return kGotitClicksCountToDisable;
}
TipsApi::TipsApi()
{
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]
{
auto const pos = m_delegate->GetCurrentPosition();
if (!pos.is_initialized())
return false;
return m_delegate->IsCountryLoaded(pos.get());
},
// Condition for Tips::Type::MapsLayers type.
[this]
{
auto const pos = m_delegate->GetCurrentPosition();
if (!pos.is_initialized())
return false;
return m_delegate->HaveTransit(pos.get());
}
}};
}
void TipsApi::SetDelegate(std::unique_ptr<Delegate> delegate)
{
m_delegate = std::move(delegate);
}
TipsApi::Tip TipsApi::GetTip() const
{
return GetTipImpl(GetShowAnyTipPeriod(), GetShowSameTipPeriod(), m_conditions);
}
// static
TipsApi::Tip TipsApi::GetTipForTesting(Duration showAnyTipPeriod, Duration showSameTipPeriod,
Conditions const & triggers)
{
return GetTipImpl(showAnyTipPeriod, showSameTipPeriod, triggers);
}

44
map/tips_api.hpp Normal file
View file

@ -0,0 +1,44 @@
#pragma once
#include "eye/eye_info.hpp"
#include <array>
#include <chrono>
#include <functional>
#include <memory>
#include <boost/optional.hpp>
class TipsApi
{
public:
using Tip = boost::optional<eye::Tips::Type>;
using Duration = std::chrono::duration<uint64_t>;
using Condition = std::function<bool()>;
using Conditions = std::array<Condition, static_cast<size_t>(eye::Tips::Type::Count)>;
class Delegate
{
public:
virtual boost::optional<m2::PointD> GetCurrentPosition() const = 0;
virtual bool IsCountryLoaded(m2::PointD const & pt) const = 0;
virtual bool HaveTransit(m2::PointD const & pt) const = 0;
};
static Duration GetShowAnyTipPeriod();
static Duration GetShowSameTipPeriod();
static size_t GetActionClicksCountToDisable();
static size_t GetGotitClicksCountToDisable();
TipsApi();
void SetDelegate(std::unique_ptr<Delegate> delegate);
Tip GetTip() const;
static Tip GetTipForTesting(Duration showAnyTipPeriod, Duration showSameTipPeriod,
Conditions const & triggers);
private:
std::unique_ptr<Delegate> m_delegate;
Conditions m_conditions;
};