[search] Keep type of mwm from first batch (ViewportIntersect/UserPosition/MatchedCity).

This commit is contained in:
tatiana-yan 2020-03-17 16:06:50 +03:00 committed by mpimenov
parent a1f75ac67f
commit 0df67950f0
2 changed files with 62 additions and 31 deletions

View file

@ -440,7 +440,8 @@ void Geocoder::SetParamsForCategorialSearch(Params const & params)
LOG(LDEBUG, (static_cast<QueryParams const &>(m_params)));
}
size_t Geocoder::OrderCountries(bool inViewport, vector<shared_ptr<MwmInfo>> & infos)
Geocoder::MwmInfosWithType Geocoder::OrderCountries(bool inViewport,
vector<shared_ptr<MwmInfo>> const & infos)
{
vector<KeyedMwmInfo> keyedInfos;
keyedInfos.reserve(infos.size());
@ -448,10 +449,6 @@ size_t Geocoder::OrderCountries(bool inViewport, vector<shared_ptr<MwmInfo>> & i
keyedInfos.emplace_back(info, m_params.m_position, m_params.m_pivot, inViewport);
sort(keyedInfos.begin(), keyedInfos.end());
infos.clear();
for (auto const & info : keyedInfos)
infos.emplace_back(info.m_info);
set<storage::CountryId> mwmsWithCities;
if (!inViewport)
{
@ -462,21 +459,28 @@ size_t Geocoder::OrderCountries(bool inViewport, vector<shared_ptr<MwmInfo>> & i
}
}
auto const firstBatch = [&](shared_ptr<MwmInfo> const & info) {
if (!inViewport)
{
if (m_params.m_position && info->m_bordersRect.IsPointInside(*m_params.m_position))
return true;
if (mwmsWithCities.count(info->GetCountryName()) != 0)
return true;
}
return m_params.m_pivot.IsIntersect(info->m_bordersRect);
auto const getMwmType = [&](auto const & info) {
MwmType mwmType;
mwmType.m_viewportIntersect = m_params.m_pivot.IsIntersect(info->m_bordersRect);
mwmType.m_userPosition = m_params.m_position &&
info->m_bordersRect.IsPointInside(*m_params.m_position);
mwmType.m_matchedCity = mwmsWithCities.count(info->GetCountryName()) != 0;
return mwmType;
};
auto const sep = stable_partition(infos.begin(), infos.end(), firstBatch);
return distance(infos.begin(), sep);
MwmInfosWithType res;
for (auto const & info : keyedInfos)
res.m_infos.emplace_back(info.m_info, getMwmType(info.m_info));
auto const firstBatch = [&](auto const & infoWithType) {
return infoWithType.second.IsFirstBatchMwm(inViewport);
};
auto const sep = stable_partition(res.m_infos.begin(), res.m_infos.end(), firstBatch);
res.m_firstBatchSize = distance(res.m_infos.begin(), sep);
return res;
}
void Geocoder::GoImpl(vector<shared_ptr<MwmInfo>> & infos, bool inViewport)
void Geocoder::GoImpl(vector<shared_ptr<MwmInfo>> const & infos, bool inViewport)
{
// base::PProf pprof("/tmp/geocoder.prof");
@ -517,11 +521,11 @@ void Geocoder::GoImpl(vector<shared_ptr<MwmInfo>> & infos, bool inViewport)
// maps are ordered by distance from pivot, and we stop to call
// MatchAroundPivot() on them as soon as at least one feature is
// found.
size_t const numIntersectingMaps = OrderCountries(inViewport, infos);
auto const infosWithType = OrderCountries(inViewport, infos);
// MatchAroundPivot() should always be matched in mwms
// intersecting with position and viewport.
auto processCountry = [&](size_t index, unique_ptr<MwmContext> context) {
auto processCountry = [&](MwmType const & mwmType, unique_ptr<MwmContext> context, bool updatePreranker) {
ASSERT(context, ());
m_context = move(context);
@ -560,20 +564,21 @@ void Geocoder::GoImpl(vector<shared_ptr<MwmInfo>> & infos, bool inViewport)
FillVillageLocalities(ctx);
SCOPE_GUARD(remove_villages, [&]() { m_cities = citiesFromWorld; });
bool const intersectsPivot = index < numIntersectingMaps;
if (m_params.IsCategorialRequest())
{
MatchCategories(ctx, intersectsPivot);
MatchCategories(ctx, mwmType.IsFirstBatchMwm(inViewport));
}
else
{
MatchRegions(ctx, Region::TYPE_COUNTRY);
if (intersectsPivot || m_preRanker.NumSentResults() == 0)
if (mwmType.IsFirstBatchMwm(inViewport) || m_preRanker.NumSentResults() == 0)
{
MatchAroundPivot(ctx);
}
}
if (index + 1 >= numIntersectingMaps)
if (updatePreranker)
m_preRanker.UpdateResults(false /* lastUpdate */);
if (m_preRanker.IsFull())
@ -583,7 +588,7 @@ void Geocoder::GoImpl(vector<shared_ptr<MwmInfo>> & infos, bool inViewport)
};
// Iterates through all alive mwms and performs geocoding.
ForEachCountry(infos, processCountry);
ForEachCountry(infosWithType, processCountry);
}
void Geocoder::InitBaseContext(BaseContext & ctx)
@ -792,11 +797,11 @@ bool Geocoder::CityHasPostcode(BaseContext const & ctx) const
}
template <typename Fn>
void Geocoder::ForEachCountry(vector<shared_ptr<MwmInfo>> const & infos, Fn && fn)
void Geocoder::ForEachCountry(MwmInfosWithType const & infosWithType, Fn && fn)
{
for (size_t i = 0; i < infos.size(); ++i)
for (size_t i = 0; i < infosWithType.m_infos.size(); ++i)
{
auto const & info = infos[i];
auto const & info = infosWithType.m_infos[i].first;
if (info->GetType() != MwmInfo::COUNTRY && info->GetType() != MwmInfo::WORLD)
continue;
if (info->GetType() == MwmInfo::COUNTRY && m_params.m_mode == Mode::Downloader)
@ -808,8 +813,13 @@ void Geocoder::ForEachCountry(vector<shared_ptr<MwmInfo>> const & infos, Fn && f
auto & value = *handle.GetValue();
if (!value.HasSearchIndex() || !value.HasGeometryIndex())
continue;
if (fn(i, make_unique<MwmContext>(move(handle))) == base::ControlFlow::Break)
bool const updatePreranker = i + 1 >= infosWithType.m_firstBatchSize;
auto const mwmType = infosWithType.m_infos[i].second;
if (fn(mwmType, make_unique<MwmContext>(move(handle)), updatePreranker) ==
base::ControlFlow::Break)
{
break;
}
}
}

View file

@ -134,6 +134,26 @@ private:
Count
};
struct MwmType
{
bool IsFirstBatchMwm(bool inViewport) const {
if (inViewport)
return m_viewportIntersect;
return m_viewportIntersect || m_userPosition || m_matchedCity;
}
bool m_viewportIntersect = false;
bool m_userPosition = false;
bool m_matchedCity = false;
};
struct MwmInfosWithType
{
using MwmInfoWithType = std::pair<std::shared_ptr<MwmInfo>, MwmType>;
std::vector<MwmInfoWithType> m_infos;
size_t m_firstBatchSize = 0;
};
struct Postcodes
{
void Clear()
@ -160,7 +180,7 @@ private:
// Sets search query params for categorial search.
void SetParamsForCategorialSearch(Params const & params);
void GoImpl(std::vector<std::shared_ptr<MwmInfo>> & infos, bool inViewport);
void GoImpl(std::vector<std::shared_ptr<MwmInfo>> const & infos, bool inViewport);
template <typename Locality>
using TokenToLocalities = std::map<TokenRange, std::vector<Locality>>;
@ -183,7 +203,7 @@ private:
bool CityHasPostcode(BaseContext const & ctx) const;
template <typename Fn>
void ForEachCountry(std::vector<std::shared_ptr<MwmInfo>> const & infos, Fn && fn);
void ForEachCountry(MwmInfosWithType const & infos, Fn && fn);
// Throws CancelException if cancelled.
void BailIfCancelled() { ::search::BailIfCancelled(m_cancellable); }
@ -270,7 +290,8 @@ private:
// center.
// For non-viewport search mode prefix consists of maps intersecting with pivot, map with user location
// and maps with cities matched to the query, sorting prefers mwms that contain the user's position.
size_t OrderCountries(bool inViewport, std::vector<std::shared_ptr<MwmInfo>> & infos);
MwmInfosWithType OrderCountries(bool inViewport,
std::vector<std::shared_ptr<MwmInfo>> const & infos);
DataSource const & m_dataSource;
storage::CountryInfoGetter const & m_infoGetter;