diff --git a/search/intermediate_result.cpp b/search/intermediate_result.cpp index 9c7bb82a26..3fd67841fb 100644 --- a/search/intermediate_result.cpp +++ b/search/intermediate_result.cpp @@ -60,11 +60,8 @@ void ProcessMetadata(FeatureType const & ft, Result::Metadata & meta) namespace impl { -PreResult1::PreResult1(double priority) : m_priority(priority) {} - -PreResult1::PreResult1(FeatureID const & fID, double priority, int8_t viewportID, - v2::PreRankingInfo const & info) - : m_id(fID), m_priority(priority), m_viewportID(viewportID), m_info(info) +PreResult1::PreResult1(FeatureID const & fID, v2::PreRankingInfo const & info) + : m_id(fID), m_info(info) { ASSERT(m_id.IsValid(), ()); } @@ -74,14 +71,14 @@ bool PreResult1::LessRank(PreResult1 const & r1, PreResult1 const & r2) { if (r1.m_info.m_rank != r2.m_info.m_rank) return r1.m_info.m_rank > r2.m_info.m_rank; - return r1.m_priority < r2.m_priority; + return r1.m_info.m_distanceToPivot < r2.m_info.m_distanceToPivot; } // static -bool PreResult1::LessPriority(PreResult1 const & r1, PreResult1 const & r2) +bool PreResult1::LessDistance(PreResult1 const & r1, PreResult1 const & r2) { - if (r1.m_priority != r2.m_priority) - return r1.m_priority < r2.m_priority; + if (r1.m_info.m_distanceToPivot != r2.m_info.m_distanceToPivot) + return r1.m_info.m_distanceToPivot < r2.m_info.m_distanceToPivot; return r1.m_info.m_rank > r2.m_info.m_rank; } diff --git a/search/intermediate_result.hpp b/search/intermediate_result.hpp index 9593e1ed89..1a4d744281 100644 --- a/search/intermediate_result.hpp +++ b/search/intermediate_result.hpp @@ -24,31 +24,25 @@ namespace impl /// Works fast without feature loading and provide ranking. class PreResult1 { +public: + PreResult1(FeatureID const & fID, v2::PreRankingInfo const & info); + + static bool LessRank(PreResult1 const & r1, PreResult1 const & r2); + static bool LessDistance(PreResult1 const & r1, PreResult1 const & r2); + + inline FeatureID GetId() const { return m_id; } + inline double GetDistance() const { return m_info.m_distanceToPivot; } + inline uint8_t GetRank() const { return m_info.m_rank; } + inline v2::PreRankingInfo & GetInfo() { return m_info; } + inline v2::PreRankingInfo const & GetInfo() const { return m_info; } + +private: friend class PreResult2; FeatureID m_id; - double m_priority; - int8_t m_viewportID; - v2::PreRankingInfo m_info; - -public: - explicit PreResult1(double priority); - - PreResult1(FeatureID const & fID, double priority, int8_t viewportID, - v2::PreRankingInfo const & info); - - static bool LessRank(PreResult1 const & r1, PreResult1 const & r2); - static bool LessPriority(PreResult1 const & r1, PreResult1 const & r2); - - inline FeatureID GetID() const { return m_id; } - inline double GetPriority() const { return m_priority; } - inline uint8_t GetRank() const { return m_info.m_rank; } - inline int8_t GetViewportID() const { return m_viewportID; } - inline v2::PreRankingInfo const & GetInfo() const { return m_info; } }; - /// Second result class. Objects are creating during reading of features. /// Read and fill needed info for ranking and getting final results. class PreResult2 diff --git a/search/pre_ranker.cpp b/search/pre_ranker.cpp new file mode 100644 index 0000000000..8b70e37d96 --- /dev/null +++ b/search/pre_ranker.cpp @@ -0,0 +1,114 @@ +#include "search/pre_ranker.hpp" + +#include "search/v2/pre_ranking_info.hpp" + +#include "std/iterator.hpp" +#include "std/random.hpp" +#include "std/set.hpp" + +namespace search +{ +namespace +{ +struct LessFeatureID +{ + using TValue = impl::PreResult1; + + inline bool operator()(TValue const & lhs, TValue const & rhs) const + { + return lhs.GetId() < rhs.GetId(); + } +}; + +struct EqualFeatureID +{ + using TValue = impl::PreResult1; + + inline bool operator()(TValue const & lhs, TValue const & rhs) const + { + return lhs.GetId() == rhs.GetId(); + } +}; + +// Orders PreResult1 by following criterion: +// 1. Feature Id (increasing), if same... +// 2. Number of matched tokens from the query (decreasing), if same... +// 3. Index of the first matched token from the query (increasing). +struct ComparePreResult1 +{ + bool operator()(impl::PreResult1 const & lhs, impl::PreResult1 const & rhs) const + { + if (lhs.GetId() != rhs.GetId()) + return lhs.GetId() < rhs.GetId(); + + auto const & linfo = lhs.GetInfo(); + auto const & rinfo = rhs.GetInfo(); + if (linfo.GetNumTokens() != rinfo.GetNumTokens()) + return linfo.GetNumTokens() > rinfo.GetNumTokens(); + return linfo.m_startToken < rinfo.m_startToken; + } +}; +} // namespace + +PreRanker::PreRanker(size_t limit) : m_limit(limit) {} + +void PreRanker::Add(impl::PreResult1 const & result) { m_results.push_back(result); } + +void PreRanker::Filter(bool viewportSearch) +{ + using TSet = set; + TSet theSet; + + sort(m_results.begin(), m_results.end(), ComparePreResult1()); + m_results.erase(unique(m_results.begin(), m_results.end(), EqualFeatureID()), m_results.end()); + + sort(m_results.begin(), m_results.end(), &impl::PreResult1::LessDistance); + + if (m_limit != 0 && m_results.size() > m_limit) + { + // Priority is some kind of distance from the viewport or + // position, therefore if we have a bunch of results with the same + // priority, we have no idea here which results are relevant. To + // prevent bias from previous search routines (like sorting by + // feature id) this code randomly selects tail of the + // sorted-by-priority list of pre-results. + + double const last = m_results[m_limit - 1].GetDistance(); + + auto b = m_results.begin() + m_limit - 1; + for (; b != m_results.begin() && b->GetDistance() == last; --b) + ; + if (b->GetDistance() != last) + ++b; + + auto e = m_results.begin() + m_limit; + for (; e != m_results.end() && e->GetDistance() == last; ++e) + ; + + // The main reason of shuffling here is to select a random subset + // from the low-priority results. We're using a linear + // congruential method with default seed because it is fast, + // simple and doesn't need an external entropy source. + // + // TODO (@y, @m, @vng): consider to take some kind of hash from + // features and then select a subset with smallest values of this + // hash. In this case this subset of results will be persistent + // to small changes in the original set. + minstd_rand engine; + shuffle(b, e, engine); + } + theSet.insert(m_results.begin(), m_results.begin() + min(m_results.size(), m_limit)); + + if (!viewportSearch) + { + size_t n = min(m_results.size(), m_limit); + nth_element(m_results.begin(), m_results.begin() + n, m_results.end(), + &impl::PreResult1::LessRank); + theSet.insert(m_results.begin(), m_results.begin() + n); + } + + m_results.reserve(theSet.size()); + m_results.clear(); + copy(theSet.begin(), theSet.end(), back_inserter(m_results)); +} +} // namespace search diff --git a/search/pre_ranker.hpp b/search/pre_ranker.hpp new file mode 100644 index 0000000000..3e7f25f591 --- /dev/null +++ b/search/pre_ranker.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include "search/intermediate_result.hpp" + +#include "base/macros.hpp" + +#include "std/algorithm.hpp" +#include "std/cstdint.hpp" +#include "std/utility.hpp" +#include "std/vector.hpp" + +namespace search +{ +// Fast and simple pre-ranker for search results. +class PreRanker +{ +public: + explicit PreRanker(size_t limit); + + void Add(impl::PreResult1 const & result); + + template + void Emplace(TArgs &&... args) + { + m_results.emplace_back(forward(args)...); + } + + void Filter(bool viewportSearch); + + inline size_t Size() const { return m_results.size(); } + inline size_t Limit() const { return m_limit; } + inline bool IsEmpty() const { return Size() == 0; } + inline void Clear() { m_results.clear(); }; + + template + void ForEach(TFn && fn) + { + for_each(m_results.begin(), m_results.end(), forward(fn)); + } + + template + void ForEachInfo(TFn && fn) + { + for (auto & result : m_results) + fn(result.GetId(), result.GetInfo()); + } + +private: + vector m_results; + size_t const m_limit; + + DISALLOW_COPY_AND_MOVE(PreRanker); +}; +} // namespace search diff --git a/search/search.pro b/search/search.pro index 6ba422fe32..1f763168a0 100644 --- a/search/search.pro +++ b/search/search.pro @@ -25,6 +25,7 @@ HEADERS += \ locality_finder.hpp \ mode.hpp \ params.hpp \ + pre_ranker.hpp \ projection_on_street.hpp \ query_saver.hpp \ region.hpp \ @@ -78,6 +79,7 @@ SOURCES += \ locality_finder.cpp \ mode.cpp \ params.cpp \ + pre_ranker.cpp \ projection_on_street.cpp \ query_saver.cpp \ region.cpp \ diff --git a/search/search_query.cpp b/search/search_query.cpp index 0f78a1c64f..6ccda4996d 100644 --- a/search/search_query.cpp +++ b/search/search_query.cpp @@ -2,6 +2,7 @@ #include "search/dummy_rank_table.hpp" #include "search/geometry_utils.hpp" +#include "search/intermediate_result.hpp" #include "search/latlon_match.hpp" #include "search/locality.hpp" #include "search/region.hpp" @@ -49,7 +50,6 @@ #include "std/function.hpp" #include "std/iterator.hpp" #include "std/limits.hpp" -#include "std/random.hpp" #define LONG_OP(op) \ { \ @@ -227,6 +227,7 @@ Query::Query(Index & index, CategoriesHolder const & categories, vector , m_mode(Mode::Everywhere) , m_worldSearch(true) , m_suggestsEnabled(true) + , m_preRanker(kPreResultsCount) , m_viewportSearch(false) , m_keepHouseNumberInQuery(false) , m_reverseGeocoder(index) @@ -385,14 +386,8 @@ void Query::Init(bool viewportSearch) m_tokens.clear(); m_prefix.clear(); + m_preRanker.Clear(); m_viewportSearch = viewportSearch; - - ClearResults(); -} - -void Query::ClearResults() -{ - m_results.clear(); } int Query::GetCategoryLocales(int8_t (&arr) [3]) const @@ -544,51 +539,6 @@ void Query::SearchCoordinates(Results & res) const namespace { -struct LessFeatureID -{ - using TValue = impl::PreResult1; - - inline bool operator()(TValue const & lhs, TValue const & rhs) const - { - return lhs.GetID() < rhs.GetID(); - } -}; - -struct EqualFeatureID -{ - using TValue = impl::PreResult1; - - inline bool operator()(TValue const & lhs, TValue const & rhs) const - { - return lhs.GetID() == rhs.GetID(); - } -}; - -// Orders PreResult1 by following criterion: -// 1. Feature Id (increasing), if same... -// 2. Number of matched tokens from the query (decreasing), if same... -// 3. Index of the first matched token from the query (increasing). -struct ComparePreResult1 -{ - bool operator()(impl::PreResult1 const & lhs, impl::PreResult1 const & rhs) const - { - if (lhs.GetID() != rhs.GetID()) - return lhs.GetID() < rhs.GetID(); - - auto const & linfo = lhs.GetInfo(); - auto const & rinfo = rhs.GetInfo(); - if (linfo.GetNumTokens() != rinfo.GetNumTokens()) - return linfo.GetNumTokens() > rinfo.GetNumTokens(); - return linfo.m_startToken < rinfo.m_startToken; - } -}; - -void RemoveDuplicatingPreResults1(vector & results) -{ - sort(results.begin(), results.end(), ComparePreResult1()); - results.erase(unique(results.begin(), results.end(), EqualFeatureID()), results.end()); -} - bool IsResultExists(impl::PreResult2 const & p, vector const & indV) { impl::PreResult2::StrictEqualF equalCmp(p); @@ -719,7 +669,7 @@ public: string name; string country; - LoadFeature(res1.GetID(), ft, center, name, country); + LoadFeature(res1.GetId(), ft, center, name, country); auto res2 = make_unique(ft, &res1, center, m_query.GetPosition() /* pivot */, name, country); @@ -738,75 +688,25 @@ template void Query::MakePreResult2(v2::Geocoder::Params const & params, vector & cont, vector & streets) { - // make unique set of PreResult1 - using TPreResultSet = set; - TPreResultSet theSet; - - RemoveDuplicatingPreResults1(m_results); - - sort(m_results.begin(), m_results.end(), &impl::PreResult1::LessPriority); - if (kPreResultsCount != 0 && m_results.size() > kPreResultsCount) - { - // Priority is some kind of distance from the viewport or - // position, therefore if we have a bunch of results with the same - // priority, we have no idea here which results are relevant. To - // prevent bias from previous search routines (like sorting by - // feature id) this code randomly selects tail of the - // sorted-by-priority list of pre-results. - - double const lastPriority = m_results[kPreResultsCount - 1].GetPriority(); - - auto b = m_results.begin() + kPreResultsCount - 1; - for (; b != m_results.begin() && b->GetPriority() == lastPriority; --b) - ; - if (b->GetPriority() != lastPriority) - ++b; - - auto e = m_results.begin() + kPreResultsCount; - for (; e != m_results.end() && e->GetPriority() == lastPriority; ++e) - ; - - // The main reason of shuffling here is to select a random subset - // from the low-priority results. We're using a linear - // congruential method with default seed because it is fast, - // simple and doesn't need an external entropy source. - // - // TODO (@y, @m, @vng): consider to take some kind of hash from - // features and then select a subset with smallest values of this - // hash. In this case this subset of results will be persistent - // to small changes in the original set. - minstd_rand engine; - shuffle(b, e, engine); - } - theSet.insert(m_results.begin(), m_results.begin() + min(m_results.size(), kPreResultsCount)); - - if (!m_viewportSearch) - { - size_t n = min(m_results.size(), kPreResultsCount); - nth_element(m_results.begin(), m_results.begin() + n, m_results.end(), - &impl::PreResult1::LessRank); - theSet.insert(m_results.begin(), m_results.begin() + n); - } - - ClearResults(); + m_preRanker.Filter(m_viewportSearch); // Makes PreResult2 vector. impl::PreResult2Maker maker(*this, params); - for (auto const & r : theSet) + m_preRanker.ForEach([&](impl::PreResult1 const & r) { auto p = maker(r); if (!p) - continue; + return; if (params.m_mode == Mode::Viewport && !params.m_pivot.IsPointInside(p->GetCenter())) - continue; + return; if (p->IsStreet()) streets.push_back(p->GetID()); if (!IsResultExists(*p, cont)) cont.push_back(IndexedValue(move(p))); - } + }); } void Query::FlushResults(v2::Geocoder::Params const & params, Results & res, bool allMWMs, @@ -941,13 +841,6 @@ void Query::ProcessSuggestions(vector & vec, Results & res) const } } -void Query::AddPreResult1(MwmSet::MwmId const & mwmId, uint32_t featureId, double priority, - v2::PreRankingInfo const & info, ViewportID viewportId /* = DEFAULT_V */) -{ - FeatureID id(mwmId, featureId); - m_results.emplace_back(id, priority, viewportId, info); -} - namespace impl { class BestNameFinder diff --git a/search/search_query.hpp b/search/search_query.hpp index a35732d43f..50c7bec03f 100644 --- a/search/search_query.hpp +++ b/search/search_query.hpp @@ -1,7 +1,7 @@ #pragma once -#include "search/intermediate_result.hpp" #include "search/keyword_lang_matcher.hpp" #include "search/mode.hpp" +#include "search/pre_ranker.hpp" #include "search/reverse_geocoder.hpp" #include "search/search_trie.hpp" #include "search/suggest.hpp" @@ -59,11 +59,6 @@ namespace impl class HouseCompFactory; } -namespace v2 -{ -struct PreRankingInfo; -} - // TODO (@y): rename this class to QueryProcessor. class Query : public my::Cancellable { @@ -106,8 +101,8 @@ public: /// @name Different search functions. //@{ - virtual void Search(Results & res, size_t resCount) = 0; - virtual void SearchViewportPoints(Results & res) = 0; + virtual void Search(Results & results, size_t limit) = 0; + virtual void SearchViewportPoints(Results & results) = 0; // Tries to generate a (lat, lon) result from |m_query|. void SearchCoordinates(Results & res) const; @@ -143,8 +138,6 @@ protected: friend class impl::DoFindLocality; friend class impl::HouseCompFactory; - void ClearResults(); - int GetCategoryLocales(int8_t (&arr) [3]) const; template void ForEachCategoryTypes(v2::QuerySlice const & slice, ToDo toDo) const; @@ -162,9 +155,6 @@ protected: bool forceUpdate); void ClearCache(size_t ind); - void AddPreResult1(MwmSet::MwmId const & mwmId, uint32_t featureId, double priority, - v2::PreRankingInfo const & info, ViewportID viewportId = DEFAULT_V); - template void MakePreResult2(v2::Geocoder::Params const & params, vector & cont, vector & streets); @@ -245,29 +235,10 @@ protected: using TQueueCompare = TCompare; using TQueue = my::limited_priority_queue; - /// @name Intermediate result queues sorted by different criterias. - //@{ -public: - enum - { - kQueuesCount = 2 - }; - protected: - // The values order should be the same as in - // g_arrCompare1, g_arrCompare2 function arrays. - enum - { - DISTANCE_TO_PIVOT, // LessDistance - FEATURE_RANK // LessRank - }; - - vector m_results; + PreRanker m_preRanker; bool m_viewportSearch; bool m_keepHouseNumberInQuery; - //@} - search::ReverseGeocoder const m_reverseGeocoder; }; - } // namespace search diff --git a/search/v2/geocoder.cpp b/search/v2/geocoder.cpp index b39acdfb82..defafbe7bc 100644 --- a/search/v2/geocoder.cpp +++ b/search/v2/geocoder.cpp @@ -385,18 +385,10 @@ void UniteCBVs(vector> & cbvs) cbvs.resize(i); } } - -bool SameMwm(Geocoder::TResult const & lhs, Geocoder::TResult const & rhs) -{ - return lhs.first.m_mwmId == rhs.first.m_mwmId; -} } // namespace // Geocoder::Params -------------------------------------------------------------------------------- -Geocoder::Params::Params() - : m_mode(Mode::Everywhere), m_accuratePivotCenter(0, 0), m_maxNumResults(0) -{ -} +Geocoder::Params::Params() : m_mode(Mode::Everywhere), m_accuratePivotCenter(0, 0) {} // Geocoder::Geocoder ------------------------------------------------------------------------------ Geocoder::Geocoder(Index & index, storage::CountryInfoGetter const & infoGetter) @@ -414,7 +406,7 @@ Geocoder::Geocoder(Index & index, storage::CountryInfoGetter const & infoGetter) , m_matcher(nullptr) , m_finder(static_cast(*this)) , m_lastMatchedRegion(nullptr) - , m_results(nullptr) + , m_preRanker(nullptr) { } @@ -463,7 +455,7 @@ void Geocoder::SetParams(Params const & params) LOG(LDEBUG, ("Languages =", m_params.m_langs)); } -void Geocoder::GoEverywhere(TResultList & results) +void Geocoder::GoEverywhere(PreRanker & preRanker) { // TODO (@y): remove following code as soon as Geocoder::Go() will // work fast for most cases (significantly less than 1 second). @@ -482,21 +474,17 @@ void Geocoder::GoEverywhere(TResultList & results) if (m_numTokens == 0) return; - m_results = &results; - vector> infos; m_index.GetMwmsInfo(infos); - GoImpl(infos, false /* inViewport */); + GoImpl(preRanker, infos, false /* inViewport */); } -void Geocoder::GoInViewport(TResultList & results) +void Geocoder::GoInViewport(PreRanker & preRanker) { if (m_numTokens == 0) return; - m_results = &results; - vector> infos; m_index.GetMwmsInfo(infos); @@ -505,11 +493,13 @@ void Geocoder::GoInViewport(TResultList & results) return !m_params.m_pivot.IsIntersect(info->m_limitRect); }); - GoImpl(infos, true /* inViewport */); + GoImpl(preRanker, infos, true /* inViewport */); } -void Geocoder::GoImpl(vector> & infos, bool inViewport) +void Geocoder::GoImpl(PreRanker & preRanker, vector> & infos, bool inViewport) { + m_preRanker = &preRanker; + try { // Tries to find world and fill localities table. @@ -605,7 +595,7 @@ void Geocoder::GoImpl(vector> & infos, bool inViewport) m_lastMatchedRegion = nullptr; MatchRegions(REGION_TYPE_COUNTRY); - if (index < numIntersectingMaps || m_results->empty()) + if (index < numIntersectingMaps || m_preRanker->IsEmpty()) MatchAroundPivot(); }; @@ -986,7 +976,7 @@ void Geocoder::MatchAroundPivot() if (!features) return; - ViewportFilter filter(*features, m_params.m_maxNumResults /* threshold */); + ViewportFilter filter(*features, m_preRanker->Limit() /* threshold */); LimitedSearch(filter); } @@ -1364,13 +1354,17 @@ void Geocoder::EmitResult(MwmSet::MwmId const & mwmId, uint32_t ftId, SearchMode { FeatureID id(mwmId, ftId); + // Distance and rank will be filled at the end, for all results at once. + // + // TODO (@y, @m): need to skip zero rank features that are too + // distant from the pivot when there're enough results close to the + // pivot. PreRankingInfo info; info.m_searchType = type; info.m_startToken = startToken; info.m_endToken = endToken; - // Other fields will be filled at the end, for all results at once. - m_results->emplace_back(move(id), move(info)); + m_preRanker->Emplace(id, info); } void Geocoder::EmitResult(Region const & region, size_t startToken, size_t endToken) @@ -1392,42 +1386,32 @@ void Geocoder::EmitResult(City const & city, size_t startToken, size_t endToken) void Geocoder::FillMissingFieldsInResults() { - sort(m_results->begin(), m_results->end(), my::CompareBy(&TResult::first)); + MwmSet::MwmId mwmId; + MwmSet::MwmHandle mwmHandle; + unique_ptr rankTable; - auto ib = m_results->begin(); - while (ib != m_results->end()) - { - auto ie = ib; - while (ie != m_results->end() && SameMwm(*ib, *ie)) - ++ie; + m_preRanker->ForEachInfo([&](FeatureID const & id, PreRankingInfo & info) + { + if (id.m_mwmId != mwmId) + { + mwmId = id.m_mwmId; + mwmHandle = m_index.GetMwmHandleById(mwmId); + rankTable = RankTable::Load(mwmHandle.GetValue()->m_cont); + if (!rankTable) + rankTable = make_unique(); + } - /// @todo Add RankTableCache here? - MwmSet::MwmHandle handle = m_index.GetMwmHandleById(ib->first.m_mwmId); - if (handle.IsAlive()) - { - auto rankTable = RankTable::Load(handle.GetValue()->m_cont); - if (!rankTable.get()) - rankTable.reset(new DummyRankTable()); + info.m_rank = rankTable->Get(id.m_index); + }); - for (auto ii = ib; ii != ie; ++ii) - { - auto const & id = ii->first; - auto & info = ii->second; - info.m_rank = rankTable->Get(id.m_index); - } - } - ib = ie; - } - - if (m_results->size() > m_params.m_maxNumResults) + if (m_preRanker->Size() > m_preRanker->Limit()) { m_pivotFeatures.SetPosition(m_params.m_accuratePivotCenter, m_params.m_scale); - for (auto & result : *m_results) - { - auto const & id = result.first; - auto & info = result.second; - info.m_distanceToPivot = m_pivotFeatures.GetDistanceToFeatureMeters(id); - } + m_preRanker->ForEachInfo([&](FeatureID const & id, PreRankingInfo & info) + { + info.m_distanceToPivot = + m_pivotFeatures.GetDistanceToFeatureMeters(id); + }); } } diff --git a/search/v2/geocoder.hpp b/search/v2/geocoder.hpp index 355b25c5fe..db4753b657 100644 --- a/search/v2/geocoder.hpp +++ b/search/v2/geocoder.hpp @@ -48,6 +48,8 @@ class CountryInfoGetter; namespace search { +class PreRanker; + namespace v2 { class FeaturesFilter; @@ -88,7 +90,6 @@ public: // compute a distance from a feature to the pivot. m2::RectD m_pivot; m2::PointD m_accuratePivotCenter; - size_t m_maxNumResults; }; enum RegionType @@ -141,9 +142,6 @@ public: #endif }; - using TResult = pair; - using TResultList = vector; - Geocoder(Index & index, storage::CountryInfoGetter const & infoGetter); ~Geocoder() override; @@ -153,8 +151,8 @@ public: // Starts geocoding, retrieved features will be appended to // |results|. - void GoEverywhere(TResultList & results); - void GoInViewport(TResultList & results); + void GoEverywhere(PreRanker & preRanker); + void GoInViewport(PreRanker & preRanker); void ClearCaches(); @@ -182,7 +180,7 @@ private: unique_ptr m_features; }; - void GoImpl(vector> & infos, bool inViewport); + void GoImpl(PreRanker & preRanker, vector> & infos, bool inViewport); template using TLocalitiesCache = map, vector>; @@ -259,13 +257,13 @@ private: // the lowest layer. void FindPaths(); - // Forms result and appends it to |m_results|. + // Forms result and feeds it to |m_preRanker|. void EmitResult(MwmSet::MwmId const & mwmId, uint32_t ftId, SearchModel::SearchType type, size_t startToken, size_t endToken); void EmitResult(Region const & region, size_t startToken, size_t endToken); void EmitResult(City const & city, size_t startToken, size_t endToken); - // Computes missing fields for all results in |m_results|. + // Computes missing fields for all results in |m_preRanker|. void FillMissingFieldsInResults(); // Tries to match unclassified objects from lower layers, like @@ -382,8 +380,8 @@ private: // Stack of layers filled during geocoding. vector m_layers; - // Non-owning pointer to a vector of results. - TResultList * m_results; + // Non-owning. + PreRanker * m_preRanker; }; string DebugPrint(Geocoder::Locality const & locality); diff --git a/search/v2/search_query_v2.cpp b/search/v2/search_query_v2.cpp index 02040088eb..af70a2fe83 100644 --- a/search/v2/search_query_v2.cpp +++ b/search/v2/search_query_v2.cpp @@ -33,10 +33,10 @@ void SearchQueryV2::Cancel() m_geocoder.Cancel(); } -void SearchQueryV2::Search(Results & res, size_t resCount) +void SearchQueryV2::Search(Results & results, size_t limit) { if (m_tokens.empty()) - SuggestStrings(res); + SuggestStrings(results); Geocoder::Params params; InitParams(false /* localitySearch */, params); @@ -44,30 +44,24 @@ void SearchQueryV2::Search(Results & res, size_t resCount) params.m_pivot = GetPivotRect(); params.m_accuratePivotCenter = GetPivotPoint(); - params.m_maxNumResults = max(resCount, kPreResultsCount); m_geocoder.SetParams(params); - Geocoder::TResultList results; - m_geocoder.GoEverywhere(results); - AddPreResults1(results); + m_geocoder.GoEverywhere(m_preRanker); - FlushResults(params, res, false /* allMWMs */, resCount, false /* oldHouseSearch */); + FlushResults(params, results, false /* allMWMs */, limit, false /* oldHouseSearch */); } -void SearchQueryV2::SearchViewportPoints(Results & res) +void SearchQueryV2::SearchViewportPoints(Results & results) { Geocoder::Params params; InitParams(false /* localitySearch */, params); params.m_pivot = m_viewport[CURRENT_V]; params.m_accuratePivotCenter = params.m_pivot.Center(); - params.m_maxNumResults = kPreResultsCount; m_geocoder.SetParams(params); - Geocoder::TResultList results; - m_geocoder.GoInViewport(results); - AddPreResults1(results); + m_geocoder.GoInViewport(m_preRanker); - FlushViewportResults(params, res, false /* oldHouseSearch */); + FlushViewportResults(params, results, false /* oldHouseSearch */); } void SearchQueryV2::ClearCaches() @@ -75,15 +69,5 @@ void SearchQueryV2::ClearCaches() Query::ClearCaches(); m_geocoder.ClearCaches(); } - -void SearchQueryV2::AddPreResults1(Geocoder::TResultList & results) -{ - for (auto const & result : results) - { - auto const & id = result.first; - auto const & info = result.second; - AddPreResult1(id.m_mwmId, id.m_index, info.m_distanceToPivot /* priority */, info); - } -} } // namespace v2 } // namespace search diff --git a/search/v2/search_query_v2.hpp b/search/v2/search_query_v2.hpp index ee64b9333f..1bb2946dcc 100644 --- a/search/v2/search_query_v2.hpp +++ b/search/v2/search_query_v2.hpp @@ -18,14 +18,11 @@ public: void Cancel() override; // Query overrides: - void Search(Results & res, size_t resCount) override; - void SearchViewportPoints(Results & res) override; + void Search(Results & results, size_t limit) override; + void SearchViewportPoints(Results & results) override; void ClearCaches() override; protected: - // Adds a bunch of features as PreResult1. - void AddPreResults1(Geocoder::TResultList & results); - Geocoder m_geocoder; }; } // namespace v2