diff --git a/search/geocoder.cpp b/search/geocoder.cpp index f3ef40781f..cf77e68865 100644 --- a/search/geocoder.cpp +++ b/search/geocoder.cpp @@ -440,7 +440,8 @@ void Geocoder::SetParamsForCategorialSearch(Params const & params) LOG(LDEBUG, (static_cast(m_params))); } -size_t Geocoder::OrderCountries(bool inViewport, vector> & infos) +Geocoder::MwmInfosWithType Geocoder::OrderCountries(bool inViewport, + vector> const & infos) { vector keyedInfos; keyedInfos.reserve(infos.size()); @@ -448,10 +449,6 @@ size_t Geocoder::OrderCountries(bool inViewport, vector> & 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 mwmsWithCities; if (!inViewport) { @@ -462,21 +459,28 @@ size_t Geocoder::OrderCountries(bool inViewport, vector> & i } } - auto const firstBatch = [&](shared_ptr 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> & infos, bool inViewport) +void Geocoder::GoImpl(vector> const & infos, bool inViewport) { // base::PProf pprof("/tmp/geocoder.prof"); @@ -517,11 +521,11 @@ void Geocoder::GoImpl(vector> & 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 context) { + auto processCountry = [&](MwmType const & mwmType, unique_ptr context, bool updatePreranker) { ASSERT(context, ()); m_context = move(context); @@ -560,20 +564,21 @@ void Geocoder::GoImpl(vector> & 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> & 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 -void Geocoder::ForEachCountry(vector> 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> const & infos, Fn && f auto & value = *handle.GetValue(); if (!value.HasSearchIndex() || !value.HasGeometryIndex()) continue; - if (fn(i, make_unique(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(move(handle)), updatePreranker) == + base::ControlFlow::Break) + { break; + } } } diff --git a/search/geocoder.hpp b/search/geocoder.hpp index d35be15118..efddf3ca04 100644 --- a/search/geocoder.hpp +++ b/search/geocoder.hpp @@ -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, MwmType>; + std::vector 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> & infos, bool inViewport); + void GoImpl(std::vector> const & infos, bool inViewport); template using TokenToLocalities = std::map>; @@ -183,7 +203,7 @@ private: bool CityHasPostcode(BaseContext const & ctx) const; template - void ForEachCountry(std::vector> 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> & infos); + MwmInfosWithType OrderCountries(bool inViewport, + std::vector> const & infos); DataSource const & m_dataSource; storage::CountryInfoGetter const & m_infoGetter;