mirror of
https://codeberg.org/comaps/comaps
synced 2026-01-01 18:44:02 +00:00
Format all C++ and Java code via clang-format
Signed-off-by: Konstantin Pastbin <konstantin.pastbin@gmail.com>
This commit is contained in:
@@ -10,71 +10,71 @@ namespace search
|
||||
{
|
||||
namespace impl
|
||||
{
|
||||
struct LS
|
||||
struct LS
|
||||
{
|
||||
size_t prevDecreasePos, decreaseValue;
|
||||
size_t prevIncreasePos, increaseValue;
|
||||
|
||||
LS(size_t i)
|
||||
{
|
||||
size_t prevDecreasePos, decreaseValue;
|
||||
size_t prevIncreasePos, increaseValue;
|
||||
prevDecreasePos = i;
|
||||
decreaseValue = 1;
|
||||
prevIncreasePos = i;
|
||||
increaseValue = 1;
|
||||
}
|
||||
};
|
||||
} // namespace impl
|
||||
|
||||
LS(size_t i)
|
||||
{
|
||||
prevDecreasePos = i;
|
||||
decreaseValue = 1;
|
||||
prevIncreasePos = i;
|
||||
increaseValue = 1;
|
||||
}
|
||||
};
|
||||
} // namespace impl
|
||||
template <typename T, typename OutIter, typename Comp>
|
||||
void LongestSubsequence(std::vector<T> const & in, OutIter out, Comp cmp)
|
||||
{
|
||||
if (in.empty())
|
||||
return;
|
||||
|
||||
template <typename T, typename OutIter, typename Comp>
|
||||
void LongestSubsequence(std::vector<T> const & in, OutIter out, Comp cmp)
|
||||
std::vector<impl::LS> v;
|
||||
v.reserve(in.size());
|
||||
for (size_t i = 0; i < in.size(); ++i)
|
||||
v.push_back(impl::LS(i));
|
||||
|
||||
size_t res = 1;
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
if (in.empty())
|
||||
return;
|
||||
|
||||
std::vector<impl::LS> v;
|
||||
v.reserve(in.size());
|
||||
for (size_t i = 0; i < in.size(); ++i)
|
||||
v.push_back(impl::LS(i));
|
||||
|
||||
size_t res = 1;
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < v.size(); ++i)
|
||||
for (size_t j = i + 1; j < v.size(); ++j)
|
||||
{
|
||||
for (size_t j = i + 1; j < v.size(); ++j)
|
||||
if (cmp.Less(in[i], in[j]) && v[i].increaseValue + 1 >= v[j].increaseValue)
|
||||
{
|
||||
if (cmp.Less(in[i], in[j]) && v[i].increaseValue + 1 >= v[j].increaseValue)
|
||||
{
|
||||
v[j].increaseValue = v[i].increaseValue + 1;
|
||||
v[j].prevIncreasePos = i;
|
||||
}
|
||||
v[j].increaseValue = v[i].increaseValue + 1;
|
||||
v[j].prevIncreasePos = i;
|
||||
}
|
||||
|
||||
if (cmp.Greater(in[i], in[j]) && v[i].decreaseValue + 1 >= v[j].decreaseValue)
|
||||
{
|
||||
v[j].decreaseValue = v[i].decreaseValue + 1;
|
||||
v[j].prevDecreasePos = i;
|
||||
}
|
||||
if (cmp.Greater(in[i], in[j]) && v[i].decreaseValue + 1 >= v[j].decreaseValue)
|
||||
{
|
||||
v[j].decreaseValue = v[i].decreaseValue + 1;
|
||||
v[j].prevDecreasePos = i;
|
||||
}
|
||||
|
||||
size_t const m = std::max(v[j].increaseValue, v[j].decreaseValue);
|
||||
if (m > res)
|
||||
{
|
||||
res = m;
|
||||
pos = j;
|
||||
}
|
||||
size_t const m = std::max(v[j].increaseValue, v[j].decreaseValue);
|
||||
if (m > res)
|
||||
{
|
||||
res = m;
|
||||
pos = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool increasing = true;
|
||||
if (v[pos].increaseValue < v[pos].decreaseValue)
|
||||
increasing = false;
|
||||
bool increasing = true;
|
||||
if (v[pos].increaseValue < v[pos].decreaseValue)
|
||||
increasing = false;
|
||||
|
||||
while (res-- > 0)
|
||||
{
|
||||
*out++ = in[pos];
|
||||
while (res-- > 0)
|
||||
{
|
||||
*out++ = in[pos];
|
||||
|
||||
if (increasing)
|
||||
pos = v[pos].prevIncreasePos;
|
||||
else
|
||||
pos = v[pos].prevDecreasePos;
|
||||
}
|
||||
if (increasing)
|
||||
pos = v[pos].prevIncreasePos;
|
||||
else
|
||||
pos = v[pos].prevDecreasePos;
|
||||
}
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -20,10 +20,7 @@ struct MatchCostData
|
||||
MatchCostData() : m_A(0), m_B(0), m_Cost(0) {}
|
||||
MatchCostData(uint32_t a, uint32_t b, uint32_t cost) : m_A(a), m_B(b), m_Cost(cost) {}
|
||||
|
||||
bool operator < (MatchCostData const & o) const
|
||||
{
|
||||
return m_Cost > o.m_Cost;
|
||||
}
|
||||
bool operator<(MatchCostData const & o) const { return m_Cost > o.m_Cost; }
|
||||
};
|
||||
|
||||
template <typename PriorityQueue>
|
||||
@@ -47,8 +44,8 @@ public:
|
||||
};
|
||||
|
||||
template <typename Char, typename CostFn>
|
||||
uint32_t StringMatchCost(Char const * sA, size_t sizeA, Char const * sB, size_t sizeB,
|
||||
CostFn const & costF, uint32_t maxCost, bool bPrefixMatch = false)
|
||||
uint32_t StringMatchCost(Char const * sA, size_t sizeA, Char const * sB, size_t sizeB, CostFn const & costF,
|
||||
uint32_t maxCost, bool bPrefixMatch = false)
|
||||
{
|
||||
std::priority_queue<impl::MatchCostData, buffer_vector<impl::MatchCostData, 256>> q;
|
||||
q.push(impl::MatchCostData(0, 0, 0));
|
||||
|
||||
@@ -43,9 +43,8 @@ public:
|
||||
|
||||
std::vector<Id> GetAllIds() const
|
||||
{
|
||||
return WithIds([&](std::vector<Id> & ids) {
|
||||
m_trie.ForEachInTrie([&](Token const & /* token */, Id const & id) { ids.push_back(id); });
|
||||
});
|
||||
return WithIds([&](std::vector<Id> & ids)
|
||||
{ m_trie.ForEachInTrie([&](Token const & /* token */, Id const & id) { ids.push_back(id); }); });
|
||||
}
|
||||
|
||||
size_t GetNumDocs(int8_t lang, strings::UniString const & token, bool prefix) const
|
||||
@@ -59,11 +58,10 @@ public:
|
||||
return numDocs;
|
||||
}
|
||||
|
||||
return WithIds([&](std::vector<Id> & ids) {
|
||||
m_trie.ForEachInSubtree(
|
||||
key, [&](Token const & /* token */, Id const & id) { ids.push_back(id); });
|
||||
})
|
||||
.size();
|
||||
return WithIds([&](std::vector<Id> & ids)
|
||||
{
|
||||
m_trie.ForEachInSubtree(key, [&](Token const & /* token */, Id const & id) { ids.push_back(id); });
|
||||
}).size();
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -78,7 +76,8 @@ private:
|
||||
template <typename Doc, typename Fn>
|
||||
void ForEachToken(Id const & /*id*/, Doc const & doc, Fn && fn)
|
||||
{
|
||||
doc.ForEachToken([&](int8_t lang, Token const & token) {
|
||||
doc.ForEachToken([&](int8_t lang, Token const & token)
|
||||
{
|
||||
if (lang >= 0)
|
||||
fn(AddLang(lang, token));
|
||||
});
|
||||
|
||||
@@ -85,9 +85,9 @@ private:
|
||||
{
|
||||
public:
|
||||
explicit MemPostingsFetcher(std::map<Token, std::vector<Posting>> const & postingsByToken)
|
||||
: m_postingsByToken(postingsByToken), m_it(m_postingsByToken.begin())
|
||||
{
|
||||
}
|
||||
: m_postingsByToken(postingsByToken)
|
||||
, m_it(m_postingsByToken.begin())
|
||||
{}
|
||||
|
||||
// PostingsFetcher overrides:
|
||||
bool IsValid() const override { return m_it != m_postingsByToken.end(); }
|
||||
|
||||
@@ -29,7 +29,9 @@ class MergedPostingsListFetcher : public PostingsFetcher
|
||||
public:
|
||||
MergedPostingsListFetcher(TextIndexDictionary const & dict, TextIndexReader const & index1,
|
||||
TextIndexReader const & index2)
|
||||
: m_dict(dict), m_index1(index1), m_index2(index2)
|
||||
: m_dict(dict)
|
||||
, m_index1(index1)
|
||||
, m_index2(index2)
|
||||
{
|
||||
ReadPostings();
|
||||
}
|
||||
@@ -82,8 +84,7 @@ private:
|
||||
vector<uint32_t> m_postings;
|
||||
};
|
||||
|
||||
TextIndexDictionary MergeDictionaries(TextIndexDictionary const & dict1,
|
||||
TextIndexDictionary const & dict2)
|
||||
TextIndexDictionary MergeDictionaries(TextIndexDictionary const & dict1, TextIndexDictionary const & dict2)
|
||||
{
|
||||
vector<Token> commonTokens;
|
||||
auto const & ts1 = dict1.GetTokens();
|
||||
@@ -101,11 +102,9 @@ TextIndexDictionary MergeDictionaries(TextIndexDictionary const & dict1,
|
||||
namespace search_base
|
||||
{
|
||||
// static
|
||||
void TextIndexMerger::Merge(TextIndexReader const & index1, TextIndexReader const & index2,
|
||||
FileWriter & sink)
|
||||
void TextIndexMerger::Merge(TextIndexReader const & index1, TextIndexReader const & index2, FileWriter & sink)
|
||||
{
|
||||
TextIndexDictionary const dict =
|
||||
MergeDictionaries(index1.GetDictionary(), index2.GetDictionary());
|
||||
TextIndexDictionary const dict = MergeDictionaries(index1.GetDictionary(), index2.GetDictionary());
|
||||
|
||||
TextIndexHeader header;
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ public:
|
||||
//
|
||||
// Note that the dictionary and offsets are kept in memory during the whole
|
||||
// merging process.
|
||||
static void Merge(TextIndexReader const & index1, TextIndexReader const & index2,
|
||||
FileWriter & sink);
|
||||
static void Merge(TextIndexReader const & index1, TextIndexReader const & index2, FileWriter & sink);
|
||||
};
|
||||
} // namespace search_base
|
||||
|
||||
@@ -44,8 +44,7 @@ public:
|
||||
// |startPos| marks the start of the entire text index and is needed to compute
|
||||
// the offsets that are stored in |header|.
|
||||
template <typename Sink>
|
||||
void WritePostings(Sink & sink, uint64_t startPos, TextIndexHeader & header,
|
||||
PostingsFetcher & fetcher)
|
||||
void WritePostings(Sink & sink, uint64_t startPos, TextIndexHeader & header, PostingsFetcher & fetcher)
|
||||
{
|
||||
header.m_postingsStartsOffset = RelativePos(sink, startPos);
|
||||
// An uint32_t for each 32-bit offset and an uint32_t for the dummy entry at the end.
|
||||
@@ -58,7 +57,8 @@ void WritePostings(Sink & sink, uint64_t startPos, TextIndexHeader & header,
|
||||
{
|
||||
uint32_t last;
|
||||
// todo(@m) s/uint32_t/Posting/ ?
|
||||
auto writePostings = [&](uint32_t p) {
|
||||
auto writePostings = [&](uint32_t p)
|
||||
{
|
||||
CHECK(last == 0 || last < p, (last, p));
|
||||
uint32_t const delta = p - last;
|
||||
WriteVarUint(sink, delta);
|
||||
|
||||
@@ -50,8 +50,8 @@ public:
|
||||
return;
|
||||
CHECK_LESS(tokenId + 1, m_postingsStarts.size(), ());
|
||||
|
||||
ReaderSource<FileReader> source(m_fileReader.SubReader(
|
||||
m_postingsStarts[tokenId], m_postingsStarts[tokenId + 1] - m_postingsStarts[tokenId]));
|
||||
ReaderSource<FileReader> source(
|
||||
m_fileReader.SubReader(m_postingsStarts[tokenId], m_postingsStarts[tokenId + 1] - m_postingsStarts[tokenId]));
|
||||
|
||||
uint32_t last = 0;
|
||||
while (source.Size() > 0)
|
||||
|
||||
@@ -13,9 +13,8 @@ string DebugPrint(TextIndexVersion const & version)
|
||||
{
|
||||
case TextIndexVersion::V0: return "V0";
|
||||
}
|
||||
string ret =
|
||||
"Unknown TextIndexHeader version: " + strings::to_string(static_cast<uint8_t>(version));
|
||||
string ret = "Unknown TextIndexHeader version: " + strings::to_string(static_cast<uint8_t>(version));
|
||||
ASSERT(false, (ret));
|
||||
return ret;
|
||||
}
|
||||
} // namespace search
|
||||
} // namespace search_base
|
||||
|
||||
@@ -25,13 +25,13 @@ public:
|
||||
Data(kml::BookmarkData const & bookmarkData, std::string const & locale)
|
||||
: m_names(ExtractIndexableNames(bookmarkData, locale))
|
||||
, m_description(kml::GetDefaultStr(bookmarkData.m_description))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
template <typename Fn>
|
||||
void ForEachNameToken(Fn && fn) const
|
||||
{
|
||||
auto withDefaultLang = [&](strings::UniString const & token) {
|
||||
auto withDefaultLang = [&](strings::UniString const & token)
|
||||
{
|
||||
// Note that the Default Language here is not the same as in the kml library.
|
||||
// Bookmark search by locale is not supported so every name is stored
|
||||
// in the default branch of the search trie.
|
||||
@@ -45,9 +45,7 @@ public:
|
||||
template <typename Fn>
|
||||
void ForEachDescriptionToken(Fn && fn) const
|
||||
{
|
||||
auto withDefaultLang = [&](strings::UniString const & token) {
|
||||
fn(StringUtf8Multilang::kDefaultCode, token);
|
||||
};
|
||||
auto withDefaultLang = [&](strings::UniString const & token) { fn(StringUtf8Multilang::kDefaultCode, token); };
|
||||
|
||||
ForEachNormalizedToken(m_description, withDefaultLang);
|
||||
}
|
||||
@@ -56,8 +54,7 @@ public:
|
||||
std::string const & GetDescription() const { return m_description; }
|
||||
|
||||
private:
|
||||
std::vector<std::string> ExtractIndexableNames(kml::BookmarkData const & bookmarkData,
|
||||
std::string const & locale)
|
||||
std::vector<std::string> ExtractIndexableNames(kml::BookmarkData const & bookmarkData, std::string const & locale)
|
||||
{
|
||||
std::vector<std::string> names;
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
namespace bookmarks
|
||||
@@ -34,10 +33,7 @@ struct DocVecWrapper
|
||||
|
||||
struct RankingInfo
|
||||
{
|
||||
bool operator<(RankingInfo const & rhs) const
|
||||
{
|
||||
return m_cosineSimilarity > rhs.m_cosineSimilarity;
|
||||
}
|
||||
bool operator<(RankingInfo const & rhs) const { return m_cosineSimilarity > rhs.m_cosineSimilarity; }
|
||||
|
||||
bool operator>(RankingInfo const & rhs) const { return rhs < *this; }
|
||||
|
||||
@@ -69,9 +65,9 @@ void FillRankingInfo(QueryVec & qv, IdfMap & idfs, DocVec const & dv, RankingInf
|
||||
} // namespace
|
||||
|
||||
Processor::Processor(Emitter & emitter, base::Cancellable const & cancellable)
|
||||
: m_emitter(emitter), m_cancellable(cancellable)
|
||||
{
|
||||
}
|
||||
: m_emitter(emitter)
|
||||
, m_cancellable(cancellable)
|
||||
{}
|
||||
|
||||
void Processor::Reset()
|
||||
{
|
||||
@@ -83,7 +79,10 @@ void Processor::Reset()
|
||||
m_bookmarksInGroup.clear();
|
||||
}
|
||||
|
||||
void Processor::EnableIndexingOfDescriptions(bool enable) { m_indexDescriptions = enable; }
|
||||
void Processor::EnableIndexingOfDescriptions(bool enable)
|
||||
{
|
||||
m_indexDescriptions = enable;
|
||||
}
|
||||
|
||||
void Processor::EnableIndexingOfBookmarkGroup(GroupId const & groupId, bool enable)
|
||||
{
|
||||
@@ -98,12 +97,10 @@ void Processor::EnableIndexingOfBookmarkGroup(GroupId const & groupId, bool enab
|
||||
return;
|
||||
|
||||
for (auto const & id : m_bookmarksInGroup[groupId])
|
||||
{
|
||||
if (nowIndexable)
|
||||
AddToIndex(id);
|
||||
else
|
||||
EraseFromIndex(id);
|
||||
}
|
||||
}
|
||||
|
||||
void Processor::Add(Id const & id, Doc const & doc)
|
||||
@@ -111,14 +108,10 @@ void Processor::Add(Id const & id, Doc const & doc)
|
||||
ASSERT_EQUAL(m_docs.count(id), 0, ());
|
||||
|
||||
DocVec::Builder builder;
|
||||
doc.ForEachNameToken(
|
||||
[&](int8_t /* lang */, strings::UniString const & token) { builder.Add(token); });
|
||||
doc.ForEachNameToken([&](int8_t /* lang */, strings::UniString const & token) { builder.Add(token); });
|
||||
|
||||
if (m_indexDescriptions)
|
||||
{
|
||||
doc.ForEachDescriptionToken(
|
||||
[&](int8_t /* lang */, strings::UniString const & token) { builder.Add(token); });
|
||||
}
|
||||
doc.ForEachDescriptionToken([&](int8_t /* lang */, strings::UniString const & token) { builder.Add(token); });
|
||||
|
||||
DocVec const docVec(builder);
|
||||
|
||||
@@ -172,10 +165,7 @@ void Processor::AttachToGroup(Id const & id, GroupId const & group)
|
||||
{
|
||||
auto const it = m_idToGroup.find(id);
|
||||
if (it != m_idToGroup.end())
|
||||
{
|
||||
LOG(LWARNING, ("Tried to attach bookmark", id, "to group", group,
|
||||
"but it already belongs to group", it->second));
|
||||
}
|
||||
LOG(LWARNING, ("Tried to attach bookmark", id, "to group", group, "but it already belongs to group", it->second));
|
||||
|
||||
m_idToGroup[id] = group;
|
||||
m_bookmarksInGroup[group].insert(id);
|
||||
@@ -188,15 +178,13 @@ void Processor::DetachFromGroup(Id const & id, GroupId const & group)
|
||||
auto const it = m_idToGroup.find(id);
|
||||
if (it == m_idToGroup.end())
|
||||
{
|
||||
LOG(LWARNING, ("Tried to detach bookmark", id, "from group", group,
|
||||
"but it does not belong to any group"));
|
||||
LOG(LWARNING, ("Tried to detach bookmark", id, "from group", group, "but it does not belong to any group"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (it->second != group)
|
||||
{
|
||||
LOG(LWARNING, ("Tried to detach bookmark", id, "from group", group,
|
||||
"but it only belongs to group", it->second));
|
||||
LOG(LWARNING, ("Tried to detach bookmark", id, "from group", group, "but it only belongs to group", it->second));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -266,12 +254,14 @@ void Processor::Search(Params const & params) const
|
||||
}
|
||||
}
|
||||
|
||||
void Processor::Finish(bool cancelled) { m_emitter.Finish(cancelled); }
|
||||
void Processor::Finish(bool cancelled)
|
||||
{
|
||||
m_emitter.Finish(cancelled);
|
||||
}
|
||||
|
||||
uint64_t Processor::GetNumDocs(strings::UniString const & token, bool isPrefix) const
|
||||
{
|
||||
return base::asserted_cast<uint64_t>(
|
||||
m_index.GetNumDocs(StringUtf8Multilang::kDefaultCode, token, isPrefix));
|
||||
return base::asserted_cast<uint64_t>(m_index.GetNumDocs(StringUtf8Multilang::kDefaultCode, token, isPrefix));
|
||||
}
|
||||
|
||||
QueryVec Processor::GetQueryVec(IdfMap & idfs, QueryParams const & params) const
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
|
||||
namespace base
|
||||
{
|
||||
class Cancellable;
|
||||
@@ -81,9 +80,8 @@ private:
|
||||
FillRequestFromToken(token, request);
|
||||
request.m_langs.insert(StringUtf8Multilang::kDefaultCode);
|
||||
|
||||
MatchFeaturesInTrie(
|
||||
request, m_index.GetRootIterator(), [](Id const & /* id */) { return true; } /* filter */,
|
||||
std::forward<Fn>(fn));
|
||||
MatchFeaturesInTrie(request, m_index.GetRootIterator(), [](Id const & /* id */) { return true; } /* filter */,
|
||||
std::forward<Fn>(fn));
|
||||
}
|
||||
|
||||
QueryVec GetQueryVec(IdfMap & idfs, QueryParams const & params) const;
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include "indexer/ftypes_matcher.hpp"
|
||||
#include "indexer/search_string_utils.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
using namespace std;
|
||||
@@ -37,9 +36,7 @@ CBV CategoriesCache::Load(MwmContext const & context) const
|
||||
m_categories.ForEach([&request, &c](uint32_t const type)
|
||||
{
|
||||
c.ForEachInSubtree([&](uint32_t descendantType)
|
||||
{
|
||||
request.m_categories.emplace_back(FeatureTypeToString(c.GetIndexForType(descendantType)));
|
||||
}, type);
|
||||
{ request.m_categories.emplace_back(FeatureTypeToString(c.GetIndexForType(descendantType))); }, type);
|
||||
});
|
||||
|
||||
Retrieval retrieval(context, m_cancellable);
|
||||
@@ -49,47 +46,39 @@ CBV CategoriesCache::Load(MwmContext const & context) const
|
||||
// StreetsCache ------------------------------------------------------------------------------------
|
||||
StreetsCache::StreetsCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsStreetOrSquareChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// SuburbsCache ------------------------------------------------------------------------------------
|
||||
SuburbsCache::SuburbsCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsSuburbChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
// VillagesCache -----------------------------------------------------------------------------------
|
||||
VillagesCache::VillagesCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsVillageChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// CountriesCache ----------------------------------------------------------------------------------
|
||||
CountriesCache::CountriesCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsCountryChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// StatesCache -------------------------------------------------------------------------------------
|
||||
StatesCache::StatesCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsStateChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// CitiesTownsOrVillagesCache ----------------------------------------------------------------------
|
||||
CitiesTownsOrVillagesCache::CitiesTownsOrVillagesCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsCityTownOrVillageChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// HotelsCache -------------------------------------------------------------------------------------
|
||||
HotelsCache::HotelsCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsHotelChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
// FoodCache ---------------------------------------------------------------------------------------
|
||||
FoodCache::FoodCache(base::Cancellable const & cancellable)
|
||||
: CategoriesCache(ftypes::IsEatChecker::Instance(), cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
} // namespace search
|
||||
|
||||
@@ -18,8 +18,7 @@ class CategoriesCache
|
||||
{
|
||||
public:
|
||||
template <typename TypesSource>
|
||||
CategoriesCache(TypesSource const & source, base::Cancellable const & cancellable)
|
||||
: m_cancellable(cancellable)
|
||||
CategoriesCache(TypesSource const & source, base::Cancellable const & cancellable) : m_cancellable(cancellable)
|
||||
{
|
||||
source.ForEachType([this](uint32_t type) { m_categories.Add(type); });
|
||||
}
|
||||
|
||||
@@ -21,7 +21,10 @@ CBV const & CBV::GetFull()
|
||||
|
||||
CBV::CBV(unique_ptr<coding::CompressedBitVector> p) : m_p(std::move(p)) {}
|
||||
|
||||
CBV::CBV(CBV && cbv) : m_p(std::move(cbv.m_p)), m_isFull(cbv.m_isFull) { cbv.m_isFull = false; }
|
||||
CBV::CBV(CBV && cbv) : m_p(std::move(cbv.m_p)), m_isFull(cbv.m_isFull)
|
||||
{
|
||||
cbv.m_isFull = false;
|
||||
}
|
||||
|
||||
CBV::CBV(bool full) : m_isFull(full) {}
|
||||
|
||||
|
||||
@@ -26,8 +26,7 @@ using namespace std;
|
||||
// CitiesBoundariesTable::Boundaries ---------------------------------------------------------------
|
||||
bool CitiesBoundariesTable::Boundaries::HasPoint(m2::PointD const & p) const
|
||||
{
|
||||
return any_of(m_boundaries.begin(), m_boundaries.end(),
|
||||
[&](CityBoundary const & b) { return b.HasPoint(p, m_eps); });
|
||||
return any_of(m_boundaries.begin(), m_boundaries.end(), [&](CityBoundary const & b) { return b.HasPoint(p, m_eps); });
|
||||
}
|
||||
|
||||
std::string DebugPrint(CitiesBoundariesTable::Boundaries const & boundaries)
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace search
|
||||
{
|
||||
class CitiesBoundariesTable
|
||||
{
|
||||
friend void GetCityBoundariesInRectForTesting(CitiesBoundariesTable const &,
|
||||
m2::RectD const & rect,
|
||||
friend void GetCityBoundariesInRectForTesting(CitiesBoundariesTable const &, m2::RectD const & rect,
|
||||
std::vector<uint32_t> & featureIds);
|
||||
|
||||
public:
|
||||
@@ -26,10 +25,8 @@ public:
|
||||
public:
|
||||
Boundaries() = default;
|
||||
|
||||
Boundaries(std::vector<indexer::CityBoundary> const & boundaries, double eps)
|
||||
: m_boundaries(boundaries), m_eps(eps)
|
||||
{
|
||||
}
|
||||
Boundaries(std::vector<indexer::CityBoundary> const & boundaries, double eps) : m_boundaries(boundaries), m_eps(eps)
|
||||
{}
|
||||
|
||||
// Returns true iff |p| is inside any of the regions bounded by
|
||||
// |*this|.
|
||||
@@ -48,7 +45,8 @@ public:
|
||||
|
||||
size_t GetCount() const { return m_boundaries.size(); }
|
||||
|
||||
template <class FnT> void ForEachBoundary(FnT && fn) const
|
||||
template <class FnT>
|
||||
void ForEachBoundary(FnT && fn) const
|
||||
{
|
||||
for (size_t i = 0; i < m_boundaries.size(); ++i)
|
||||
fn(m_boundaries[i], i);
|
||||
|
||||
@@ -10,16 +10,12 @@ CityFinder::CityFinder(DataSource const & dataSource)
|
||||
: m_unusedBoundaries(dataSource)
|
||||
, m_unusedCache(m_cancellable)
|
||||
, m_finder(dataSource, m_unusedBoundaries, m_unusedCache)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
string CityFinder::GetCityName(m2::PointD const & p, int8_t lang)
|
||||
{
|
||||
string_view city;
|
||||
m_finder.GetLocality(p, [&](LocalityItem const & item)
|
||||
{
|
||||
item.GetSpecifiedOrDefaultName(lang, city);
|
||||
});
|
||||
m_finder.GetLocality(p, [&](LocalityItem const & item) { item.GetSpecifiedOrDefaultName(lang, city); });
|
||||
|
||||
// Return string, because m_finder.GetLocality() is not persistent.
|
||||
return std::string(city);
|
||||
|
||||
@@ -22,16 +22,18 @@ namespace cuisine_filter
|
||||
Description::Description(FeatureType & ft)
|
||||
{
|
||||
m_types.clear();
|
||||
ft.ForEachType([this](uint32_t t) {
|
||||
ft.ForEachType([this](uint32_t t)
|
||||
{
|
||||
if (ftypes::IsCuisineChecker::Instance()(t))
|
||||
m_types.push_back(t);
|
||||
});
|
||||
}
|
||||
|
||||
CuisineFilter::ScopedFilter::ScopedFilter(MwmSet::MwmId const & mwmId,
|
||||
Descriptions const & descriptions,
|
||||
CuisineFilter::ScopedFilter::ScopedFilter(MwmSet::MwmId const & mwmId, Descriptions const & descriptions,
|
||||
vector<uint32_t> const & types)
|
||||
: m_mwmId(mwmId), m_descriptions(descriptions), m_types(types)
|
||||
: m_mwmId(mwmId)
|
||||
, m_descriptions(descriptions)
|
||||
, m_types(types)
|
||||
{
|
||||
sort(m_types.begin(), m_types.end());
|
||||
}
|
||||
@@ -41,34 +43,33 @@ bool CuisineFilter::ScopedFilter::Matches(FeatureID const & fid) const
|
||||
if (fid.m_mwmId != m_mwmId)
|
||||
return false;
|
||||
|
||||
auto it = lower_bound(
|
||||
m_descriptions.begin(), m_descriptions.end(), make_pair(fid.m_index, Description{}),
|
||||
[](pair<uint32_t, Description> const & lhs, pair<uint32_t, Description> const & rhs) {
|
||||
return lhs.first < rhs.first;
|
||||
});
|
||||
auto it = lower_bound(m_descriptions.begin(), m_descriptions.end(), make_pair(fid.m_index, Description{}),
|
||||
[](pair<uint32_t, Description> const & lhs, pair<uint32_t, Description> const & rhs)
|
||||
{ return lhs.first < rhs.first; });
|
||||
if (it == m_descriptions.end() || it->first != fid.m_index)
|
||||
return false;
|
||||
|
||||
for (auto const t : it->second.m_types)
|
||||
{
|
||||
if (binary_search(m_types.begin(), m_types.end(), t))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// CuisineFilter ------------------------------------------------------------------------------------
|
||||
CuisineFilter::CuisineFilter(FoodCache & food) : m_food(food) {}
|
||||
|
||||
unique_ptr<CuisineFilter::ScopedFilter> CuisineFilter::MakeScopedFilter(
|
||||
MwmContext const & context, vector<uint32_t> const & types)
|
||||
unique_ptr<CuisineFilter::ScopedFilter> CuisineFilter::MakeScopedFilter(MwmContext const & context,
|
||||
vector<uint32_t> const & types)
|
||||
{
|
||||
if (types.empty())
|
||||
return {};
|
||||
return make_unique<ScopedFilter>(context.GetId(), GetDescriptions(context), types);
|
||||
}
|
||||
|
||||
void CuisineFilter::ClearCaches() { m_descriptions.clear(); }
|
||||
void CuisineFilter::ClearCaches()
|
||||
{
|
||||
m_descriptions.clear();
|
||||
}
|
||||
|
||||
CuisineFilter::Descriptions const & CuisineFilter::GetDescriptions(MwmContext const & context)
|
||||
{
|
||||
@@ -82,7 +83,8 @@ CuisineFilter::Descriptions const & CuisineFilter::GetDescriptions(MwmContext co
|
||||
|
||||
auto const food = m_food.Get(context);
|
||||
auto & descriptions = m_descriptions[mwmId];
|
||||
food.ForEach([&descriptions, &context](uint64_t bit) {
|
||||
food.ForEach([&descriptions, &context](uint64_t bit)
|
||||
{
|
||||
auto const id = base::asserted_cast<uint32_t>(bit);
|
||||
auto ft = context.GetFeature(id);
|
||||
if (ft)
|
||||
|
||||
@@ -32,8 +32,7 @@ public:
|
||||
class ScopedFilter
|
||||
{
|
||||
public:
|
||||
ScopedFilter(MwmSet::MwmId const & mwmId, Descriptions const & descriptions,
|
||||
std::vector<uint32_t> const & types);
|
||||
ScopedFilter(MwmSet::MwmId const & mwmId, Descriptions const & descriptions, std::vector<uint32_t> const & types);
|
||||
|
||||
bool Matches(FeatureID const & fid) const;
|
||||
|
||||
@@ -45,8 +44,7 @@ public:
|
||||
|
||||
CuisineFilter(FoodCache & food);
|
||||
|
||||
std::unique_ptr<ScopedFilter> MakeScopedFilter(MwmContext const & context,
|
||||
std::vector<uint32_t> const & types);
|
||||
std::unique_ptr<ScopedFilter> MakeScopedFilter(MwmContext const & context, std::vector<uint32_t> const & types);
|
||||
|
||||
void ClearCaches();
|
||||
|
||||
|
||||
@@ -8,29 +8,12 @@ namespace search
|
||||
{
|
||||
DisplayedCategories::DisplayedCategories(CategoriesHolder const & holder) : m_holder(holder)
|
||||
{
|
||||
m_keys = {"category_eat",
|
||||
"category_hotel",
|
||||
"category_food",
|
||||
"category_tourism",
|
||||
"category_wifi",
|
||||
"category_transport",
|
||||
"category_fuel",
|
||||
"category_parking",
|
||||
"category_shopping",
|
||||
"category_secondhand",
|
||||
"category_atm",
|
||||
"category_nightlife",
|
||||
"category_children",
|
||||
"category_bank",
|
||||
"category_entertainment",
|
||||
"category_water",
|
||||
"category_hospital",
|
||||
"category_pharmacy",
|
||||
"category_recycling",
|
||||
"category_rv",
|
||||
"category_police",
|
||||
"category_toilet",
|
||||
"category_post"};
|
||||
m_keys = {"category_eat", "category_hotel", "category_food", "category_tourism",
|
||||
"category_wifi", "category_transport", "category_fuel", "category_parking",
|
||||
"category_shopping", "category_secondhand", "category_atm", "category_nightlife",
|
||||
"category_children", "category_bank", "category_entertainment", "category_water",
|
||||
"category_hospital", "category_pharmacy", "category_recycling", "category_rv",
|
||||
"category_police", "category_toilet", "category_post"};
|
||||
}
|
||||
|
||||
void DisplayedCategories::Modify(CategoriesModifier & modifier)
|
||||
@@ -38,5 +21,8 @@ void DisplayedCategories::Modify(CategoriesModifier & modifier)
|
||||
modifier.Modify(m_keys);
|
||||
}
|
||||
|
||||
std::vector<std::string> const & DisplayedCategories::GetKeys() const { return m_keys; }
|
||||
std::vector<std::string> const & DisplayedCategories::GetKeys() const
|
||||
{
|
||||
return m_keys;
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
return CategoriesHolder::MapLocaleToInteger(locale) != CategoriesHolder::kUnsupportedLocaleCode;
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
CategoriesHolder const & m_holder;
|
||||
Keys m_keys;
|
||||
};
|
||||
|
||||
@@ -15,15 +15,16 @@ void SortAndMerge(vector<strings::UniString> tokens, vector<TokenFrequencyPair>
|
||||
ASSERT(tfs.empty(), ());
|
||||
sort(tokens.begin(), tokens.end());
|
||||
for (size_t i = 0; i < tokens.size(); ++i)
|
||||
{
|
||||
if (tfs.empty() || tfs.back().m_token != tokens[i])
|
||||
tfs.emplace_back(tokens[i], 1 /* frequency */);
|
||||
else
|
||||
++tfs.back().m_frequency;
|
||||
}
|
||||
}
|
||||
|
||||
double GetTfIdf(double tf, double idf) { return tf * idf; }
|
||||
double GetTfIdf(double tf, double idf)
|
||||
{
|
||||
return tf * idf;
|
||||
}
|
||||
|
||||
double GetWeightImpl(IdfMap & idfs, TokenFrequencyPair const & tf, bool isPrefix)
|
||||
{
|
||||
@@ -46,15 +47,11 @@ double SqrL2(IdfMap & idfs, vector<TokenFrequencyPair> const & tfs)
|
||||
}
|
||||
|
||||
// Computes squared L2 norm of vector of tokens + prefix token.
|
||||
double SqrL2(IdfMap & idfs, vector<TokenFrequencyPair> const & tfs,
|
||||
optional<strings::UniString> const & prefix)
|
||||
double SqrL2(IdfMap & idfs, vector<TokenFrequencyPair> const & tfs, optional<strings::UniString> const & prefix)
|
||||
{
|
||||
auto result = SqrL2(idfs, tfs);
|
||||
if (prefix)
|
||||
{
|
||||
result +=
|
||||
GetSqrWeightImpl(idfs, TokenFrequencyPair(*prefix, 1 /* frequency */), true /* isPrefix */);
|
||||
}
|
||||
result += GetSqrWeightImpl(idfs, TokenFrequencyPair(*prefix, 1 /* frequency */), true /* isPrefix */);
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
@@ -81,9 +78,15 @@ string DebugPrint(TokenFrequencyPair const & tf)
|
||||
}
|
||||
|
||||
// DocVec ------------------------------------------------------------------------------------------
|
||||
DocVec::DocVec(Builder const & builder) { SortAndMerge(builder.m_tokens, m_tfs); }
|
||||
DocVec::DocVec(Builder const & builder)
|
||||
{
|
||||
SortAndMerge(builder.m_tokens, m_tfs);
|
||||
}
|
||||
|
||||
double DocVec::Norm(IdfMap & idfs) const { return SqrL2(idfs, m_tfs); }
|
||||
double DocVec::Norm(IdfMap & idfs) const
|
||||
{
|
||||
return SqrL2(idfs, m_tfs);
|
||||
}
|
||||
|
||||
strings::UniString const & DocVec::GetToken(size_t i) const
|
||||
{
|
||||
@@ -104,8 +107,7 @@ double DocVec::GetWeight(IdfMap & idfs, size_t i) const
|
||||
}
|
||||
|
||||
// QueryVec ----------------------------------------------------------------------------------------
|
||||
QueryVec::QueryVec(IdfMap & idfs, Builder const & builder)
|
||||
: m_idfs(&idfs), m_prefix(builder.m_prefix)
|
||||
QueryVec::QueryVec(IdfMap & idfs, Builder const & builder) : m_idfs(&idfs), m_prefix(builder.m_prefix)
|
||||
{
|
||||
SortAndMerge(builder.m_tokens, m_tfs);
|
||||
}
|
||||
@@ -212,7 +214,10 @@ double QueryVec::Similarity(IdfMap & docIdfs, DocVec const & rhs)
|
||||
return max(similarityWithPrefix, similarityNoPrefix);
|
||||
}
|
||||
|
||||
double QueryVec::Norm() { return SqrL2(*m_idfs, m_tfs, m_prefix); }
|
||||
double QueryVec::Norm()
|
||||
{
|
||||
return SqrL2(*m_idfs, m_tfs, m_prefix);
|
||||
}
|
||||
|
||||
double QueryVec::GetFullTokenWeight(size_t i)
|
||||
{
|
||||
@@ -223,7 +228,6 @@ double QueryVec::GetFullTokenWeight(size_t i)
|
||||
double QueryVec::GetPrefixTokenWeight()
|
||||
{
|
||||
ASSERT(m_prefix, ());
|
||||
return GetWeightImpl(*m_idfs, TokenFrequencyPair(*m_prefix, 1 /* frequency */),
|
||||
true /* isPrefix */);
|
||||
return GetWeightImpl(*m_idfs, TokenFrequencyPair(*m_prefix, 1 /* frequency */), true /* isPrefix */);
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -23,10 +23,9 @@ struct TokenFrequencyPair
|
||||
TokenFrequencyPair() = default;
|
||||
|
||||
template <typename Token>
|
||||
TokenFrequencyPair(Token && token, uint64_t frequency)
|
||||
: m_token(std::forward<Token>(token)), m_frequency(frequency)
|
||||
{
|
||||
}
|
||||
TokenFrequencyPair(Token && token, uint64_t frequency) : m_token(std::forward<Token>(token))
|
||||
, m_frequency(frequency)
|
||||
{}
|
||||
|
||||
bool operator<(TokenFrequencyPair const & rhs) const;
|
||||
|
||||
@@ -72,10 +71,7 @@ public:
|
||||
bool Empty() const { return m_tfs.empty(); }
|
||||
|
||||
private:
|
||||
friend std::string DebugPrint(DocVec const & dv)
|
||||
{
|
||||
return "DocVec " + ::DebugPrint(dv.m_tfs);
|
||||
}
|
||||
friend std::string DebugPrint(DocVec const & dv) { return "DocVec " + ::DebugPrint(dv.m_tfs); }
|
||||
|
||||
std::vector<TokenFrequencyPair> m_tfs;
|
||||
};
|
||||
|
||||
@@ -19,12 +19,10 @@
|
||||
namespace
|
||||
{
|
||||
/// @todo Can't change on string_view now, because of unordered_map<string> synonyms.
|
||||
bool GetGroupCountryIdFromFeature(storage::Storage const & storage, FeatureType & ft,
|
||||
std::string & name)
|
||||
bool GetGroupCountryIdFromFeature(storage::Storage const & storage, FeatureType & ft, std::string & name)
|
||||
{
|
||||
auto const & synonyms = storage.GetCountryNameSynonyms();
|
||||
int8_t const langIndices[] = {StringUtf8Multilang::kEnglishCode,
|
||||
StringUtf8Multilang::kDefaultCode,
|
||||
int8_t const langIndices[] = {StringUtf8Multilang::kEnglishCode, StringUtf8Multilang::kDefaultCode,
|
||||
StringUtf8Multilang::kInternationalCode};
|
||||
|
||||
for (auto const langIndex : langIndices)
|
||||
@@ -49,8 +47,7 @@ bool GetGroupCountryIdFromFeature(storage::Storage const & storage, FeatureType
|
||||
|
||||
namespace search
|
||||
{
|
||||
DownloaderSearchCallback::DownloaderSearchCallback(Delegate & delegate,
|
||||
DataSource const & dataSource,
|
||||
DownloaderSearchCallback::DownloaderSearchCallback(Delegate & delegate, DataSource const & dataSource,
|
||||
storage::CountryInfoGetter const & infoGetter,
|
||||
storage::Storage const & storage,
|
||||
storage::DownloaderSearchParams params)
|
||||
@@ -59,8 +56,7 @@ DownloaderSearchCallback::DownloaderSearchCallback(Delegate & delegate,
|
||||
, m_infoGetter(infoGetter)
|
||||
, m_storage(storage)
|
||||
, m_params(std::move(params))
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void DownloaderSearchCallback::operator()(search::Results const & results)
|
||||
{
|
||||
@@ -90,8 +86,7 @@ void DownloaderSearchCallback::operator()(search::Results const & results)
|
||||
std::string groupFeatureName;
|
||||
if (GetGroupCountryIdFromFeature(m_storage, *ft, groupFeatureName))
|
||||
{
|
||||
storage::DownloaderSearchResult downloaderResult(groupFeatureName,
|
||||
result.GetString() /* m_matchedName */);
|
||||
storage::DownloaderSearchResult downloaderResult(groupFeatureName, result.GetString() /* m_matchedName */);
|
||||
if (uniqueResults.find(downloaderResult) == uniqueResults.end())
|
||||
{
|
||||
uniqueResults.insert(downloaderResult);
|
||||
@@ -106,8 +101,7 @@ void DownloaderSearchCallback::operator()(search::Results const & results)
|
||||
if (countryId == storage::kInvalidCountryId)
|
||||
continue;
|
||||
|
||||
storage::DownloaderSearchResult downloaderResult(countryId,
|
||||
result.GetString() /* m_matchedName */);
|
||||
storage::DownloaderSearchResult downloaderResult(countryId, result.GetString() /* m_matchedName */);
|
||||
if (uniqueResults.find(downloaderResult) == uniqueResults.end())
|
||||
{
|
||||
uniqueResults.insert(downloaderResult);
|
||||
@@ -119,8 +113,6 @@ void DownloaderSearchCallback::operator()(search::Results const & results)
|
||||
downloaderSearchResults.m_endMarker = results.IsEndMarker();
|
||||
|
||||
m_delegate.RunUITask([onResults = m_params.m_onResults, results = std::move(downloaderSearchResults)]() mutable
|
||||
{
|
||||
onResults(std::move(results));
|
||||
});
|
||||
{ onResults(std::move(results)); });
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -31,8 +31,7 @@ public:
|
||||
};
|
||||
|
||||
DownloaderSearchCallback(Delegate & delegate, DataSource const & dataSource,
|
||||
storage::CountryInfoGetter const & infoGetter,
|
||||
storage::Storage const & storage,
|
||||
storage::CountryInfoGetter const & infoGetter, storage::Storage const & storage,
|
||||
storage::DownloaderSearchParams params);
|
||||
|
||||
void operator()(search::Results const & results);
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
|
||||
namespace search
|
||||
{
|
||||
uint8_t DummyRankTable::Get(uint64_t /* i */) const { return kNoRank; }
|
||||
uint8_t DummyRankTable::Get(uint64_t /* i */) const
|
||||
{
|
||||
return kNoRank;
|
||||
}
|
||||
|
||||
uint64_t DummyRankTable::Size() const
|
||||
{
|
||||
|
||||
@@ -36,8 +36,7 @@ string EditorDelegate::GetOriginalFeatureStreet(FeatureID const & fid) const
|
||||
return coder.GetOriginalFeatureStreetName(fid);
|
||||
}
|
||||
|
||||
void EditorDelegate::ForEachFeatureAtPoint(osm::Editor::FeatureTypeFn && fn,
|
||||
m2::PointD const & point) const
|
||||
void EditorDelegate::ForEachFeatureAtPoint(osm::Editor::FeatureTypeFn && fn, m2::PointD const & point) const
|
||||
{
|
||||
auto const kToleranceMeters = 1e-2;
|
||||
indexer::ForEachFeatureAtPoint(m_dataSource, std::move(fn), point, kToleranceMeters);
|
||||
|
||||
@@ -18,11 +18,9 @@ public:
|
||||
|
||||
// osm::Editor::Delegate overrides:
|
||||
MwmSet::MwmId GetMwmIdByMapName(std::string const & name) const override;
|
||||
std::unique_ptr<osm::EditableMapObject> GetOriginalMapObject(
|
||||
FeatureID const & fid) const override;
|
||||
std::unique_ptr<osm::EditableMapObject> GetOriginalMapObject(FeatureID const & fid) const override;
|
||||
std::string GetOriginalFeatureStreet(FeatureID const & fid) const override;
|
||||
void ForEachFeatureAtPoint(osm::Editor::FeatureTypeFn && fn,
|
||||
m2::PointD const & point) const override;
|
||||
void ForEachFeatureAtPoint(osm::Editor::FeatureTypeFn && fn, m2::PointD const & point) const override;
|
||||
|
||||
private:
|
||||
DataSource const & m_dataSource;
|
||||
|
||||
@@ -37,8 +37,8 @@ public:
|
||||
if (m_prevEmitSize == newCount && !force)
|
||||
return;
|
||||
|
||||
LOG(LINFO, ("Emitting a new batch of results:", newCount - m_prevEmitSize, ",",
|
||||
m_timer.ElapsedMilliseconds(), "ms since the search has started."));
|
||||
LOG(LINFO, ("Emitting a new batch of results:", newCount - m_prevEmitSize, ",", m_timer.ElapsedMilliseconds(),
|
||||
"ms since the search has started."));
|
||||
m_prevEmitSize = m_results.GetCount();
|
||||
|
||||
m_onResults(m_results);
|
||||
|
||||
@@ -74,10 +74,7 @@ void ProcessorHandle::Detach()
|
||||
// Engine::Params ----------------------------------------------------------------------------------
|
||||
Engine::Params::Params() : m_locale("en"), m_numThreads(1) {}
|
||||
|
||||
Engine::Params::Params(string const & locale, size_t numThreads)
|
||||
: m_locale(locale), m_numThreads(numThreads)
|
||||
{
|
||||
}
|
||||
Engine::Params::Params(string const & locale, size_t numThreads) : m_locale(locale), m_numThreads(numThreads) {}
|
||||
|
||||
// Engine ------------------------------------------------------------------------------------------
|
||||
Engine::Engine(DataSource & dataSource, CategoriesHolder const & categories,
|
||||
@@ -121,19 +118,19 @@ weak_ptr<ProcessorHandle> Engine::Search(SearchParams params)
|
||||
{
|
||||
shared_ptr<ProcessorHandle> handle(new ProcessorHandle());
|
||||
PostMessage(Message::TYPE_TASK, [this, params = std::move(params), handle](Processor & processor)
|
||||
{
|
||||
DoSearch(std::move(params), handle, processor);
|
||||
});
|
||||
{ DoSearch(std::move(params), handle, processor); });
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Engine::SetLocale(string const & locale)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[locale](Processor & processor) { processor.SetPreferredLocale(locale); });
|
||||
PostMessage(Message::TYPE_BROADCAST, [locale](Processor & processor) { processor.SetPreferredLocale(locale); });
|
||||
}
|
||||
|
||||
size_t Engine::GetNumThreads() const { return m_threads.size(); }
|
||||
size_t Engine::GetNumThreads() const
|
||||
{
|
||||
return m_threads.size();
|
||||
}
|
||||
|
||||
void Engine::ClearCaches()
|
||||
{
|
||||
@@ -142,75 +139,61 @@ void Engine::ClearCaches()
|
||||
|
||||
void Engine::CacheWorldLocalities()
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[](Processor & processor) { processor.CacheWorldLocalities(); });
|
||||
PostMessage(Message::TYPE_BROADCAST, [](Processor & processor) { processor.CacheWorldLocalities(); });
|
||||
}
|
||||
|
||||
void Engine::LoadCitiesBoundaries()
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[](Processor & processor) { processor.LoadCitiesBoundaries(); });
|
||||
PostMessage(Message::TYPE_BROADCAST, [](Processor & processor) { processor.LoadCitiesBoundaries(); });
|
||||
}
|
||||
|
||||
void Engine::LoadCountriesTree()
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[](Processor & processor) { processor.LoadCountriesTree(); });
|
||||
PostMessage(Message::TYPE_BROADCAST, [](Processor & processor) { processor.LoadCountriesTree(); });
|
||||
}
|
||||
|
||||
void Engine::EnableIndexingOfBookmarksDescriptions(bool enable)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST, [enable](Processor & processor) {
|
||||
processor.EnableIndexingOfBookmarksDescriptions(enable);
|
||||
});
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[enable](Processor & processor) { processor.EnableIndexingOfBookmarksDescriptions(enable); });
|
||||
}
|
||||
|
||||
void Engine::EnableIndexingOfBookmarkGroup(bookmarks::GroupId const & groupId, bool enable)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST, [=](Processor & processor) {
|
||||
processor.EnableIndexingOfBookmarkGroup(groupId, enable);
|
||||
});
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[=](Processor & processor) { processor.EnableIndexingOfBookmarkGroup(groupId, enable); });
|
||||
}
|
||||
|
||||
void Engine::ResetBookmarks()
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST, [](Processor & processor) {
|
||||
processor.ResetBookmarks();
|
||||
});
|
||||
PostMessage(Message::TYPE_BROADCAST, [](Processor & processor) { processor.ResetBookmarks(); });
|
||||
}
|
||||
|
||||
void Engine::OnBookmarksCreated(vector<pair<bookmarks::Id, bookmarks::Doc>> const & marks)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[marks](Processor & processor) { processor.OnBookmarksCreated(marks); });
|
||||
PostMessage(Message::TYPE_BROADCAST, [marks](Processor & processor) { processor.OnBookmarksCreated(marks); });
|
||||
}
|
||||
|
||||
void Engine::OnBookmarksUpdated(vector<pair<bookmarks::Id, bookmarks::Doc>> const & marks)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[marks](Processor & processor) { processor.OnBookmarksUpdated(marks); });
|
||||
PostMessage(Message::TYPE_BROADCAST, [marks](Processor & processor) { processor.OnBookmarksUpdated(marks); });
|
||||
}
|
||||
|
||||
void Engine::OnBookmarksDeleted(vector<bookmarks::Id> const & marks)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST, [marks](Processor & processor) { processor.OnBookmarksDeleted(marks); });
|
||||
}
|
||||
|
||||
void Engine::OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId, vector<bookmarks::Id> const & marks)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[marks](Processor & processor) { processor.OnBookmarksDeleted(marks); });
|
||||
[groupId, marks](Processor & processor) { processor.OnBookmarksAttachedToGroup(groupId, marks); });
|
||||
}
|
||||
|
||||
void Engine::OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId,
|
||||
vector<bookmarks::Id> const & marks)
|
||||
void Engine::OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId, vector<bookmarks::Id> const & marks)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST, [groupId, marks](Processor & processor) {
|
||||
processor.OnBookmarksAttachedToGroup(groupId, marks);
|
||||
});
|
||||
}
|
||||
|
||||
void Engine::OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId,
|
||||
vector<bookmarks::Id> const & marks)
|
||||
{
|
||||
PostMessage(Message::TYPE_BROADCAST, [groupId, marks](Processor & processor) {
|
||||
processor.OnBookmarksDetachedFromGroup(groupId, marks);
|
||||
});
|
||||
PostMessage(Message::TYPE_BROADCAST,
|
||||
[groupId, marks](Processor & processor) { processor.OnBookmarksDetachedFromGroup(groupId, marks); });
|
||||
}
|
||||
|
||||
void Engine::MainLoop(Context & context)
|
||||
@@ -222,10 +205,7 @@ void Engine::MainLoop(Context & context)
|
||||
|
||||
{
|
||||
unique_lock<mutex> lock(m_mu);
|
||||
m_cv.wait(lock, [&]()
|
||||
{
|
||||
return m_shutdown || !m_messages.empty() || !context.m_messages.empty();
|
||||
});
|
||||
m_cv.wait(lock, [&]() { return m_shutdown || !m_messages.empty() || !context.m_messages.empty(); });
|
||||
|
||||
if (m_shutdown)
|
||||
break;
|
||||
@@ -283,10 +263,7 @@ void Engine::DoSearch(SearchParams params, shared_ptr<ProcessorHandle> handle, P
|
||||
{
|
||||
LOG(LINFO, ("Search started:", params.m_mode, params.m_viewport));
|
||||
base::Timer timer;
|
||||
SCOPE_GUARD(printDuration, [&timer]()
|
||||
{
|
||||
LOG(LINFO, ("Search ended in", timer.ElapsedMilliseconds(), "ms."));
|
||||
});
|
||||
SCOPE_GUARD(printDuration, [&timer]() { LOG(LINFO, ("Search ended in", timer.ElapsedMilliseconds(), "ms.")); });
|
||||
|
||||
processor.Reset();
|
||||
handle->Attach(processor);
|
||||
|
||||
@@ -83,8 +83,8 @@ public:
|
||||
};
|
||||
|
||||
// Doesn't take ownership of dataSource and categories.
|
||||
Engine(DataSource & dataSource, CategoriesHolder const & categories,
|
||||
storage::CountryInfoGetter const & infoGetter, Params const & params);
|
||||
Engine(DataSource & dataSource, CategoriesHolder const & categories, storage::CountryInfoGetter const & infoGetter,
|
||||
Params const & params);
|
||||
~Engine();
|
||||
|
||||
// Posts search request to the queue and returns its handle.
|
||||
@@ -117,10 +117,8 @@ public:
|
||||
void OnBookmarksCreated(std::vector<std::pair<bookmarks::Id, bookmarks::Doc>> const & marks);
|
||||
void OnBookmarksUpdated(std::vector<std::pair<bookmarks::Id, bookmarks::Doc>> const & marks);
|
||||
void OnBookmarksDeleted(std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId,
|
||||
std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId,
|
||||
std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId, std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId, std::vector<bookmarks::Id> const & marks);
|
||||
|
||||
private:
|
||||
struct Message
|
||||
@@ -134,7 +132,9 @@ private:
|
||||
};
|
||||
|
||||
template <typename Gn>
|
||||
Message(Type type, Gn && gn) : m_type(type), m_fn(std::forward<Gn>(gn)) {}
|
||||
Message(Type type, Gn && gn) : m_type(type)
|
||||
, m_fn(std::forward<Gn>(gn))
|
||||
{}
|
||||
|
||||
void operator()(Processor & processor) { m_fn(processor); }
|
||||
|
||||
|
||||
@@ -43,8 +43,8 @@ bool FindLangIndex(trie::Iterator<ValueList> const & trieRoot, uint8_t lang, uin
|
||||
}
|
||||
|
||||
template <typename ValueList, typename DFA, typename ToDo>
|
||||
bool MatchInTrie(trie::Iterator<ValueList> const & trieRoot, strings::UniChar const * rootPrefix,
|
||||
size_t rootPrefixSize, DFA const & dfa, ToDo && toDo)
|
||||
bool MatchInTrie(trie::Iterator<ValueList> const & trieRoot, strings::UniChar const * rootPrefix, size_t rootPrefixSize,
|
||||
DFA const & dfa, ToDo && toDo)
|
||||
{
|
||||
using TrieDFAIt = std::shared_ptr<trie::Iterator<ValueList>>;
|
||||
using DFAIt = typename DFA::Iterator;
|
||||
@@ -72,8 +72,7 @@ bool MatchInTrie(trie::Iterator<ValueList> const & trieRoot, strings::UniChar co
|
||||
|
||||
if (dfaIt.Accepts())
|
||||
{
|
||||
trieIt->m_values.ForEach(
|
||||
[&dfaIt, &toDo](auto const & v) { toDo(v, dfaIt.ErrorsMade() == 0); });
|
||||
trieIt->m_values.ForEach([&dfaIt, &toDo](auto const & v) { toDo(v, dfaIt.ErrorsMade() == 0); });
|
||||
found = true;
|
||||
}
|
||||
|
||||
@@ -102,10 +101,7 @@ class OffsetIntersector
|
||||
std::unique_ptr<Values> m_values;
|
||||
|
||||
public:
|
||||
explicit OffsetIntersector(Filter const & filter)
|
||||
: m_filter(filter), m_values(std::make_unique<Values>())
|
||||
{
|
||||
}
|
||||
explicit OffsetIntersector(Filter const & filter) : m_filter(filter), m_values(std::make_unique<Values>()) {}
|
||||
|
||||
void operator()(Value const & v, bool exactMatch)
|
||||
{
|
||||
@@ -150,8 +146,7 @@ struct TrieRootPrefix
|
||||
strings::UniChar const * m_prefix;
|
||||
size_t m_prefixSize;
|
||||
|
||||
TrieRootPrefix(Iterator const & root, typename Iterator::Edge::EdgeLabel const & edge)
|
||||
: m_root(root)
|
||||
TrieRootPrefix(Iterator const & root, typename Iterator::Edge::EdgeLabel const & edge) : m_root(root)
|
||||
{
|
||||
if (edge.size() == 1)
|
||||
{
|
||||
@@ -203,10 +198,8 @@ struct SearchTrieRequest
|
||||
{
|
||||
m_langs.clear();
|
||||
for (auto const lang : langs)
|
||||
{
|
||||
if (lang >= 0 && lang <= std::numeric_limits<int8_t>::max())
|
||||
m_langs.insert(static_cast<int8_t>(lang));
|
||||
}
|
||||
}
|
||||
|
||||
bool HasLang(int8_t lang) const { return m_langs.find(lang) != m_langs.cend(); }
|
||||
@@ -232,8 +225,7 @@ struct SearchTrieRequest
|
||||
//
|
||||
// *NOTE* |toDo| may be called several times for the same feature.
|
||||
template <typename DFA, typename ValueList, typename ToDo>
|
||||
void MatchInTrie(std::vector<DFA> const & dfas, TrieRootPrefix<ValueList> const & trieRoot,
|
||||
ToDo && toDo)
|
||||
void MatchInTrie(std::vector<DFA> const & dfas, TrieRootPrefix<ValueList> const & trieRoot, ToDo && toDo)
|
||||
{
|
||||
for (auto const & dfa : dfas)
|
||||
impl::MatchInTrie(trieRoot.m_root, trieRoot.m_prefix, trieRoot.m_prefixSize, dfa, toDo);
|
||||
@@ -243,8 +235,8 @@ void MatchInTrie(std::vector<DFA> const & dfas, TrieRootPrefix<ValueList> const
|
||||
//
|
||||
// *NOTE* |toDo| may be called several times for the same feature.
|
||||
template <typename DFA, typename ValueList, typename ToDo>
|
||||
bool MatchCategoriesInTrie(SearchTrieRequest<DFA> const & request,
|
||||
trie::Iterator<ValueList> const & trieRoot, ToDo && toDo)
|
||||
bool MatchCategoriesInTrie(SearchTrieRequest<DFA> const & request, trie::Iterator<ValueList> const & trieRoot,
|
||||
ToDo && toDo)
|
||||
{
|
||||
uint32_t langIx = 0;
|
||||
if (!impl::FindLangIndex(trieRoot, search::kCategoriesLang, langIx))
|
||||
@@ -262,8 +254,7 @@ bool MatchCategoriesInTrie(SearchTrieRequest<DFA> const & request,
|
||||
// Calls |toDo| with trie root prefix and language code on each
|
||||
// language allowed by |request|.
|
||||
template <typename DFA, typename ValueList, typename ToDo>
|
||||
void ForEachLangPrefix(SearchTrieRequest<DFA> const & request,
|
||||
trie::Iterator<ValueList> const & trieRoot, ToDo && toDo)
|
||||
void ForEachLangPrefix(SearchTrieRequest<DFA> const & request, trie::Iterator<ValueList> const & trieRoot, ToDo && toDo)
|
||||
{
|
||||
ASSERT_LESS(trieRoot.m_edges.size(), std::numeric_limits<uint32_t>::max(), ());
|
||||
|
||||
@@ -285,9 +276,8 @@ void ForEachLangPrefix(SearchTrieRequest<DFA> const & request,
|
||||
// Calls |toDo| for each feature whose description matches to
|
||||
// |request|. Each feature will be passed to |toDo| only once.
|
||||
template <typename DFA, typename ValueList, typename Filter, typename ToDo>
|
||||
void MatchFeaturesInTrie(SearchTrieRequest<DFA> const & request,
|
||||
trie::Iterator<ValueList> const & trieRoot, Filter const & filter,
|
||||
ToDo && toDo)
|
||||
void MatchFeaturesInTrie(SearchTrieRequest<DFA> const & request, trie::Iterator<ValueList> const & trieRoot,
|
||||
Filter const & filter, ToDo && toDo)
|
||||
{
|
||||
using Value = typename ValueList::Value;
|
||||
|
||||
@@ -297,13 +287,11 @@ void MatchFeaturesInTrie(SearchTrieRequest<DFA> const & request,
|
||||
/// @todo Not sure why do we have OffsetIntersector here? We are doing aggregation only.
|
||||
impl::OffsetIntersector<Filter, Value> intersector(filter);
|
||||
|
||||
ForEachLangPrefix(
|
||||
request, trieRoot,
|
||||
[&request, &intersector](TrieRootPrefix<ValueList> & langRoot, int8_t /* lang */)
|
||||
{
|
||||
// Aggregate for all languages.
|
||||
MatchInTrie(request.m_names, langRoot, intersector);
|
||||
});
|
||||
ForEachLangPrefix(request, trieRoot, [&request, &intersector](TrieRootPrefix<ValueList> & langRoot, int8_t /* lang */)
|
||||
{
|
||||
// Aggregate for all languages.
|
||||
MatchInTrie(request.m_names, langRoot, intersector);
|
||||
});
|
||||
|
||||
if (categoriesExist)
|
||||
{
|
||||
@@ -316,8 +304,8 @@ void MatchFeaturesInTrie(SearchTrieRequest<DFA> const & request,
|
||||
}
|
||||
|
||||
template <typename ValueList, typename Filter, typename ToDo>
|
||||
void MatchPostcodesInTrie(TokenSlice const & slice, trie::Iterator<ValueList> const & trieRoot,
|
||||
Filter const & filter, ToDo && toDo)
|
||||
void MatchPostcodesInTrie(TokenSlice const & slice, trie::Iterator<ValueList> const & trieRoot, Filter const & filter,
|
||||
ToDo && toDo)
|
||||
{
|
||||
using namespace strings;
|
||||
using Value = typename ValueList::Value;
|
||||
|
||||
@@ -5,10 +5,7 @@
|
||||
namespace search
|
||||
{
|
||||
// FeaturesFilter ----------------------------------------------------------------------------------
|
||||
FeaturesFilter::FeaturesFilter(CBV const & filter, uint64_t threshold)
|
||||
: m_filter(filter), m_threshold(threshold)
|
||||
{
|
||||
}
|
||||
FeaturesFilter::FeaturesFilter(CBV const & filter, uint64_t threshold) : m_filter(filter), m_threshold(threshold) {}
|
||||
|
||||
bool FeaturesFilter::NeedToFilter(CBV const & cbv) const
|
||||
{
|
||||
@@ -18,10 +15,7 @@ bool FeaturesFilter::NeedToFilter(CBV const & cbv) const
|
||||
}
|
||||
|
||||
// LocalityFilter ----------------------------------------------------------------------------------
|
||||
LocalityFilter::LocalityFilter(CBV const & filter)
|
||||
: FeaturesFilter(filter, 0 /* threshold */)
|
||||
{
|
||||
}
|
||||
LocalityFilter::LocalityFilter(CBV const & filter) : FeaturesFilter(filter, 0 /* threshold */) {}
|
||||
|
||||
CBV LocalityFilter::Filter(CBV const & cbv) const
|
||||
{
|
||||
@@ -29,10 +23,7 @@ CBV LocalityFilter::Filter(CBV const & cbv) const
|
||||
}
|
||||
|
||||
// ViewportFilter ----------------------------------------------------------------------------------
|
||||
ViewportFilter::ViewportFilter(CBV const & filter, uint64_t threshold)
|
||||
: FeaturesFilter(filter, threshold)
|
||||
{
|
||||
}
|
||||
ViewportFilter::ViewportFilter(CBV const & filter, uint64_t threshold) : FeaturesFilter(filter, threshold) {}
|
||||
|
||||
CBV ViewportFilter::Filter(CBV const & cbv) const
|
||||
{
|
||||
|
||||
@@ -9,7 +9,10 @@ using namespace std;
|
||||
|
||||
namespace search
|
||||
{
|
||||
FeaturesLayer::FeaturesLayer() { Clear(); }
|
||||
FeaturesLayer::FeaturesLayer()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
void FeaturesLayer::Clear()
|
||||
{
|
||||
@@ -24,13 +27,9 @@ void FeaturesLayer::Clear()
|
||||
string DebugPrint(FeaturesLayer const & layer)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "FeaturesLayer [size of m_sortedFeatures: "
|
||||
<< (layer.m_sortedFeatures ? layer.m_sortedFeatures->size() : 0)
|
||||
<< ", subquery: " << DebugPrint(layer.m_subQuery)
|
||||
<< ", tokenRange: " << DebugPrint(layer.m_tokenRange)
|
||||
<< ", type: " << DebugPrint(layer.m_type)
|
||||
<< ", lastTokenIsPrefix: " << layer.m_lastTokenIsPrefix
|
||||
<< "]";
|
||||
os << "FeaturesLayer [size of m_sortedFeatures: " << (layer.m_sortedFeatures ? layer.m_sortedFeatures->size() : 0)
|
||||
<< ", subquery: " << DebugPrint(layer.m_subQuery) << ", tokenRange: " << DebugPrint(layer.m_tokenRange)
|
||||
<< ", type: " << DebugPrint(layer.m_type) << ", lastTokenIsPrefix: " << layer.m_lastTokenIsPrefix << "]";
|
||||
return os.str();
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -24,7 +24,7 @@ struct FeaturesLayer
|
||||
// Non-owning ptr to a sorted vector of features.
|
||||
std::vector<uint32_t> const * m_sortedFeatures = nullptr;
|
||||
// Fetch vector of Features, described by this layer (used for CITY, SUBURB).
|
||||
std::function<CBV ()> m_getFeatures;
|
||||
std::function<CBV()> m_getFeatures;
|
||||
|
||||
strings::UniString m_subQuery;
|
||||
TokenRange m_tokenRange;
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
using namespace std;
|
||||
@@ -20,8 +19,7 @@ using namespace std;
|
||||
/// even if there is no exact street written for this house.
|
||||
int constexpr kMaxApproxStreetDistanceM = 100;
|
||||
|
||||
FeaturesLayerMatcher::FeaturesLayerMatcher(DataSource const & dataSource,
|
||||
base::Cancellable const & cancellable)
|
||||
FeaturesLayerMatcher::FeaturesLayerMatcher(DataSource const & dataSource, base::Cancellable const & cancellable)
|
||||
: m_context(nullptr)
|
||||
, m_postcodes(nullptr)
|
||||
, m_reverseGeocoder(dataSource)
|
||||
@@ -30,8 +28,7 @@ FeaturesLayerMatcher::FeaturesLayerMatcher(DataSource const & dataSource,
|
||||
, m_place2address("PlaceToAddresses")
|
||||
, m_loader(scales::GetUpperScale(), ReverseGeocoder::kLookupRadiusM)
|
||||
, m_cancellable(cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void FeaturesLayerMatcher::SetContext(MwmContext * context)
|
||||
{
|
||||
@@ -57,8 +54,8 @@ void FeaturesLayerMatcher::OnQueryFinished()
|
||||
m_loader.OnQueryFinished();
|
||||
}
|
||||
|
||||
std::vector<uint32_t> const & FeaturesLayerMatcher::GetPlaceAddrFeatures(
|
||||
uint32_t placeId, std::function<CBV ()> const & fn)
|
||||
std::vector<uint32_t> const & FeaturesLayerMatcher::GetPlaceAddrFeatures(uint32_t placeId,
|
||||
std::function<CBV()> const & fn)
|
||||
{
|
||||
ASSERT(fn, ());
|
||||
|
||||
@@ -93,10 +90,7 @@ uint32_t FeaturesLayerMatcher::GetMatchingStreet(FeatureID const & houseId)
|
||||
|
||||
uint32_t FeaturesLayerMatcher::GetMatchingStreet(FeatureType & feature)
|
||||
{
|
||||
return GetMatchingStreetImpl(feature.GetID(), [&]()
|
||||
{
|
||||
return &feature;
|
||||
});
|
||||
return GetMatchingStreetImpl(feature.GetID(), [&]() { return &feature; });
|
||||
}
|
||||
|
||||
FeaturesLayerMatcher::Streets const & FeaturesLayerMatcher::GetNearbyStreets(FeatureType & feature)
|
||||
@@ -140,8 +134,8 @@ uint32_t FeaturesLayerMatcher::GetMatchingStreetImpl(FeatureID const & id, Featu
|
||||
|
||||
if (edited)
|
||||
{
|
||||
auto const ret = find_if(streets.begin(), streets.end(),
|
||||
[&streetName](Street const & st) { return st.m_name == streetName; });
|
||||
auto const ret =
|
||||
find_if(streets.begin(), streets.end(), [&streetName](Street const & st) { return st.m_name == streetName; });
|
||||
if (ret != streets.end())
|
||||
{
|
||||
result = ret->m_id.m_index;
|
||||
|
||||
@@ -74,9 +74,7 @@ public:
|
||||
case Model::TYPE_STATE:
|
||||
case Model::TYPE_COUNTRY:
|
||||
case Model::TYPE_UNCLASSIFIED:
|
||||
case Model::TYPE_COUNT:
|
||||
ASSERT(false, ("Invalid parent layer type:", parent.m_type));
|
||||
break;
|
||||
case Model::TYPE_COUNT: ASSERT(false, ("Invalid parent layer type:", parent.m_type)); break;
|
||||
case Model::TYPE_CITY:
|
||||
ASSERT_EQUAL(child.m_type, Model::TYPE_BUILDING, ());
|
||||
MatchBuildingsWithPlace(child, parent, fn);
|
||||
@@ -97,8 +95,8 @@ public:
|
||||
MatchBuildingsWithStreets(child, parent, fn);
|
||||
break;
|
||||
case Model::TYPE_SUBURB:
|
||||
ASSERT(child.m_type == Model::TYPE_STREET || child.m_type == Model::TYPE_BUILDING ||
|
||||
Model::IsPoi(child.m_type), ());
|
||||
ASSERT(child.m_type == Model::TYPE_STREET || child.m_type == Model::TYPE_BUILDING || Model::IsPoi(child.m_type),
|
||||
());
|
||||
// Avoid matching buildings to suburb without street.
|
||||
if (child.m_type == Model::TYPE_BUILDING)
|
||||
MatchBuildingsWithPlace(child, parent, fn);
|
||||
@@ -111,7 +109,7 @@ public:
|
||||
void OnQueryFinished();
|
||||
|
||||
private:
|
||||
std::vector<uint32_t> const & GetPlaceAddrFeatures(uint32_t placeId, std::function<CBV ()> const & fn);
|
||||
std::vector<uint32_t> const & GetPlaceAddrFeatures(uint32_t placeId, std::function<CBV()> const & fn);
|
||||
|
||||
void BailIfCancelled() { ::search::BailIfCancelled(m_cancellable); }
|
||||
|
||||
@@ -157,13 +155,8 @@ private:
|
||||
poiCenters.reserve(pois.size());
|
||||
|
||||
for (size_t i = 0; i < pois.size(); ++i)
|
||||
{
|
||||
if (auto poiFt = GetByIndex(pois[i]))
|
||||
{
|
||||
poiCenters.emplace_back(feature::GetCenter(*poiFt, FeatureType::WORST_GEOMETRY),
|
||||
i /* id */);
|
||||
}
|
||||
}
|
||||
poiCenters.emplace_back(feature::GetCenter(*poiFt, FeatureType::WORST_GEOMETRY), i /* id */);
|
||||
|
||||
std::vector<PointRectMatcher::RectIdPair> buildingRects;
|
||||
buildingRects.reserve(buildings.size());
|
||||
@@ -179,25 +172,23 @@ private:
|
||||
if (buildingFt->GetGeomType() == feature::GeomType::Point)
|
||||
{
|
||||
auto const center = feature::GetCenter(*buildingFt, FeatureType::WORST_GEOMETRY);
|
||||
buildingRects.emplace_back(mercator::RectByCenterXYAndSizeInMeters(center, parentRadius),
|
||||
i /* id */);
|
||||
buildingRects.emplace_back(mercator::RectByCenterXYAndSizeInMeters(center, parentRadius), i /* id */);
|
||||
}
|
||||
else
|
||||
{
|
||||
buildingRects.emplace_back(buildingFt->GetLimitRect(FeatureType::WORST_GEOMETRY),
|
||||
i /* id */);
|
||||
double const rectSize =
|
||||
std::max(buildingRects.back().m_rect.SizeX(), buildingRects.back().m_rect.SizeY());
|
||||
buildingRects.emplace_back(buildingFt->GetLimitRect(FeatureType::WORST_GEOMETRY), i /* id */);
|
||||
double const rectSize = std::max(buildingRects.back().m_rect.SizeX(), buildingRects.back().m_rect.SizeY());
|
||||
maxRadius = std::max(maxRadius, rectSize / 2);
|
||||
}
|
||||
}
|
||||
|
||||
PointRectMatcher::Match(poiCenters, buildingRects, PointRectMatcher::RequestType::Any,
|
||||
[&](size_t poiId, size_t buildingId) {
|
||||
ASSERT_LESS(poiId, pois.size(), ());
|
||||
ASSERT_LESS(buildingId, buildings.size(), ());
|
||||
fn(pois[poiId], buildings[buildingId]);
|
||||
});
|
||||
[&](size_t poiId, size_t buildingId)
|
||||
{
|
||||
ASSERT_LESS(poiId, pois.size(), ());
|
||||
ASSERT_LESS(buildingId, buildings.size(), ());
|
||||
fn(pois[poiId], buildings[buildingId]);
|
||||
});
|
||||
|
||||
if (!parent.m_hasDelayedFeatures)
|
||||
return;
|
||||
@@ -214,25 +205,20 @@ private:
|
||||
{
|
||||
BailIfCancelled();
|
||||
|
||||
m_context->ForEachFeature(
|
||||
mercator::RectByCenterXYAndSizeInMeters(poiCenters[i].m_point, maxRadius),
|
||||
[&](FeatureType & ft)
|
||||
{
|
||||
BailIfCancelled();
|
||||
m_context->ForEachFeature(mercator::RectByCenterXYAndSizeInMeters(poiCenters[i].m_point, maxRadius),
|
||||
[&](FeatureType & ft)
|
||||
{
|
||||
BailIfCancelled();
|
||||
|
||||
if (m_postcodes && !m_postcodes->HasBit(ft.GetID().m_index) &&
|
||||
!m_postcodes->HasBit(GetMatchingStreet(ft)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (HouseNumbersMatch(ft, queryParse))
|
||||
{
|
||||
double const distanceM =
|
||||
mercator::DistanceOnEarth(feature::GetCenter(ft), poiCenters[i].m_point);
|
||||
if (distanceM < maxRadius)
|
||||
fn(pois[i], ft.GetID().m_index);
|
||||
}
|
||||
});
|
||||
if (m_postcodes && !m_postcodes->HasBit(ft.GetID().m_index) && !m_postcodes->HasBit(GetMatchingStreet(ft)))
|
||||
return;
|
||||
if (HouseNumbersMatch(ft, queryParse))
|
||||
{
|
||||
double const distanceM = mercator::DistanceOnEarth(feature::GetCenter(ft), poiCenters[i].m_point);
|
||||
if (distanceM < maxRadius)
|
||||
fn(pois[i], ft.GetID().m_index);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,13 +237,8 @@ private:
|
||||
poiCenters.reserve(pois.size());
|
||||
|
||||
for (size_t i = 0; i < pois.size(); ++i)
|
||||
{
|
||||
if (auto poiFt = GetByIndex(pois[i]))
|
||||
{
|
||||
poiCenters.emplace_back(feature::GetCenter(*poiFt, FeatureType::WORST_GEOMETRY),
|
||||
i /* id */);
|
||||
}
|
||||
}
|
||||
poiCenters.emplace_back(feature::GetCenter(*poiFt, FeatureType::WORST_GEOMETRY), i /* id */);
|
||||
|
||||
std::vector<PointRectMatcher::RectIdPair> streetRects;
|
||||
streetRects.reserve(streets.size());
|
||||
@@ -276,10 +257,7 @@ private:
|
||||
m2::RectD inflationRect;
|
||||
// Any point is good enough here, and feature::GetCenter would re-read the geometry.
|
||||
if (streetFt->GetPointsCount() > 0)
|
||||
{
|
||||
inflationRect = mercator::RectByCenterXYAndSizeInMeters(streetFt->GetPoint(0),
|
||||
0.5 * kStreetRadiusMeters);
|
||||
}
|
||||
inflationRect = mercator::RectByCenterXYAndSizeInMeters(streetFt->GetPoint(0), 0.5 * kStreetRadiusMeters);
|
||||
|
||||
for (size_t j = 0; j + 1 < streetFt->GetPointsCount(); ++j)
|
||||
{
|
||||
@@ -299,17 +277,15 @@ private:
|
||||
|
||||
BailIfCancelled();
|
||||
PointRectMatcher::Match(poiCenters, streetRects, PointRectMatcher::RequestType::All,
|
||||
[&](size_t poiId, size_t streetId) {
|
||||
ASSERT_LESS(poiId, pois.size(), ());
|
||||
ASSERT_LESS(streetId, streets.size(), ());
|
||||
auto const & poiCenter = poiCenters[poiId].m_point;
|
||||
ProjectionOnStreet proj;
|
||||
if (streetProjectors[streetId].GetProjection(poiCenter, proj) &&
|
||||
proj.m_distMeters < kStreetRadiusMeters)
|
||||
{
|
||||
fn(pois[poiId], streets[streetId]);
|
||||
}
|
||||
});
|
||||
[&](size_t poiId, size_t streetId)
|
||||
{
|
||||
ASSERT_LESS(poiId, pois.size(), ());
|
||||
ASSERT_LESS(streetId, streets.size(), ());
|
||||
auto const & poiCenter = poiCenters[poiId].m_point;
|
||||
ProjectionOnStreet proj;
|
||||
if (streetProjectors[streetId].GetProjection(poiCenter, proj) && proj.m_distMeters < kStreetRadiusMeters)
|
||||
fn(pois[poiId], streets[streetId]);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
@@ -365,14 +341,14 @@ private:
|
||||
};
|
||||
|
||||
// Cache is not needed since we process unique and mapped-only house->street.
|
||||
// std::unordered_map<uint32_t, bool> cache;
|
||||
// auto const cachingHouseNumberFilter = [&](uint32_t houseId, uint32_t streetId)
|
||||
// {
|
||||
// auto const res = cache.emplace(houseId, false);
|
||||
// if (res.second)
|
||||
// res.first->second = houseNumberFilter(houseId, streetId);
|
||||
// return res.first->second;
|
||||
// };
|
||||
// std::unordered_map<uint32_t, bool> cache;
|
||||
// auto const cachingHouseNumberFilter = [&](uint32_t houseId, uint32_t streetId)
|
||||
// {
|
||||
// auto const res = cache.emplace(houseId, false);
|
||||
// if (res.second)
|
||||
// res.first->second = houseNumberFilter(houseId, streetId);
|
||||
// return res.first->second;
|
||||
// };
|
||||
|
||||
for (uint32_t streetId : streets)
|
||||
{
|
||||
@@ -383,10 +359,8 @@ private:
|
||||
continue;
|
||||
|
||||
for (uint32_t houseId : street.m_features)
|
||||
{
|
||||
if (houseNumberFilter(houseId, streetId))
|
||||
fn(houseId, streetId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,10 +376,8 @@ private:
|
||||
if (!buildings.empty())
|
||||
{
|
||||
for (uint32_t houseId : buildings)
|
||||
{
|
||||
if (std::binary_search(ids.begin(), ids.end(), houseId))
|
||||
fn(houseId, placeId);
|
||||
}
|
||||
}
|
||||
if (!child.m_hasDelayedFeatures)
|
||||
return;
|
||||
@@ -432,10 +404,8 @@ private:
|
||||
};
|
||||
|
||||
for (uint32_t houseId : ids)
|
||||
{
|
||||
if (houseNumberFilter(houseId))
|
||||
fn(houseId, placeId);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
|
||||
@@ -59,8 +59,7 @@ bool GetPath(uint32_t id, vector<FeaturesLayer const *> const & layers, ParentGr
|
||||
return false;
|
||||
|
||||
size_t level = 0;
|
||||
for (auto parentGraphLayer = parent.crbegin(); parentGraphLayer != parent.crend();
|
||||
++parentGraphLayer, ++level)
|
||||
for (auto parentGraphLayer = parent.crbegin(); parentGraphLayer != parent.crend(); ++parentGraphLayer, ++level)
|
||||
{
|
||||
result.Set(layers[level]->m_type, id);
|
||||
auto const it = parentGraphLayer->find(id);
|
||||
@@ -81,8 +80,7 @@ bool MayHaveDelayedFeatures(FeaturesLayer const & layer)
|
||||
|
||||
template <class FnT>
|
||||
void FeaturesLayerPathFinder::FindReachableVertices(FeaturesLayerMatcher & matcher,
|
||||
vector<FeaturesLayer const *> const & layers,
|
||||
FnT && fn)
|
||||
vector<FeaturesLayer const *> const & layers, FnT && fn)
|
||||
{
|
||||
switch (m_mode)
|
||||
{
|
||||
@@ -103,9 +101,8 @@ void FeaturesLayerPathFinder::FindReachableVertices(FeaturesLayerMatcher & match
|
||||
}
|
||||
|
||||
template <class FnT>
|
||||
void FeaturesLayerPathFinder::FindReachableVerticesTopDown(
|
||||
FeaturesLayerMatcher & matcher, vector<FeaturesLayer const *> const & layers,
|
||||
FnT && fn)
|
||||
void FeaturesLayerPathFinder::FindReachableVerticesTopDown(FeaturesLayerMatcher & matcher,
|
||||
vector<FeaturesLayer const *> const & layers, FnT && fn)
|
||||
{
|
||||
ASSERT(!layers.empty(), ());
|
||||
|
||||
@@ -114,7 +111,8 @@ void FeaturesLayerPathFinder::FindReachableVerticesTopDown(
|
||||
|
||||
ParentGraph parentGraph;
|
||||
|
||||
auto addEdge = [&](uint32_t childFeature, uint32_t parentFeature) {
|
||||
auto addEdge = [&](uint32_t childFeature, uint32_t parentFeature)
|
||||
{
|
||||
auto & parent = parentGraph.back();
|
||||
if (parent.find(childFeature) != parent.end())
|
||||
return;
|
||||
@@ -148,16 +146,13 @@ void FeaturesLayerPathFinder::FindReachableVerticesTopDown(
|
||||
|
||||
IntersectionResult result;
|
||||
for (auto const & id : lowestLevel)
|
||||
{
|
||||
if (GetPath(id, layers, parentGraph, result))
|
||||
fn(result);
|
||||
}
|
||||
}
|
||||
|
||||
template <class FnT>
|
||||
void FeaturesLayerPathFinder::FindReachableVerticesBottomUp(
|
||||
FeaturesLayerMatcher & matcher, vector<FeaturesLayer const *> const & layers,
|
||||
FnT && fn)
|
||||
void FeaturesLayerPathFinder::FindReachableVerticesBottomUp(FeaturesLayerMatcher & matcher,
|
||||
vector<FeaturesLayer const *> const & layers, FnT && fn)
|
||||
{
|
||||
ASSERT(!layers.empty(), ());
|
||||
|
||||
@@ -176,7 +171,8 @@ void FeaturesLayerPathFinder::FindReachableVerticesBottomUp(
|
||||
// True iff |addEdge| works with the lowest level.
|
||||
bool first = true;
|
||||
|
||||
auto addEdge = [&](uint32_t childFeature, uint32_t parentFeature) {
|
||||
auto addEdge = [&](uint32_t childFeature, uint32_t parentFeature)
|
||||
{
|
||||
auto & parent = parentGraph.front();
|
||||
if (parent.find(childFeature) != parent.end())
|
||||
return;
|
||||
@@ -212,9 +208,7 @@ void FeaturesLayerPathFinder::FindReachableVerticesBottomUp(
|
||||
|
||||
IntersectionResult result;
|
||||
for (auto const & id : lowestLevel)
|
||||
{
|
||||
if (GetPath(id, layers, parentGraph, result))
|
||||
fn(result);
|
||||
}
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -50,8 +50,8 @@ public:
|
||||
FeaturesLayerPathFinder(base::Cancellable const & cancellable) : m_cancellable(cancellable) {}
|
||||
|
||||
template <typename TFn>
|
||||
void ForEachReachableVertex(FeaturesLayerMatcher & matcher,
|
||||
std::vector<FeaturesLayer const *> const & layers, TFn && fn)
|
||||
void ForEachReachableVertex(FeaturesLayerMatcher & matcher, std::vector<FeaturesLayer const *> const & layers,
|
||||
TFn && fn)
|
||||
{
|
||||
if (layers.empty())
|
||||
return;
|
||||
@@ -86,22 +86,19 @@ private:
|
||||
void BailIfCancelled() { ::search::BailIfCancelled(m_cancellable); }
|
||||
|
||||
template <class FnT>
|
||||
void FindReachableVertices(FeaturesLayerMatcher & matcher,
|
||||
std::vector<FeaturesLayer const *> const & layers,
|
||||
void FindReachableVertices(FeaturesLayerMatcher & matcher, std::vector<FeaturesLayer const *> const & layers,
|
||||
FnT && fn);
|
||||
|
||||
// Tries to find all |reachable| features from the lowest layer in a
|
||||
// high level -> low level pass.
|
||||
template <class FnT>
|
||||
void FindReachableVerticesTopDown(FeaturesLayerMatcher & matcher,
|
||||
std::vector<FeaturesLayer const *> const & layers,
|
||||
void FindReachableVerticesTopDown(FeaturesLayerMatcher & matcher, std::vector<FeaturesLayer const *> const & layers,
|
||||
FnT && fn);
|
||||
|
||||
// Tries to find all |reachable| features from the lowest layer in a
|
||||
// low level -> high level pass.
|
||||
template <class FnT>
|
||||
void FindReachableVerticesBottomUp(FeaturesLayerMatcher & matcher,
|
||||
std::vector<FeaturesLayer const *> const & layers,
|
||||
void FindReachableVerticesBottomUp(FeaturesLayerMatcher & matcher, std::vector<FeaturesLayer const *> const & layers,
|
||||
FnT && fn);
|
||||
|
||||
base::Cancellable const & m_cancellable;
|
||||
|
||||
@@ -25,4 +25,4 @@ struct RecommendedFilteringParams
|
||||
/// @}
|
||||
};
|
||||
|
||||
} // namespace search
|
||||
} // namespace search
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#include "base/timer.hpp"
|
||||
#endif // DEBUG
|
||||
|
||||
#include "search/features_layer_path_finder.cpp" // template functions implementation
|
||||
#include "search/features_layer_path_finder.cpp" // template functions implementation
|
||||
|
||||
namespace search
|
||||
{
|
||||
@@ -72,14 +72,14 @@ size_t constexpr kPostcodesRectsCacheSize = 10;
|
||||
size_t constexpr kSuburbsRectsCacheSize = 10;
|
||||
size_t constexpr kLocalityRectsCacheSize = 10;
|
||||
|
||||
|
||||
struct ScopedMarkTokens
|
||||
{
|
||||
static BaseContext::TokenType constexpr kUnused = BaseContext::TOKEN_TYPE_COUNT;
|
||||
|
||||
ScopedMarkTokens(vector<BaseContext::TokenType> & tokens, BaseContext::TokenType type,
|
||||
TokenRange const & range)
|
||||
: m_tokens(tokens), m_type(type), m_range(range)
|
||||
ScopedMarkTokens(vector<BaseContext::TokenType> & tokens, BaseContext::TokenType type, TokenRange const & range)
|
||||
: m_tokens(tokens)
|
||||
, m_type(type)
|
||||
, m_range(range)
|
||||
{
|
||||
ASSERT(m_range.IsValid(), ());
|
||||
ASSERT_LESS_OR_EQUAL(m_range.End(), m_tokens.size(), ());
|
||||
@@ -215,8 +215,7 @@ private:
|
||||
LazyRankTable m_ranks;
|
||||
};
|
||||
|
||||
void JoinQueryTokens(QueryParams const & params, TokenRange const & range, UniString const & sep,
|
||||
UniString & res)
|
||||
void JoinQueryTokens(QueryParams const & params, TokenRange const & range, UniString const & sep, UniString & res)
|
||||
{
|
||||
ASSERT(range.IsValid(), (range));
|
||||
for (size_t i : range)
|
||||
@@ -246,7 +245,10 @@ void JoinQueryTokens(QueryParams const & params, TokenRange const & range, UniSt
|
||||
return true;
|
||||
}
|
||||
|
||||
double Area(m2::RectD const & rect) { return rect.IsValid() ? rect.SizeX() * rect.SizeY() : 0; }
|
||||
double Area(m2::RectD const & rect)
|
||||
{
|
||||
return rect.IsValid() ? rect.SizeX() * rect.SizeY() : 0;
|
||||
}
|
||||
|
||||
/// @brief Computes the average similarity between |rect| and |pivot|.
|
||||
/// By similarity between two rects we mean a fraction of the area of
|
||||
@@ -275,7 +277,8 @@ double GetDistanceMeters(m2::PointD const & pivot, m2::RectD const & rect)
|
||||
|
||||
double distance = numeric_limits<double>::max();
|
||||
|
||||
rect.ForEachSide([&](m2::PointD const & a, m2::PointD const & b) {
|
||||
rect.ForEachSide([&](m2::PointD const & a, m2::PointD const & b)
|
||||
{
|
||||
m2::ParametrizedSegment<m2::PointD> segment(a, b);
|
||||
distance = min(distance, mercator::DistanceOnEarth(pivot, segment.ClosestPointTo(pivot)));
|
||||
});
|
||||
@@ -293,20 +296,18 @@ unique_ptr<MwmContext> GetWorldContext(DataSource const & dataSource)
|
||||
return {};
|
||||
}
|
||||
|
||||
#define TRACE(branch) \
|
||||
m_resultTracer.CallMethod(ResultTracer::Branch::branch); \
|
||||
#define TRACE(branch) \
|
||||
m_resultTracer.CallMethod(ResultTracer::Branch::branch); \
|
||||
SCOPE_GUARD(tracerGuard, [&] { m_resultTracer.LeaveMethod(ResultTracer::Branch::branch); })
|
||||
} // namespace
|
||||
|
||||
|
||||
// Geocoder::LocalitiesCaches ----------------------------------------------------------------------
|
||||
Geocoder::LocalitiesCaches::LocalitiesCaches(base::Cancellable const & cancellable)
|
||||
: m_countries(cancellable)
|
||||
, m_states(cancellable)
|
||||
, m_citiesTownsOrVillages(cancellable)
|
||||
, m_villages(cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void Geocoder::LocalitiesCaches::Clear()
|
||||
{
|
||||
@@ -318,9 +319,8 @@ void Geocoder::LocalitiesCaches::Clear()
|
||||
|
||||
// Geocoder::Geocoder ------------------------------------------------------------------------------
|
||||
Geocoder::Geocoder(DataSource const & dataSource, storage::CountryInfoGetter const & infoGetter,
|
||||
CategoriesHolder const & categories,
|
||||
CitiesBoundariesTable const & citiesBoundaries, PreRanker & preRanker,
|
||||
LocalitiesCaches & localitiesCaches, base::Cancellable const & cancellable)
|
||||
CategoriesHolder const & categories, CitiesBoundariesTable const & citiesBoundaries,
|
||||
PreRanker & preRanker, LocalitiesCaches & localitiesCaches, base::Cancellable const & cancellable)
|
||||
: m_dataSource(dataSource)
|
||||
, m_infoGetter(infoGetter)
|
||||
, m_categories(categories)
|
||||
@@ -340,8 +340,7 @@ Geocoder::Geocoder(DataSource const & dataSource, storage::CountryInfoGetter con
|
||||
, m_matcher(nullptr)
|
||||
, m_finder(m_cancellable)
|
||||
, m_preRanker(preRanker)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
Geocoder::~Geocoder() {}
|
||||
|
||||
@@ -389,9 +388,7 @@ void Geocoder::GoEverywhere()
|
||||
// work fast for most cases (significantly less than 1 second).
|
||||
#if defined(DEBUG)
|
||||
base::Timer timer;
|
||||
SCOPE_GUARD(printDuration, [&timer]() {
|
||||
LOG(LINFO, ("Total geocoding time:", timer.ElapsedSeconds(), "seconds"));
|
||||
});
|
||||
SCOPE_GUARD(printDuration, [&timer]() { LOG(LINFO, ("Total geocoding time:", timer.ElapsedSeconds(), "seconds")); });
|
||||
#endif
|
||||
|
||||
TRACE(GoEverywhere);
|
||||
@@ -415,9 +412,7 @@ void Geocoder::GoInViewport()
|
||||
vector<MwmInfoPtr> infos;
|
||||
m_dataSource.GetMwmsInfo(infos);
|
||||
|
||||
base::EraseIf(infos, [this](MwmInfoPtr const & info) {
|
||||
return !m_params.m_pivot.IsIntersect(info->m_bordersRect);
|
||||
});
|
||||
base::EraseIf(infos, [this](MwmInfoPtr const & info) { return !m_params.m_pivot.IsIntersect(info->m_bordersRect); });
|
||||
|
||||
GoImpl(infos, true /* inViewport */);
|
||||
}
|
||||
@@ -458,27 +453,17 @@ Geocoder::ExtendedMwmInfos Geocoder::OrderCountries(bool inViewport, vector<MwmI
|
||||
if (!inViewport)
|
||||
{
|
||||
for (auto const & p : m_cities)
|
||||
{
|
||||
for (auto const & city : p.second)
|
||||
mwmsWithCities.insert(m_infoGetter.GetRegionCountryId(city.m_rect.Center()));
|
||||
}
|
||||
for (auto const & p : m_regions[Region::TYPE_STATE])
|
||||
{
|
||||
for (auto const & state : p.second)
|
||||
{
|
||||
mwmsWithStates.insert(m_infoGetter.GetRegionCountryId(state.m_center));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto const hasMatchedCity = [&mwmsWithCities](auto const & i)
|
||||
{
|
||||
return mwmsWithCities.count(i->GetCountryName()) != 0;
|
||||
};
|
||||
{ return mwmsWithCities.count(i->GetCountryName()) != 0; };
|
||||
auto const hasMatchedState = [&mwmsWithStates](auto const & i)
|
||||
{
|
||||
return mwmsWithStates.count(i->GetCountryName()) != 0;
|
||||
};
|
||||
{ return mwmsWithStates.count(i->GetCountryName()) != 0; };
|
||||
|
||||
std::string locationMwm;
|
||||
if (m_params.m_position)
|
||||
@@ -528,9 +513,7 @@ Geocoder::ExtendedMwmInfos Geocoder::OrderCountries(bool inViewport, vector<MwmI
|
||||
sort(res.m_infos.begin(), res.m_infos.end());
|
||||
|
||||
auto const sep = stable_partition(res.m_infos.begin(), res.m_infos.end(), [&](auto const & extendedInfo)
|
||||
{
|
||||
return extendedInfo.m_type.IsFirstBatchMwm(inViewport);
|
||||
});
|
||||
{ return extendedInfo.m_type.IsFirstBatchMwm(inViewport); });
|
||||
res.m_firstBatchSize = distance(res.m_infos.begin(), sep);
|
||||
|
||||
return res;
|
||||
@@ -581,11 +564,13 @@ void Geocoder::GoImpl(vector<MwmInfoPtr> const & infos, bool inViewport)
|
||||
|
||||
// MatchAroundPivot() should always be matched in mwms
|
||||
// intersecting with position and viewport.
|
||||
auto processCountry = [&](unique_ptr<MwmContext> context, bool updatePreranker) {
|
||||
auto processCountry = [&](unique_ptr<MwmContext> context, bool updatePreranker)
|
||||
{
|
||||
ASSERT(context, ());
|
||||
m_context = std::move(context);
|
||||
|
||||
SCOPE_GUARD(cleanup, [&]() {
|
||||
SCOPE_GUARD(cleanup, [&]()
|
||||
{
|
||||
LOG(LDEBUG, (m_context->GetName(), "geocoding complete."));
|
||||
m_matcher->OnQueryFinished();
|
||||
m_matcher = nullptr;
|
||||
@@ -596,8 +581,8 @@ void Geocoder::GoImpl(vector<MwmInfoPtr> const & infos, bool inViewport)
|
||||
if (it == m_matchersCache.end())
|
||||
{
|
||||
it = m_matchersCache
|
||||
.insert(make_pair(m_context->GetId(),
|
||||
std::make_unique<FeaturesLayerMatcher>(m_dataSource, m_cancellable)))
|
||||
.insert(
|
||||
make_pair(m_context->GetId(), std::make_unique<FeaturesLayerMatcher>(m_dataSource, m_cancellable)))
|
||||
.first;
|
||||
}
|
||||
m_matcher = it->second.get();
|
||||
@@ -608,8 +593,7 @@ void Geocoder::GoImpl(vector<MwmInfoPtr> const & infos, bool inViewport)
|
||||
|
||||
if (inViewport)
|
||||
{
|
||||
auto const viewportCBV =
|
||||
RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RectId::Pivot);
|
||||
auto const viewportCBV = RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RectId::Pivot);
|
||||
for (auto & features : ctx.m_features)
|
||||
features = features.Intersect(viewportCBV);
|
||||
}
|
||||
@@ -684,12 +668,10 @@ void Geocoder::InitLayer(Model::Type type, TokenRange const & tokenRange, Featur
|
||||
layer.m_tokenRange = tokenRange;
|
||||
|
||||
JoinQueryTokens(m_params, layer.m_tokenRange, UniString::kSpace /* sep */, layer.m_subQuery);
|
||||
layer.m_lastTokenIsPrefix =
|
||||
!layer.m_tokenRange.Empty() && m_params.IsPrefixToken(layer.m_tokenRange.End() - 1);
|
||||
layer.m_lastTokenIsPrefix = !layer.m_tokenRange.Empty() && m_params.IsPrefixToken(layer.m_tokenRange.End() - 1);
|
||||
}
|
||||
|
||||
void Geocoder::FillLocalityCandidates(BaseContext const & ctx, CBV const & filter,
|
||||
size_t const maxNumLocalities,
|
||||
void Geocoder::FillLocalityCandidates(BaseContext const & ctx, CBV const & filter, size_t const maxNumLocalities,
|
||||
vector<Locality> & preLocalities)
|
||||
{
|
||||
// todo(@m) "food moscow" should be a valid categorial request.
|
||||
@@ -703,16 +685,13 @@ void Geocoder::FillLocalityCandidates(BaseContext const & ctx, CBV const & filte
|
||||
for (auto const & type : m_regions)
|
||||
{
|
||||
for (auto const & ranges : type)
|
||||
{
|
||||
for (auto const & regions : ranges.second)
|
||||
ids.insert(ids.end(), regions.m_ids.begin(), regions.m_ids.end());
|
||||
}
|
||||
}
|
||||
base::SortUnique(ids);
|
||||
|
||||
auto const belongsToMatchedRegion = [&](m2::PointD const & point) {
|
||||
return m_infoGetter.BelongsToAnyRegion(point, ids);
|
||||
};
|
||||
auto const belongsToMatchedRegion = [&](m2::PointD const & point)
|
||||
{ return m_infoGetter.BelongsToAnyRegion(point, ids); };
|
||||
|
||||
LocalityScorerDelegate delegate(*m_context, m_params, belongsToMatchedRegion, m_cancellable);
|
||||
LocalityScorer scorer(m_params, m_params.m_pivot.Center(), delegate);
|
||||
@@ -813,8 +792,8 @@ void Geocoder::FillLocalitiesTable(BaseContext const & ctx)
|
||||
/// @todo Replace with assert in future. Now make additional check for compatibility with old "buggy" World.
|
||||
if (city.m_rect.IsPointInside(center))
|
||||
haveBoundary = true;
|
||||
//else
|
||||
// ASSERT(false, (city.m_rect, center, ft->GetID()));
|
||||
// else
|
||||
// ASSERT(false, (city.m_rect, center, ft->GetID()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -825,11 +804,10 @@ void Geocoder::FillLocalitiesTable(BaseContext const & ctx)
|
||||
city.m_rect = mercator::RectByCenterXYAndSizeInMeters(center, radius);
|
||||
}
|
||||
|
||||
LOG(LDEBUG,
|
||||
("City =", ft->GetName(StringUtf8Multilang::kDefaultCode), "ll =", mercator::ToLatLon(center),
|
||||
"rect =", mercator::ToLatLon(city.m_rect), "rect source:", haveBoundary ? "table" : "population",
|
||||
"sizeX =", mercator::DistanceOnEarth(city.m_rect.LeftTop(), city.m_rect.RightTop()),
|
||||
"sizeY =", mercator::DistanceOnEarth(city.m_rect.LeftTop(), city.m_rect.LeftBottom())));
|
||||
LOG(LDEBUG, ("City =", ft->GetName(StringUtf8Multilang::kDefaultCode), "ll =", mercator::ToLatLon(center),
|
||||
"rect =", mercator::ToLatLon(city.m_rect), "rect source:", haveBoundary ? "table" : "population",
|
||||
"sizeX =", mercator::DistanceOnEarth(city.m_rect.LeftTop(), city.m_rect.RightTop()),
|
||||
"sizeY =", mercator::DistanceOnEarth(city.m_rect.LeftTop(), city.m_rect.LeftBottom())));
|
||||
|
||||
m_cities[city.m_tokenRange].push_back(std::move(city));
|
||||
}
|
||||
@@ -874,8 +852,8 @@ void Geocoder::FillVillageLocalities(BaseContext const & ctx)
|
||||
auto const radius = ftypes::GetRadiusByPopulation(population);
|
||||
village.m_rect = mercator::RectByCenterXYAndSizeInMeters(center, radius);
|
||||
|
||||
LOG(LDEBUG, ("Village =", ft->GetName(StringUtf8Multilang::kDefaultCode),
|
||||
"ll =", mercator::ToLatLon(center), "radius =", radius));
|
||||
LOG(LDEBUG, ("Village =", ft->GetName(StringUtf8Multilang::kDefaultCode), "ll =", mercator::ToLatLon(center),
|
||||
"radius =", radius));
|
||||
|
||||
m_cities[village.m_tokenRange].push_back(std::move(village));
|
||||
}
|
||||
@@ -908,11 +886,8 @@ void Geocoder::ForEachCountry(ExtendedMwmInfos const & extendedInfos, Fn && fn)
|
||||
continue;
|
||||
bool const updatePreranker = i + 1 >= extendedInfos.m_firstBatchSize;
|
||||
auto const & mwmType = extendedInfos.m_infos[i].m_type;
|
||||
if (fn(make_unique<MwmContext>(std::move(handle), mwmType), updatePreranker) ==
|
||||
base::ControlFlow::Break)
|
||||
{
|
||||
if (fn(make_unique<MwmContext>(std::move(handle), mwmType), updatePreranker) == base::ControlFlow::Break)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -924,12 +899,10 @@ void Geocoder::MatchCategories(BaseContext & ctx, bool aroundPivot)
|
||||
|
||||
if (aroundPivot)
|
||||
{
|
||||
auto const pivotFeatures =
|
||||
RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RectId::Pivot);
|
||||
auto const pivotFeatures = RetrieveGeometryFeatures(*m_context, m_params.m_pivot, RectId::Pivot);
|
||||
ViewportFilter filter(pivotFeatures, m_preRanker.Limit() /* threshold */);
|
||||
features.m_features = filter.Filter(features.m_features);
|
||||
features.m_exactMatchingFeatures =
|
||||
features.m_exactMatchingFeatures.Intersect(features.m_features);
|
||||
features.m_exactMatchingFeatures = features.m_exactMatchingFeatures.Intersect(features.m_features);
|
||||
}
|
||||
|
||||
// Features have been retrieved from the search index
|
||||
@@ -941,9 +914,9 @@ void Geocoder::MatchCategories(BaseContext & ctx, bool aroundPivot)
|
||||
if (!GetTypeInGeocoding(ctx, featureId, type))
|
||||
return;
|
||||
|
||||
EmitResult(ctx, {m_context->GetId(), featureId}, type, TokenRange(0, ctx.NumTokens()),
|
||||
nullptr /* geoParts */, true /* allTokensUsed */, exactMatch);
|
||||
});
|
||||
EmitResult(ctx, {m_context->GetId(), featureId}, type, TokenRange(0, ctx.NumTokens()), nullptr /* geoParts */,
|
||||
true /* allTokensUsed */, exactMatch);
|
||||
});
|
||||
}
|
||||
|
||||
void Geocoder::MatchRegions(BaseContext & ctx, Region::Type type)
|
||||
@@ -989,8 +962,8 @@ void Geocoder::MatchRegions(BaseContext & ctx, Region::Type type)
|
||||
// mwm that is currently being processed belongs to region.
|
||||
if (isWorld)
|
||||
{
|
||||
matches = ctx.m_regions.empty() ||
|
||||
m_infoGetter.BelongsToAnyRegion(region.m_center, ctx.m_regions.back()->m_ids);
|
||||
matches =
|
||||
ctx.m_regions.empty() || m_infoGetter.BelongsToAnyRegion(region.m_center, ctx.m_regions.back()->m_ids);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1009,10 +982,8 @@ void Geocoder::MatchRegions(BaseContext & ctx, Region::Type type)
|
||||
{
|
||||
bool exactMatch = true;
|
||||
for (auto const & region : ctx.m_regions)
|
||||
{
|
||||
if (!region->m_exactMatch)
|
||||
exactMatch = false;
|
||||
}
|
||||
|
||||
// Region matches to search query, we need to emit it as is.
|
||||
EmitResult(ctx, region, tokenRange, true /* allTokensUsed */, exactMatch);
|
||||
@@ -1046,11 +1017,8 @@ void Geocoder::MatchCities(BaseContext & ctx)
|
||||
{
|
||||
BailIfCancelled();
|
||||
|
||||
if (!ctx.m_regions.empty() &&
|
||||
!m_infoGetter.BelongsToAnyRegion(city.m_rect.Center(), ctx.m_regions.back()->m_ids))
|
||||
{
|
||||
if (!ctx.m_regions.empty() && !m_infoGetter.BelongsToAnyRegion(city.m_rect.Center(), ctx.m_regions.back()->m_ids))
|
||||
continue;
|
||||
}
|
||||
|
||||
ScopedMarkTokens mark(ctx.m_tokens, BaseContext::FromModelType(city.m_type), tokenRange);
|
||||
ctx.m_city = &city;
|
||||
@@ -1113,8 +1081,7 @@ void Geocoder::MatchAroundPivot(BaseContext & ctx)
|
||||
LimitedSearch(ctx, filter, centers);
|
||||
}
|
||||
|
||||
void Geocoder::LimitedSearch(BaseContext & ctx, FeaturesFilter const & filter,
|
||||
CentersFilter const & centers)
|
||||
void Geocoder::LimitedSearch(BaseContext & ctx, FeaturesFilter const & filter, CentersFilter const & centers)
|
||||
{
|
||||
m_filter = &filter;
|
||||
SCOPE_GUARD(resetFilter, [&]() { m_filter = nullptr; });
|
||||
@@ -1127,7 +1094,8 @@ void Geocoder::LimitedSearch(BaseContext & ctx, FeaturesFilter const & filter,
|
||||
|
||||
MatchUnclassified(ctx, 0 /* curToken */);
|
||||
|
||||
auto const search = [this, &ctx, ¢ers]() {
|
||||
auto const search = [this, &ctx, ¢ers]()
|
||||
{
|
||||
GreedilyMatchStreets(ctx, centers);
|
||||
MatchPOIsAndBuildings(ctx, 0 /* curToken */, CBV::GetFull());
|
||||
};
|
||||
@@ -1194,10 +1162,7 @@ void Geocoder::WithPostcodes(BaseContext & ctx, Fn && fn)
|
||||
m_postcodes.Clear();
|
||||
|
||||
if (worldContext)
|
||||
{
|
||||
m_postcodes.m_worldFeatures =
|
||||
RetrievePostcodeFeatures(*worldContext, TokenSlice(m_params, tokenRange));
|
||||
}
|
||||
m_postcodes.m_worldFeatures = RetrievePostcodeFeatures(*worldContext, TokenSlice(m_params, tokenRange));
|
||||
|
||||
m_postcodes.m_tokenRange = tokenRange;
|
||||
m_postcodes.m_countryFeatures = std::move(postcodes);
|
||||
@@ -1256,7 +1221,7 @@ void Geocoder::GreedilyMatchStreetsWithSuburbs(BaseContext & ctx, CentersFilter
|
||||
auto & layers = ctx.m_layers;
|
||||
ASSERT(layers.empty(), ());
|
||||
layers.emplace_back();
|
||||
SCOPE_GUARD(cleanupGuard, [&layers]{ layers.pop_back(); });
|
||||
SCOPE_GUARD(cleanupGuard, [&layers] { layers.pop_back(); });
|
||||
|
||||
auto & layer = layers.back();
|
||||
InitLayer(Model::TYPE_SUBURB, suburb.m_tokenRange, layer);
|
||||
@@ -1288,8 +1253,8 @@ void Geocoder::GreedilyMatchStreetsWithSuburbs(BaseContext & ctx, CentersFilter
|
||||
}
|
||||
|
||||
template <class FnT>
|
||||
void Geocoder::CentersFilter::ClusterizeStreets(std::vector<uint32_t> & streets,
|
||||
Geocoder const & geocoder, FnT && fn) const
|
||||
void Geocoder::CentersFilter::ClusterizeStreets(std::vector<uint32_t> & streets, Geocoder const & geocoder,
|
||||
FnT && fn) const
|
||||
{
|
||||
std::vector<std::tuple<double, m2::PointD, uint32_t>> loadedStreets;
|
||||
loadedStreets.reserve(streets.size());
|
||||
@@ -1313,27 +1278,23 @@ void Geocoder::CentersFilter::ClusterizeStreets(std::vector<uint32_t> & streets,
|
||||
}
|
||||
|
||||
// Sort by distance.
|
||||
std::sort(loadedStreets.begin(), loadedStreets.end(), [](auto const & t1, auto const & t2)
|
||||
{
|
||||
return std::get<0>(t1) < std::get<0>(t2);
|
||||
});
|
||||
std::sort(loadedStreets.begin(), loadedStreets.end(),
|
||||
[](auto const & t1, auto const & t2) { return std::get<0>(t1) < std::get<0>(t2); });
|
||||
|
||||
buffer_vector<m2::RectD, 2> rects(m_centers.size());
|
||||
for (size_t i = 0; i < rects.size(); ++i)
|
||||
{
|
||||
rects[i] = mercator::RectByCenterXYAndSizeInMeters(
|
||||
m_centers[i], geocoder.m_params.m_filteringParams.m_streetSearchRadiusM);
|
||||
rects[i] = mercator::RectByCenterXYAndSizeInMeters(m_centers[i],
|
||||
geocoder.m_params.m_filteringParams.m_streetSearchRadiusM);
|
||||
}
|
||||
|
||||
// Find the first (after m_maxStreetsCount) street that is out of the rect's bounds
|
||||
size_t count = std::min(loadedStreets.size(), geocoder.m_params.m_filteringParams.m_maxStreetsCount);
|
||||
for (; count < loadedStreets.size(); ++count)
|
||||
{
|
||||
bool const outside = std::all_of(rects.begin(), rects.end(),
|
||||
[pt = std::get<1>(loadedStreets[count])](m2::RectD const & rect)
|
||||
{
|
||||
return !rect.IsPointInside(pt);
|
||||
});
|
||||
bool const outside =
|
||||
std::all_of(rects.begin(), rects.end(), [pt = std::get<1>(loadedStreets[count])](m2::RectD const & rect)
|
||||
{ return !rect.IsPointInside(pt); });
|
||||
if (outside)
|
||||
break;
|
||||
}
|
||||
@@ -1360,14 +1321,13 @@ void Geocoder::CentersFilter::ClusterizeStreets(std::vector<uint32_t> & streets,
|
||||
fn();
|
||||
}
|
||||
|
||||
void Geocoder::CreateStreetsLayerAndMatchLowerLayers(BaseContext & ctx,
|
||||
StreetsMatcher::Prediction const & prediction,
|
||||
void Geocoder::CreateStreetsLayerAndMatchLowerLayers(BaseContext & ctx, StreetsMatcher::Prediction const & prediction,
|
||||
CentersFilter const & centers, bool makeRelaxed)
|
||||
{
|
||||
auto & layers = ctx.m_layers;
|
||||
|
||||
layers.emplace_back();
|
||||
SCOPE_GUARD(cleanupGuard, [&]{ layers.pop_back(); });
|
||||
SCOPE_GUARD(cleanupGuard, [&] { layers.pop_back(); });
|
||||
|
||||
auto & layer = layers.back();
|
||||
InitLayer(Model::TYPE_STREET, prediction.m_tokenRange, layer);
|
||||
@@ -1375,10 +1335,7 @@ void Geocoder::CreateStreetsLayerAndMatchLowerLayers(BaseContext & ctx,
|
||||
vector<uint32_t> sortedFeatures;
|
||||
layer.m_sortedFeatures = &sortedFeatures;
|
||||
sortedFeatures.reserve(base::asserted_cast<size_t>(prediction.m_features.PopCount()));
|
||||
prediction.m_features.ForEach([&](uint64_t bit)
|
||||
{
|
||||
sortedFeatures.push_back(base::asserted_cast<uint32_t>(bit));
|
||||
});
|
||||
prediction.m_features.ForEach([&](uint64_t bit) { sortedFeatures.push_back(base::asserted_cast<uint32_t>(bit)); });
|
||||
|
||||
centers.ClusterizeStreets(sortedFeatures, *this, [&]()
|
||||
{
|
||||
@@ -1425,8 +1382,8 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con
|
||||
Model::Type type;
|
||||
if (GetTypeInGeocoding(ctx, featureId, type))
|
||||
{
|
||||
EmitResult(ctx, {m_context->GetId(), featureId}, type, m_postcodes.m_tokenRange,
|
||||
nullptr /* geoParts */, true /* allTokensUsed */, true /* exactMatch */);
|
||||
EmitResult(ctx, {m_context->GetId(), featureId}, type, m_postcodes.m_tokenRange, nullptr /* geoParts */,
|
||||
true /* allTokensUsed */, true /* exactMatch */);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -1455,22 +1412,20 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con
|
||||
// Following code creates a fake TYPE_BUILDING layer and intersects it with the streets layer.
|
||||
// Controversial: we can emit streets like buildings here. Filtered in IsFakeBuildingButStreet().
|
||||
layers.emplace_back();
|
||||
SCOPE_GUARD(cleanupGuard, [&]{ layers.pop_back(); });
|
||||
SCOPE_GUARD(cleanupGuard, [&] { layers.pop_back(); });
|
||||
|
||||
auto & layer = layers.back();
|
||||
InitLayer(Model::TYPE_BUILDING, m_postcodes.m_tokenRange, layer);
|
||||
|
||||
vector<uint32_t> features;
|
||||
m_postcodes.m_countryFeatures.ForEach([&features](uint64_t bit)
|
||||
{
|
||||
features.push_back(base::asserted_cast<uint32_t>(bit));
|
||||
});
|
||||
{ features.push_back(base::asserted_cast<uint32_t>(bit)); });
|
||||
layer.m_sortedFeatures = &features;
|
||||
return FindPaths(ctx);
|
||||
}
|
||||
|
||||
layers.emplace_back();
|
||||
SCOPE_GUARD(cleanupGuard, [&]{ layers.pop_back(); });
|
||||
SCOPE_GUARD(cleanupGuard, [&] { layers.pop_back(); });
|
||||
|
||||
// Clusters of features by search type. Each cluster is a sorted
|
||||
// list of ids.
|
||||
@@ -1519,8 +1474,8 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con
|
||||
if (m_filter->NeedToFilter(features.m_features))
|
||||
filtered = m_filter->Filter(features.m_features);
|
||||
|
||||
bool const looksLikeHouseNumber = house_numbers::LooksLikeHouseNumber(
|
||||
layers.back().m_subQuery, layers.back().m_lastTokenIsPrefix);
|
||||
bool const looksLikeHouseNumber =
|
||||
house_numbers::LooksLikeHouseNumber(layers.back().m_subQuery, layers.back().m_lastTokenIsPrefix);
|
||||
if (filtered.IsEmpty() && !looksLikeHouseNumber)
|
||||
break;
|
||||
|
||||
@@ -1530,10 +1485,7 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con
|
||||
}
|
||||
else
|
||||
{
|
||||
auto noFeature = [&filtered](uint64_t bit) -> bool
|
||||
{
|
||||
return !filtered.HasBit(bit);
|
||||
};
|
||||
auto noFeature = [&filtered](uint64_t bit) -> bool { return !filtered.HasBit(bit); };
|
||||
for (auto & cluster : clusters)
|
||||
base::EraseIf(cluster, noFeature);
|
||||
|
||||
@@ -1542,21 +1494,21 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con
|
||||
for (size_t i = 0; i < kNumClusters; ++i)
|
||||
ends[i] = clusters[i].size();
|
||||
filtered.ForEach([&](uint64_t bit)
|
||||
{
|
||||
auto const featureId = base::asserted_cast<uint32_t>(bit);
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < kNumClusters && !found; ++i)
|
||||
{
|
||||
size_t & cur = curs[i];
|
||||
size_t const end = ends[i];
|
||||
while (cur != end && clusters[i][cur] < featureId)
|
||||
++cur;
|
||||
if (cur != end && clusters[i][cur] == featureId)
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
clusterize(featureId);
|
||||
});
|
||||
{
|
||||
auto const featureId = base::asserted_cast<uint32_t>(bit);
|
||||
bool found = false;
|
||||
for (size_t i = 0; i < kNumClusters && !found; ++i)
|
||||
{
|
||||
size_t & cur = curs[i];
|
||||
size_t const end = ends[i];
|
||||
while (cur != end && clusters[i][cur] < featureId)
|
||||
++cur;
|
||||
if (cur != end && clusters[i][cur] == featureId)
|
||||
found = true;
|
||||
}
|
||||
if (!found)
|
||||
clusterize(featureId);
|
||||
});
|
||||
for (size_t i = 0; i < kNumClusters; ++i)
|
||||
inplace_merge(clusters[i].begin(), clusters[i].begin() + ends[i], clusters[i].end());
|
||||
}
|
||||
@@ -1574,16 +1526,15 @@ void Geocoder::MatchPOIsAndBuildings(BaseContext & ctx, size_t curToken, CBV con
|
||||
continue;
|
||||
}
|
||||
else if (layer.m_sortedFeatures->empty() ||
|
||||
/// @todo The crutch, but can't invent a better solution now. Should refactor layers iteration.
|
||||
/// @see ProcessorTest_Smoke and Numeric_POI_Name tests.
|
||||
/// @todo The crutch, but can't invent a better solution now. Should refactor layers iteration.
|
||||
/// @see ProcessorTest_Smoke and Numeric_POI_Name tests.
|
||||
(house_numbers::LooksLikeHouseNumberStrict(layer.m_subQuery) && numTokens > 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
layer.m_type = static_cast<Model::Type>(i);
|
||||
ScopedMarkTokens mark(ctx.m_tokens, BaseContext::FromModelType(layer.m_type),
|
||||
TokenRange(curToken, endToken));
|
||||
ScopedMarkTokens mark(ctx.m_tokens, BaseContext::FromModelType(layer.m_type), TokenRange(curToken, endToken));
|
||||
if (IsLayerSequenceSane(layers))
|
||||
MatchPOIsAndBuildings(ctx, endToken, filter);
|
||||
}
|
||||
@@ -1633,9 +1584,7 @@ bool Geocoder::IsLayerSequenceSane(vector<FeaturesLayer> const & layers) const
|
||||
return false;
|
||||
}
|
||||
if (hasBuildings && hasPois && !hasStreets)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1659,8 +1608,7 @@ uint32_t Geocoder::MatchWorld2Country(FeatureID const & id) const
|
||||
uint32_t resID = kInvalidFeatureId;
|
||||
m_context->ForEachFeature({pt, pt}, [&](FeatureType & ft)
|
||||
{
|
||||
if (resID == kInvalidFeatureId &&
|
||||
ft.GetName(StringUtf8Multilang::kDefaultCode) == name &&
|
||||
if (resID == kInvalidFeatureId && ft.GetName(StringUtf8Multilang::kDefaultCode) == name &&
|
||||
// Relaxed points comparison because geometry coding in the World and in a Country is different.
|
||||
feature::GetCenter(ft).EqualDxDy(pt, kMwmPointAccuracy * 100))
|
||||
{
|
||||
@@ -1693,9 +1641,7 @@ void Geocoder::FindPaths(BaseContext & ctx)
|
||||
hasBuilding = l.m_sortedFeatures->empty() || house_numbers::LooksLikeHouseNumberStrict(l.m_subQuery);
|
||||
break;
|
||||
case Model::TYPE_STREET:
|
||||
case Model::TYPE_SUBURB:
|
||||
hasStreetOrSuburb = true;
|
||||
break;
|
||||
case Model::TYPE_SUBURB: hasStreetOrSuburb = true; break;
|
||||
case Model::TYPE_CITY:
|
||||
case Model::TYPE_COMPLEX_POI:
|
||||
case Model::TYPE_COUNT:
|
||||
@@ -1718,9 +1664,7 @@ void Geocoder::FindPaths(BaseContext & ctx)
|
||||
cityFeature.push_back(fid);
|
||||
cityLayer.m_sortedFeatures = &cityFeature;
|
||||
cityLayer.m_getFeatures = [this, &ctx]()
|
||||
{
|
||||
return RetrieveGeometryFeatures(*m_context, ctx.m_city->m_rect, RectId::Locality);
|
||||
};
|
||||
{ return RetrieveGeometryFeatures(*m_context, ctx.m_city->m_rect, RectId::Locality); };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1776,10 +1720,8 @@ void Geocoder::FindPaths(BaseContext & ctx)
|
||||
if (haveRegion)
|
||||
{
|
||||
for (auto const & region : ctx.m_regions)
|
||||
{
|
||||
if (!region->m_exactMatch)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1791,14 +1733,13 @@ void Geocoder::FindPaths(BaseContext & ctx)
|
||||
if (result.IsFakeBuildingButStreet())
|
||||
return;
|
||||
|
||||
EmitResult(ctx, {m_context->GetId(), result.InnermostResult()}, innermostLayer.m_type,
|
||||
innermostLayer.m_tokenRange, &result, ctx.AllTokensUsed(),
|
||||
isExactMatch(result));
|
||||
EmitResult(ctx, {m_context->GetId(), result.InnermostResult()}, innermostLayer.m_type, innermostLayer.m_tokenRange,
|
||||
&result, ctx.AllTokensUsed(), isExactMatch(result));
|
||||
});
|
||||
}
|
||||
|
||||
void Geocoder::TraceResult(Tracer & tracer, BaseContext const & ctx, MwmSet::MwmId const & mwmId,
|
||||
uint32_t ftId, Model::Type type, TokenRange const & tokenRange)
|
||||
void Geocoder::TraceResult(Tracer & tracer, BaseContext const & ctx, MwmSet::MwmId const & mwmId, uint32_t ftId,
|
||||
Model::Type type, TokenRange const & tokenRange)
|
||||
{
|
||||
SCOPE_GUARD(emitParse, [&]() { tracer.EmitParse(ctx.m_tokens); });
|
||||
|
||||
@@ -1813,15 +1754,13 @@ void Geocoder::TraceResult(Tracer & tracer, BaseContext const & ctx, MwmSet::Mwm
|
||||
return;
|
||||
|
||||
feature::TypesHolder holder(*ft);
|
||||
CategoriesInfo catInfo(holder, TokenSlice(m_params, tokenRange), m_params.m_categoryLocales,
|
||||
m_categories);
|
||||
CategoriesInfo catInfo(holder, TokenSlice(m_params, tokenRange), m_params.m_categoryLocales, m_categories);
|
||||
|
||||
emitParse.release();
|
||||
tracer.EmitParse(ctx.m_tokens, catInfo.IsPureCategories());
|
||||
}
|
||||
|
||||
void Geocoder::EmitResult(BaseContext & ctx, FeatureID const & id,
|
||||
Model::Type type, TokenRange const & tokenRange,
|
||||
void Geocoder::EmitResult(BaseContext & ctx, FeatureID const & id, Model::Type type, TokenRange const & tokenRange,
|
||||
IntersectionResult const * geoParts, bool allTokensUsed, bool exactMatch)
|
||||
{
|
||||
double matchedFraction = 1.0;
|
||||
@@ -1903,19 +1842,16 @@ void Geocoder::EmitResult(BaseContext & ctx, FeatureID const & id,
|
||||
++ctx.m_numEmitted;
|
||||
}
|
||||
|
||||
void Geocoder::EmitResult(BaseContext & ctx, Region const & region, TokenRange const & tokenRange,
|
||||
bool allTokensUsed, bool exactMatch)
|
||||
void Geocoder::EmitResult(BaseContext & ctx, Region const & region, TokenRange const & tokenRange, bool allTokensUsed,
|
||||
bool exactMatch)
|
||||
{
|
||||
auto const type = Region::ToModelType(region.m_type);
|
||||
EmitResult(ctx, region.m_featureId, type, tokenRange, nullptr /* geoParts */,
|
||||
allTokensUsed, exactMatch);
|
||||
EmitResult(ctx, region.m_featureId, type, tokenRange, nullptr /* geoParts */, allTokensUsed, exactMatch);
|
||||
}
|
||||
|
||||
void Geocoder::EmitResult(BaseContext & ctx, City const & city, TokenRange const & tokenRange,
|
||||
bool allTokensUsed)
|
||||
void Geocoder::EmitResult(BaseContext & ctx, City const & city, TokenRange const & tokenRange, bool allTokensUsed)
|
||||
{
|
||||
EmitResult(ctx, city.m_featureId, city.m_type, tokenRange,
|
||||
nullptr /* geoParts */, allTokensUsed, city.m_exactMatch);
|
||||
EmitResult(ctx, city.m_featureId, city.m_type, tokenRange, nullptr /* geoParts */, allTokensUsed, city.m_exactMatch);
|
||||
}
|
||||
|
||||
void Geocoder::MatchUnclassified(BaseContext & ctx, size_t curToken)
|
||||
@@ -1940,9 +1876,7 @@ void Geocoder::MatchUnclassified(BaseContext & ctx, size_t curToken)
|
||||
curToken = ctx.SkipUsedTokens(curToken);
|
||||
auto startToken = curToken;
|
||||
for (; curToken < ctx.NumTokens() && !ctx.IsTokenUsed(curToken); ++curToken)
|
||||
{
|
||||
allFeatures = allFeatures.Intersect(ctx.m_features[curToken]);
|
||||
}
|
||||
|
||||
if (m_filter->NeedToFilter(allFeatures.m_features))
|
||||
{
|
||||
@@ -1959,8 +1893,8 @@ void Geocoder::MatchUnclassified(BaseContext & ctx, size_t curToken)
|
||||
{
|
||||
auto const tokenRange = TokenRange(startToken, curToken);
|
||||
ScopedMarkTokens mark(ctx.m_tokens, BaseContext::TOKEN_TYPE_UNCLASSIFIED, tokenRange);
|
||||
EmitResult(ctx, {m_context->GetId(), featureId}, type, tokenRange,
|
||||
nullptr /* geoParts */, true /* allTokensUsed */, exactMatch);
|
||||
EmitResult(ctx, {m_context->GetId(), featureId}, type, tokenRange, nullptr /* geoParts */,
|
||||
true /* allTokensUsed */, exactMatch);
|
||||
}
|
||||
};
|
||||
allFeatures.ForEach(emitUnclassified);
|
||||
@@ -1972,8 +1906,7 @@ CBV Geocoder::RetrievePostcodeFeatures(MwmContext const & context, TokenSlice co
|
||||
return CBV(retrieval.RetrievePostcodeFeatures(slice));
|
||||
}
|
||||
|
||||
CBV Geocoder::RetrieveGeometryFeatures(MwmContext const & context, m2::RectD const & rect,
|
||||
RectId id)
|
||||
CBV Geocoder::RetrieveGeometryFeatures(MwmContext const & context, m2::RectD const & rect, RectId id)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
|
||||
@@ -98,9 +98,8 @@ public:
|
||||
};
|
||||
|
||||
Geocoder(DataSource const & dataSource, storage::CountryInfoGetter const & infoGetter,
|
||||
CategoriesHolder const & categories, CitiesBoundariesTable const & citiesBoundaries,
|
||||
PreRanker & preRanker, LocalitiesCaches & localitiesCaches,
|
||||
base::Cancellable const & cancellable);
|
||||
CategoriesHolder const & categories, CitiesBoundariesTable const & citiesBoundaries, PreRanker & preRanker,
|
||||
LocalitiesCaches & localitiesCaches, base::Cancellable const & cancellable);
|
||||
~Geocoder();
|
||||
|
||||
// Sets search query params.
|
||||
@@ -195,8 +194,8 @@ private:
|
||||
|
||||
void InitLayer(Model::Type type, TokenRange const & tokenRange, FeaturesLayer & layer);
|
||||
|
||||
void FillLocalityCandidates(BaseContext const & ctx, CBV const & filter,
|
||||
size_t const maxNumLocalities, std::vector<Locality> & preLocalities);
|
||||
void FillLocalityCandidates(BaseContext const & ctx, CBV const & filter, size_t const maxNumLocalities,
|
||||
std::vector<Locality> & preLocalities);
|
||||
|
||||
void FillLocalitiesTable(BaseContext const & ctx);
|
||||
|
||||
@@ -241,8 +240,7 @@ private:
|
||||
// Tries to do geocoding in a limited scope, assuming that knowledge
|
||||
// about high-level features, like cities or countries, is
|
||||
// incorporated into |filter|.
|
||||
void LimitedSearch(BaseContext & ctx, FeaturesFilter const & filter,
|
||||
CentersFilter const & centers);
|
||||
void LimitedSearch(BaseContext & ctx, FeaturesFilter const & filter, CentersFilter const & centers);
|
||||
|
||||
template <typename Fn>
|
||||
void WithPostcodes(BaseContext & ctx, Fn && fn);
|
||||
@@ -253,8 +251,7 @@ private:
|
||||
// Matches suburbs and streets inside suburbs like |GreedilyMatchStreets|.
|
||||
void GreedilyMatchStreetsWithSuburbs(BaseContext & ctx, CentersFilter const & centers);
|
||||
|
||||
void CreateStreetsLayerAndMatchLowerLayers(BaseContext & ctx,
|
||||
StreetsMatcher::Prediction const & prediction,
|
||||
void CreateStreetsLayerAndMatchLowerLayers(BaseContext & ctx, StreetsMatcher::Prediction const & prediction,
|
||||
CentersFilter const & centers, bool makeRelaxed);
|
||||
|
||||
void ProcessStreets(BaseContext & ctx, CentersFilter const & centers, CBV const & streets);
|
||||
@@ -274,17 +271,15 @@ private:
|
||||
// Finds all paths through layers and emits reachable features from the lowest layer.
|
||||
void FindPaths(BaseContext & ctx);
|
||||
|
||||
void TraceResult(Tracer & tracer, BaseContext const & ctx, MwmSet::MwmId const & mwmId,
|
||||
uint32_t ftId, Model::Type type, TokenRange const & tokenRange);
|
||||
void TraceResult(Tracer & tracer, BaseContext const & ctx, MwmSet::MwmId const & mwmId, uint32_t ftId,
|
||||
Model::Type type, TokenRange const & tokenRange);
|
||||
|
||||
// Forms result and feeds it to |m_preRanker|.
|
||||
void EmitResult(BaseContext & ctx, FeatureID const & id, Model::Type type,
|
||||
TokenRange const & tokenRange, IntersectionResult const * geoParts,
|
||||
bool allTokensUsed, bool exactMatch);
|
||||
void EmitResult(BaseContext & ctx, Region const & region, TokenRange const & tokenRange,
|
||||
bool allTokensUsed, bool exactMatch);
|
||||
void EmitResult(BaseContext & ctx, City const & city, TokenRange const & tokenRange,
|
||||
bool allTokensUsed);
|
||||
void EmitResult(BaseContext & ctx, FeatureID const & id, Model::Type type, TokenRange const & tokenRange,
|
||||
IntersectionResult const * geoParts, bool allTokensUsed, bool exactMatch);
|
||||
void EmitResult(BaseContext & ctx, Region const & region, TokenRange const & tokenRange, bool allTokensUsed,
|
||||
bool exactMatch);
|
||||
void EmitResult(BaseContext & ctx, City const & city, TokenRange const & tokenRange, bool allTokensUsed);
|
||||
|
||||
// Tries to match unclassified objects from lower layers, like
|
||||
// parks, forests, lakes, rivers, etc. This method finds all
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "base/assert.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
// static
|
||||
@@ -62,10 +61,8 @@ bool BaseContext::IsTokenUsed(size_t token) const
|
||||
bool BaseContext::AllTokensUsed() const
|
||||
{
|
||||
for (size_t i = 0; i < m_tokens.size(); ++i)
|
||||
{
|
||||
if (!IsTokenUsed(i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -73,10 +70,8 @@ bool BaseContext::HasUsedTokensInRange(TokenRange const & range) const
|
||||
{
|
||||
ASSERT(range.IsValid(), (range));
|
||||
for (size_t i = range.Begin(); i < range.End(); ++i)
|
||||
{
|
||||
if (IsTokenUsed(i))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -84,10 +79,8 @@ size_t BaseContext::NumUnusedTokenGroups() const
|
||||
{
|
||||
size_t numGroups = 0;
|
||||
for (size_t i = 0; i < m_tokens.size(); ++i)
|
||||
{
|
||||
if (!IsTokenUsed(i) && (i == 0 || IsTokenUsed(i - 1)))
|
||||
++numGroups;
|
||||
}
|
||||
return numGroups;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,7 @@ struct Locality
|
||||
, m_tokenRange(tokenRange)
|
||||
, m_queryVec(queryVec)
|
||||
, m_exactMatch(exactMatch)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
uint32_t GetFeatureIndex() const { return m_featureId.m_index; }
|
||||
|
||||
@@ -62,9 +61,7 @@ struct Region : public Locality
|
||||
// states and Locality for smaller settlements.
|
||||
struct City : public Locality
|
||||
{
|
||||
City(Locality && locality, Model::Type type) : Locality(std::move(locality)), m_type(type)
|
||||
{
|
||||
}
|
||||
City(Locality && locality, Model::Type type) : Locality(std::move(locality)), m_type(type) {}
|
||||
|
||||
m2::RectD m_rect;
|
||||
Model::Type m_type;
|
||||
@@ -72,10 +69,8 @@ struct City : public Locality
|
||||
|
||||
struct Suburb
|
||||
{
|
||||
Suburb(FeatureID const & featureId, TokenRange const & tokenRange)
|
||||
: m_featureId(featureId), m_tokenRange(tokenRange)
|
||||
{
|
||||
}
|
||||
Suburb(FeatureID const & featureId, TokenRange const & tokenRange) : m_featureId(featureId), m_tokenRange(tokenRange)
|
||||
{}
|
||||
|
||||
FeatureID m_featureId;
|
||||
TokenRange m_tokenRange;
|
||||
|
||||
@@ -12,13 +12,13 @@ namespace search
|
||||
{
|
||||
// GeometryCache -----------------------------------------------------------------------------------
|
||||
GeometryCache::GeometryCache(size_t maxNumEntries, base::Cancellable const & cancellable)
|
||||
: m_maxNumEntries(maxNumEntries), m_cancellable(cancellable)
|
||||
: m_maxNumEntries(maxNumEntries)
|
||||
, m_cancellable(cancellable)
|
||||
{
|
||||
CHECK_GREATER(m_maxNumEntries, 0, ());
|
||||
}
|
||||
|
||||
void GeometryCache::InitEntry(MwmContext const & context, m2::RectD const & rect, int scale,
|
||||
Entry & entry)
|
||||
void GeometryCache::InitEntry(MwmContext const & context, m2::RectD const & rect, int scale, Entry & entry)
|
||||
{
|
||||
Retrieval retrieval(context, m_cancellable);
|
||||
|
||||
@@ -28,20 +28,18 @@ void GeometryCache::InitEntry(MwmContext const & context, m2::RectD const & rect
|
||||
}
|
||||
|
||||
// PivotRectsCache ---------------------------------------------------------------------------------
|
||||
PivotRectsCache::PivotRectsCache(size_t maxNumEntries, base::Cancellable const & cancellable,
|
||||
double maxRadiusMeters)
|
||||
: GeometryCache(maxNumEntries, cancellable), m_maxRadiusMeters(maxRadiusMeters)
|
||||
{
|
||||
}
|
||||
PivotRectsCache::PivotRectsCache(size_t maxNumEntries, base::Cancellable const & cancellable, double maxRadiusMeters)
|
||||
: GeometryCache(maxNumEntries, cancellable)
|
||||
, m_maxRadiusMeters(maxRadiusMeters)
|
||||
{}
|
||||
|
||||
CBV PivotRectsCache::Get(MwmContext const & context, m2::RectD const & rect, int scale)
|
||||
{
|
||||
auto p = FindOrCreateEntry(
|
||||
context.GetId(), [&rect, &scale](Entry const & entry)
|
||||
{
|
||||
return scale == entry.m_scale &&
|
||||
(entry.m_rect.IsRectInside(rect) || IsEqualMercator(rect, entry.m_rect, kMwmPointAccuracy));
|
||||
});
|
||||
auto p = FindOrCreateEntry(context.GetId(), [&rect, &scale](Entry const & entry)
|
||||
{
|
||||
return scale == entry.m_scale &&
|
||||
(entry.m_rect.IsRectInside(rect) || IsEqualMercator(rect, entry.m_rect, kMwmPointAccuracy));
|
||||
});
|
||||
auto & entry = p.first;
|
||||
if (p.second)
|
||||
{
|
||||
@@ -54,19 +52,14 @@ CBV PivotRectsCache::Get(MwmContext const & context, m2::RectD const & rect, int
|
||||
}
|
||||
|
||||
// LocalityRectsCache ------------------------------------------------------------------------------
|
||||
LocalityRectsCache::LocalityRectsCache(size_t maxNumEntries,
|
||||
base::Cancellable const & cancellable)
|
||||
LocalityRectsCache::LocalityRectsCache(size_t maxNumEntries, base::Cancellable const & cancellable)
|
||||
: GeometryCache(maxNumEntries, cancellable)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
CBV LocalityRectsCache::Get(MwmContext const & context, m2::RectD const & rect, int scale)
|
||||
{
|
||||
auto p = FindOrCreateEntry(context.GetId(), [&rect, &scale](Entry const & entry)
|
||||
{
|
||||
return scale == entry.m_scale &&
|
||||
IsEqualMercator(rect, entry.m_rect, kMwmPointAccuracy);
|
||||
});
|
||||
{ return scale == entry.m_scale && IsEqualMercator(rect, entry.m_rect, kMwmPointAccuracy); });
|
||||
auto & entry = p.first;
|
||||
if (p.second)
|
||||
InitEntry(context, rect, scale, entry);
|
||||
|
||||
@@ -81,8 +81,7 @@ protected:
|
||||
class PivotRectsCache : public GeometryCache
|
||||
{
|
||||
public:
|
||||
PivotRectsCache(size_t maxNumEntries, base::Cancellable const & cancellable,
|
||||
double maxRadiusMeters);
|
||||
PivotRectsCache(size_t maxNumEntries, base::Cancellable const & cancellable, double maxRadiusMeters);
|
||||
|
||||
// GeometryCache overrides:
|
||||
CBV Get(MwmContext const & context, m2::RectD const & rect, int scale) override;
|
||||
|
||||
@@ -33,16 +33,12 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(CombinedIterator const & other) const
|
||||
{
|
||||
return m_val == other.m_val && m_cur == other.m_cur;
|
||||
}
|
||||
bool operator==(CombinedIterator const & other) const { return m_val == other.m_val && m_cur == other.m_cur; }
|
||||
|
||||
bool operator!=(CombinedIterator const & other) const { return !(*this == other); }
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
void HighlightResult(QueryTokens const & tokens, strings::UniString const & prefix, Result & res)
|
||||
{
|
||||
using Iter = QueryTokens::const_iterator;
|
||||
@@ -52,17 +48,11 @@ void HighlightResult(QueryTokens const & tokens, strings::UniString const & pref
|
||||
CombinedIter end(tokens.end() /* cur */, tokens.end() /* end */, nullptr);
|
||||
|
||||
// Highlight Title
|
||||
SearchStringTokensIntersectionRanges(res.GetString(), beg, end,
|
||||
[&](std::pair<uint16_t, uint16_t> const & range)
|
||||
{
|
||||
res.AddHighlightRange(range);
|
||||
});
|
||||
SearchStringTokensIntersectionRanges(
|
||||
res.GetString(), beg, end, [&](std::pair<uint16_t, uint16_t> const & range) { res.AddHighlightRange(range); });
|
||||
|
||||
// Highlight description.
|
||||
SearchStringTokensIntersectionRanges(res.GetAddress(), beg, end,
|
||||
[&](std::pair<uint16_t, uint16_t> const & range)
|
||||
{
|
||||
res.AddDescHighlightRange(range);
|
||||
});
|
||||
SearchStringTokensIntersectionRanges(res.GetAddress(), beg, end, [&](std::pair<uint16_t, uint16_t> const & range)
|
||||
{ res.AddDescHighlightRange(range); });
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
namespace search
|
||||
{
|
||||
template <typename LowTokensIter, typename F>
|
||||
void SearchStringTokensIntersectionRanges(std::string const & s, LowTokensIter itLowBeg,
|
||||
LowTokensIter itLowEnd, F && f)
|
||||
void SearchStringTokensIntersectionRanges(std::string const & s, LowTokensIter itLowBeg, LowTokensIter itLowEnd, F && f)
|
||||
{
|
||||
// split input query by tokens and prefix
|
||||
search::Delimiters delimsTest;
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
using namespace std;
|
||||
@@ -103,18 +102,15 @@ double const STREET_CONNECTION_LENGTH_M = 100.0;
|
||||
int const HN_NEARBY_DISTANCE = 4;
|
||||
double const STREET_CONNECTION_MAX_ANGLE = math::pi / 2.0;
|
||||
size_t const HN_COUNT_FOR_ODD_TEST = 16;
|
||||
//double const HN_MIN_READ_OFFSET_M = 50.0;
|
||||
//int const HN_NEARBY_INDEX_RANGE = 5;
|
||||
// double const HN_MIN_READ_OFFSET_M = 50.0;
|
||||
// int const HN_NEARBY_INDEX_RANGE = 5;
|
||||
double const HN_MAX_CONNECTION_DIST_M = 300.0;
|
||||
|
||||
class StreetCreator
|
||||
{
|
||||
public:
|
||||
explicit StreetCreator(Street * st) : m_street(st) {}
|
||||
void operator () (m2::PointD const & pt) const
|
||||
{
|
||||
m_street->m_points.push_back(pt);
|
||||
}
|
||||
void operator()(m2::PointD const & pt) const { m_street->m_points.push_back(pt); }
|
||||
|
||||
private:
|
||||
Street * m_street;
|
||||
@@ -133,12 +129,12 @@ double GetDistanceMeters(m2::PointD const & p1, m2::PointD const & p2)
|
||||
pair<double, double> GetConnectionAngleAndDistance(bool & isBeg, Street const * s1, Street const * s2)
|
||||
{
|
||||
m2::PointD const & p1 = isBeg ? s1->m_points.front() : s1->m_points.back();
|
||||
m2::PointD const & p0 = isBeg ? s1->m_points[1] : s1->m_points[s1->m_points.size()-2];
|
||||
m2::PointD const & p0 = isBeg ? s1->m_points[1] : s1->m_points[s1->m_points.size() - 2];
|
||||
|
||||
double const d0 = p1.SquaredLength(s2->m_points.front());
|
||||
double const d2 = p1.SquaredLength(s2->m_points.back());
|
||||
isBeg = (d0 < d2);
|
||||
m2::PointD const & p2 = isBeg ? s2->m_points[1] : s2->m_points[s2->m_points.size()-2];
|
||||
m2::PointD const & p2 = isBeg ? s2->m_points[1] : s2->m_points[s2->m_points.size() - 2];
|
||||
|
||||
return make_pair(ang::GetShortestDistance(ang::AngleTo(p0, p1), ang::AngleTo(p1, p2)), min(d0, d2));
|
||||
}
|
||||
@@ -166,10 +162,8 @@ public:
|
||||
bool operator()(MergedStreet const & st) const
|
||||
{
|
||||
for (size_t i = 0; i < st.m_cont.size(); ++i)
|
||||
{
|
||||
if (m_streets.count(st.m_cont[i]) > 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -280,10 +274,7 @@ public:
|
||||
House const * GetNearbyCandidate() const { return (HasBestMatch() ? 0 : m_results[3].house); }
|
||||
|
||||
private:
|
||||
bool IsBetter(int ind, double dist) const
|
||||
{
|
||||
return m_results[ind].house == 0 || m_results[ind].score > dist;
|
||||
}
|
||||
bool IsBetter(int ind, double dist) const { return m_results[ind].house == 0 || m_results[ind].score > dist; }
|
||||
|
||||
ParsedNumber m_number;
|
||||
bool m_isOdd = false;
|
||||
@@ -412,9 +403,10 @@ struct Competitiors
|
||||
uint32_t m_chainIndex;
|
||||
double m_score;
|
||||
Competitiors(uint32_t candidateIndex, uint32_t chainIndex, double score)
|
||||
: m_candidateIndex(candidateIndex), m_chainIndex(chainIndex), m_score(score)
|
||||
{
|
||||
}
|
||||
: m_candidateIndex(candidateIndex)
|
||||
, m_chainIndex(chainIndex)
|
||||
, m_score(score)
|
||||
{}
|
||||
bool operator<(Competitiors const & c) const { return m_score < c.m_score; }
|
||||
};
|
||||
|
||||
@@ -452,10 +444,8 @@ void ProccessHouses(vector<HouseProjection const *> const & st, ResultAccumulato
|
||||
ASSERT_LESS(used.size(), numeric_limits<uint32_t>::max(), ());
|
||||
uint32_t const count = static_cast<uint32_t>(used.size());
|
||||
for (uint32_t i = 0; i < count; ++i)
|
||||
{
|
||||
if (!used[i] && st[i]->m_house->GetIntNumber() == candidateHouseNumber)
|
||||
candidates.push_back(i);
|
||||
}
|
||||
|
||||
bool shouldAddHouseToQueue = false;
|
||||
vector<Competitiors> comp;
|
||||
@@ -470,12 +460,10 @@ void ProccessHouses(vector<HouseProjection const *> const & st, ResultAccumulato
|
||||
{
|
||||
double dist = numeric_limits<double>::max();
|
||||
for (size_t k = 0; k < houseChains[j].houses.size(); ++k)
|
||||
{
|
||||
if (abs(houseChains[j].houses[k]->m_house->GetIntNumber() -
|
||||
st[candidates[i]]->m_house->GetIntNumber()) <= HN_NEARBY_DISTANCE)
|
||||
if (abs(houseChains[j].houses[k]->m_house->GetIntNumber() - st[candidates[i]]->m_house->GetIntNumber()) <=
|
||||
HN_NEARBY_DISTANCE)
|
||||
dist = min(dist, GetDistanceMeters(houseChains[j].houses[k]->m_house->GetPosition(),
|
||||
st[candidates[i]]->m_house->GetPosition()));
|
||||
}
|
||||
if (dist < HN_MAX_CONNECTION_DIST_M)
|
||||
comp.push_back(Competitiors(candidates[i], static_cast<uint32_t>(j), dist));
|
||||
}
|
||||
@@ -582,8 +570,7 @@ struct GreaterSecond
|
||||
}
|
||||
};
|
||||
|
||||
void ProduceVoting(vector<ResultAccumulator> const & acc, vector<HouseResult> & res,
|
||||
MergedStreet const & st)
|
||||
void ProduceVoting(vector<ResultAccumulator> const & acc, vector<HouseResult> & res, MergedStreet const & st)
|
||||
{
|
||||
buffer_vector<pair<House const *, size_t>, 4> voting;
|
||||
|
||||
@@ -600,12 +587,10 @@ void ProduceVoting(vector<ResultAccumulator> const & acc, vector<HouseResult> &
|
||||
// Emit results with equal best score.
|
||||
size_t const score = voting[0].second;
|
||||
for (size_t i = 0; i < voting.size(); ++i)
|
||||
{
|
||||
if (score == voting[i].second)
|
||||
res.push_back(HouseResult(voting[i].first, &st));
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -625,9 +610,7 @@ ParsedNumber::ParsedNumber(string const & number, bool american) : m_fullN(numbe
|
||||
switch (number[curr])
|
||||
{
|
||||
case ' ':
|
||||
case '\t':
|
||||
++curr;
|
||||
break;
|
||||
case '\t': ++curr; break;
|
||||
case ',':
|
||||
case ';':
|
||||
++curr;
|
||||
@@ -672,11 +655,8 @@ ParsedNumber::ParsedNumber(string const & number, bool american) : m_fullN(numbe
|
||||
{
|
||||
if (abs(m_endN - m_startN) >= 2 * HN_NEARBY_DISTANCE)
|
||||
m_endN = -1;
|
||||
else
|
||||
{
|
||||
if (m_startN > m_endN)
|
||||
std::swap(m_startN, m_endN);
|
||||
}
|
||||
else if (m_startN > m_endN)
|
||||
std::swap(m_startN, m_endN);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -748,16 +728,21 @@ void Street::Reverse()
|
||||
reverse(m_points.begin(), m_points.end());
|
||||
}
|
||||
|
||||
void Street::SortHousesProjection() { sort(m_houses.begin(), m_houses.end(), &LessStreetDistance); }
|
||||
void Street::SortHousesProjection()
|
||||
{
|
||||
sort(m_houses.begin(), m_houses.end(), &LessStreetDistance);
|
||||
}
|
||||
|
||||
HouseDetector::HouseDetector(DataSource const & dataSource)
|
||||
: m_loader(dataSource), m_streetNum(0)
|
||||
HouseDetector::HouseDetector(DataSource const & dataSource) : m_loader(dataSource), m_streetNum(0)
|
||||
{
|
||||
// Default value for conversions.
|
||||
SetMetersToMercator(mercator::Bounds::kDegreesInMeter);
|
||||
}
|
||||
|
||||
HouseDetector::~HouseDetector() { ClearCaches(); }
|
||||
HouseDetector::~HouseDetector()
|
||||
{
|
||||
ClearCaches();
|
||||
}
|
||||
|
||||
void HouseDetector::SetMetersToMercator(double factor)
|
||||
{
|
||||
@@ -858,10 +843,10 @@ int HouseDetector::LoadStreets(vector<FeatureID> const & ids)
|
||||
|
||||
// Do clear cache if we have elements that are present in the one set,
|
||||
// but not in the other one (set's order is irrelevant).
|
||||
size_t const count = set_intersection(make_transform_iterator(m_id2st.begin(), f),
|
||||
make_transform_iterator(m_id2st.end(), f), ids.begin(),
|
||||
ids.end(), CounterIterator())
|
||||
.GetCount();
|
||||
size_t const count =
|
||||
set_intersection(make_transform_iterator(m_id2st.begin(), f), make_transform_iterator(m_id2st.end(), f),
|
||||
ids.begin(), ids.end(), CounterIterator())
|
||||
.GetCount();
|
||||
|
||||
if (count < min(ids.size(), m_id2st.size()))
|
||||
{
|
||||
@@ -926,9 +911,9 @@ int HouseDetector::MergeStreets()
|
||||
{
|
||||
LOG(LDEBUG, ("MergeStreets() called", m_id2st.size()));
|
||||
|
||||
//#ifdef DEBUG
|
||||
// KMLFileGuard file("dbg_merged_streets.kml");
|
||||
//#endif
|
||||
// #ifdef DEBUG
|
||||
// KMLFileGuard file("dbg_merged_streets.kml");
|
||||
// #endif
|
||||
|
||||
for (auto it = m_id2st.begin(); it != m_id2st.end(); ++it)
|
||||
{
|
||||
@@ -944,16 +929,16 @@ int HouseDetector::MergeStreets()
|
||||
// Put longer streets first (for better house scoring).
|
||||
sort(m_streets.begin(), m_streets.end(), MergedStreet::GreaterLength());
|
||||
|
||||
//#ifdef DEBUG
|
||||
// char const * arrColor[] = { "FFFF0000", "FF00FFFF", "FFFFFF00", "FF0000FF", "FF00FF00",
|
||||
// "FFFF00FF" };
|
||||
// #ifdef DEBUG
|
||||
// char const * arrColor[] = { "FFFF0000", "FF00FFFF", "FFFFFF00", "FF0000FF", "FF00FF00",
|
||||
// "FFFF00FF" };
|
||||
|
||||
// // Write to kml from short to long to get the longest one at the top.
|
||||
// for (int i = int(m_streets.size()) - 1; i >= 0; --i)
|
||||
// {
|
||||
// Streets2KML(file.GetStream(), m_streets[i], arrColor[i % ARRAY_SIZE(arrColor)]);
|
||||
// }
|
||||
//#endif
|
||||
// #endif
|
||||
|
||||
LOG(LDEBUG, ("MergeStreets() result", m_streetNum));
|
||||
return m_streetNum;
|
||||
@@ -1002,10 +987,8 @@ void MergedStreet::FinishReadingHouses()
|
||||
for (size_t i = 0; i < m_cont.size(); ++i)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
for (size_t j = 0; j < m_cont[i]->m_houses.size(); ++j)
|
||||
m_cont[i]->m_houses[j].m_streetDistance += length;
|
||||
}
|
||||
|
||||
length += m_cont[i]->m_length;
|
||||
m_cont[i]->m_housesRead = true;
|
||||
@@ -1094,14 +1077,12 @@ void HouseDetector::ReadHouse(FeatureType & f, Street * st, ProjectionCalculator
|
||||
auto const it = m_id2house.find(f.GetID());
|
||||
bool const isNew = it == m_id2house.end();
|
||||
|
||||
m2::PointD const pt =
|
||||
isNew ? f.GetLimitRect(FeatureType::BEST_GEOMETRY).Center() : it->second->GetPosition();
|
||||
m2::PointD const pt = isNew ? f.GetLimitRect(FeatureType::BEST_GEOMETRY).Center() : it->second->GetPosition();
|
||||
|
||||
HouseProjection pr;
|
||||
if (calc.GetProjection(pt, pr) && pr.m_distMeters <= m_houseOffsetM)
|
||||
{
|
||||
pr.m_streetDistance =
|
||||
st->GetPrefixLength(pr.m_segIndex) + st->m_points[pr.m_segIndex].Length(pr.m_proj);
|
||||
pr.m_streetDistance = st->GetPrefixLength(pr.m_segIndex) + st->m_points[pr.m_segIndex].Length(pr.m_proj);
|
||||
|
||||
House * p;
|
||||
if (isNew)
|
||||
@@ -1129,9 +1110,8 @@ void HouseDetector::ReadHouses(Street * st)
|
||||
// offsetMeters));
|
||||
|
||||
ProjectionOnStreetCalculator calc(st->m_points);
|
||||
m_loader.ForEachInRect(st->GetLimitRect(m_houseOffsetM), [this, &st, &calc](FeatureType & ft) {
|
||||
ReadHouse<ProjectionOnStreetCalculator>(ft, st, calc);
|
||||
});
|
||||
m_loader.ForEachInRect(st->GetLimitRect(m_houseOffsetM), [this, &st, &calc](FeatureType & ft)
|
||||
{ ReadHouse<ProjectionOnStreetCalculator>(ft, st, calc); });
|
||||
|
||||
st->m_length = st->GetLength();
|
||||
st->SortHousesProjection();
|
||||
@@ -1145,10 +1125,8 @@ void HouseDetector::ReadAllHouses(double offsetMeters)
|
||||
ReadHouses(e.second);
|
||||
|
||||
for (auto & st : m_streets)
|
||||
{
|
||||
if (!st.IsHousesRead())
|
||||
st.FinishReadingHouses();
|
||||
}
|
||||
}
|
||||
|
||||
void HouseDetector::ClearCaches()
|
||||
@@ -1171,7 +1149,6 @@ void HouseDetector::ClearUnusedStreets(vector<FeatureID> const & ids)
|
||||
{
|
||||
set<Street *> streets;
|
||||
for (auto it = m_id2st.begin(); it != m_id2st.end();)
|
||||
{
|
||||
if (!binary_search(ids.begin(), ids.end(), it->first))
|
||||
{
|
||||
streets.insert(it->second);
|
||||
@@ -1179,11 +1156,9 @@ void HouseDetector::ClearUnusedStreets(vector<FeatureID> const & ids)
|
||||
}
|
||||
else
|
||||
++it;
|
||||
}
|
||||
|
||||
m_end2st.erase(remove_if(m_end2st.begin(), m_end2st.end(), HasSecond(streets)), m_end2st.end());
|
||||
m_streets.erase(remove_if(m_streets.begin(), m_streets.end(), HasStreet(streets)),
|
||||
m_streets.end());
|
||||
m_streets.erase(remove_if(m_streets.begin(), m_streets.end(), HasStreet(streets)), m_streets.end());
|
||||
|
||||
for_each(streets.begin(), streets.end(), base::DeleteFunctor());
|
||||
}
|
||||
@@ -1206,7 +1181,7 @@ void HouseDetector::GetHouseForName(string const & houseNumber, vector<HouseResu
|
||||
|
||||
vector<ResultAccumulator> acc(3, ResultAccumulator(houseNumber));
|
||||
|
||||
int offsets[] = { 25, 50, 100, 200, 500 };
|
||||
int offsets[] = {25, 50, 100, 200, 500};
|
||||
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
@@ -1227,7 +1202,7 @@ void HouseDetector::GetHouseForName(string const & houseNumber, vector<HouseResu
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
end:
|
||||
ProduceVoting(acc, res, m_streets[i]);
|
||||
|
||||
for (size_t j = 0; j < acc.size(); ++j)
|
||||
@@ -1238,7 +1213,10 @@ end:
|
||||
res.erase(unique(res.begin(), res.end()), res.end());
|
||||
}
|
||||
|
||||
string DebugPrint(HouseProjection const & p) { return p.m_house->GetNumber(); }
|
||||
string DebugPrint(HouseProjection const & p)
|
||||
{
|
||||
return p.m_house->GetNumber();
|
||||
}
|
||||
|
||||
string DebugPrint(HouseResult const & r)
|
||||
{
|
||||
|
||||
@@ -76,7 +76,7 @@ struct HouseProjection : public ProjectionOnStreet
|
||||
{
|
||||
public:
|
||||
explicit EqualHouse(House const * h) : m_house(h) {}
|
||||
bool operator() (HouseProjection const * p) const { return m_house == p->m_house; }
|
||||
bool operator()(HouseProjection const * p) const { return m_house == p->m_house; }
|
||||
|
||||
private:
|
||||
House const * m_house;
|
||||
@@ -106,10 +106,7 @@ public:
|
||||
|
||||
double GetPrefixLength(size_t numSegs) const;
|
||||
|
||||
static bool IsSameStreets(Street const * s1, Street const * s2)
|
||||
{
|
||||
return s1->m_processedName == s2->m_processedName;
|
||||
}
|
||||
static bool IsSameStreets(Street const * s1, Street const * s2) { return s1->m_processedName == s2->m_processedName; }
|
||||
|
||||
void SetName(std::string_view name);
|
||||
std::string const & GetDbgName() const { return m_processedName; }
|
||||
@@ -137,10 +134,7 @@ public:
|
||||
|
||||
struct GreaterLength
|
||||
{
|
||||
bool operator() (MergedStreet const & s1, MergedStreet const & s2) const
|
||||
{
|
||||
return (s1.m_length > s2.m_length);
|
||||
}
|
||||
bool operator()(MergedStreet const & s1, MergedStreet const & s2) const { return (s1.m_length > s2.m_length); }
|
||||
};
|
||||
|
||||
MergedStreet() : m_length(0.0) {}
|
||||
@@ -190,9 +184,7 @@ private:
|
||||
|
||||
struct HouseResult
|
||||
{
|
||||
HouseResult(House const * house, MergedStreet const * street) : m_house(house), m_street(street)
|
||||
{
|
||||
}
|
||||
HouseResult(House const * house, MergedStreet const * street) : m_house(house), m_street(street) {}
|
||||
|
||||
bool operator<(HouseResult const & a) const { return m_house < a.m_house; }
|
||||
bool operator==(HouseResult const & a) const { return m_house == a.m_house; }
|
||||
|
||||
@@ -48,50 +48,27 @@ namespace
|
||||
// "way", "we", "west",
|
||||
|
||||
char const * g_strings[] = {
|
||||
"aa", "ab", "abc", "ac", "ad", "ae", "af", "ag",
|
||||
"ah", "ai", "aj", "ak", "al", "am", "an", "ao", "ap",
|
||||
"aq", "ar", "are", "as", "at", "au", "aw",
|
||||
"ax", "ay", "az", "azm", "ba", "bab", "bah", "bak",
|
||||
"bb", "bc", "bd", "be", "bedr", "ben", "bf", "bg", "bh",
|
||||
"bij", "bis", "bk", "bl", "bldg", "blk", "bloc", "block", "bloco",
|
||||
"blok", "bm", "bmn", "bn", "bo", "boe", "bol", "bor", "bov",
|
||||
"box", "bp", "br", "bra", "brc", "bs", "bsa", "bu", "building",
|
||||
"bv", "bwn", "bx", "by", "cab", "cat", "cbi", "cbu", "cc",
|
||||
"ccz", "cd", "ce", "centre", "cfn", "cgc", "cjg", "cl", "club",
|
||||
"cottage", "cottages", "cso", "cum", "db", "dd", "df",
|
||||
"dia", "dvu", "ec", "ee", "eh", "em", "en", "esm",
|
||||
"ev", "fdo", "fer", "ff", "flat", "flats", "floor",
|
||||
"gar", "gara", "gas", "gb", "gg", "gr",
|
||||
"grg", "ha", "haus", "hh", "hl", "ho", "house", "hr",
|
||||
"hs", "hv", "ii", "iii", "int", "iv", "ix",
|
||||
"jab", "jf", "jj", "jms", "jtg", "ka", "kab", "kk",
|
||||
"kmb", "kmk", "knn", "koy", "kp", "kra", "ksn", "kud",
|
||||
"ldo", "ll", "local", "loja", "lot", "lote",
|
||||
"lsb", "lt", "mac", "mad", "mah", "mak", "mat", "mb",
|
||||
"mbb", "mbn", "mch", "mei", "mks", "mm", "mny", "mo", "mok",
|
||||
"mor", "msb", "mtj", "mtk", "mvd", "na",
|
||||
"ncc", "nij", "nn", "no", "nr", "nst", "nu", "nut",
|
||||
"of", "ofof", "old", "one", "oo", "opl", "pa",
|
||||
"pap", "pav", "pb", "pch", "pg", "ph", "phd",
|
||||
"pkf", "plot", "po", "pos", "pp", "pr", "pra", "pya",
|
||||
"qq", "quater", "ra", "rbo", "rear", "reisach",
|
||||
"rk", "rm", "rosso", "rs", "rw",
|
||||
"sab", "sal", "sav", "sb", "sba", "sbb", "sbl", "sbn", "sbx",
|
||||
"sc", "sch", "sco", "seb", "sep", "sf", "sgr", "sir",
|
||||
"sj", "sl", "sm", "sn", "snc", "som", "sp",
|
||||
"spi", "spn", "ss", "sta", "stc", "std", "stiege",
|
||||
"suite", "sur", "tam", "ter", "terrace", "tf", "th", "the",
|
||||
"tl", "to", "torre", "tr", "traf", "trd", "ts", "tt", "tu",
|
||||
"uhm", "unit", "utc", "vii", "wa",
|
||||
"wf", "wink", "wrh", "ws", "wsb",
|
||||
"xx", "za", "zh", "zona", "zu", "zw", "א",
|
||||
"ב", "ג", "α", "бб", "бл", "вл",
|
||||
"вх", "лит", "разр", "стр", "тп", "уч", "участок", "ა",
|
||||
"丁目", "之", "号", "號",
|
||||
"aa", "ab", "abc", "ac", "ad", "ae", "af", "ag", "ah", "ai", "aj", "ak", "al", "am", "an", "ao", "ap", "aq", "ar",
|
||||
"are", "as", "at", "au", "aw", "ax", "ay", "az", "azm", "ba", "bab", "bah", "bak", "bb", "bc", "bd", "be", "bedr",
|
||||
"ben", "bf", "bg", "bh", "bij", "bis", "bk", "bl", "bldg", "blk", "bloc", "block", "bloco", "blok", "bm", "bmn",
|
||||
"bn", "bo", "boe", "bol", "bor", "bov", "box", "bp", "br", "bra", "brc", "bs", "bsa", "bu", "building", "bv", "bwn",
|
||||
"bx", "by", "cab", "cat", "cbi", "cbu", "cc", "ccz", "cd", "ce", "centre", "cfn", "cgc", "cjg", "cl", "club",
|
||||
"cottage", "cottages", "cso", "cum", "db", "dd", "df", "dia", "dvu", "ec", "ee", "eh", "em", "en", "esm", "ev",
|
||||
"fdo", "fer", "ff", "flat", "flats", "floor", "gar", "gara", "gas", "gb", "gg", "gr", "grg", "ha", "haus", "hh",
|
||||
"hl", "ho", "house", "hr", "hs", "hv", "ii", "iii", "int", "iv", "ix", "jab", "jf", "jj", "jms", "jtg", "ka", "kab",
|
||||
"kk", "kmb", "kmk", "knn", "koy", "kp", "kra", "ksn", "kud", "ldo", "ll", "local", "loja", "lot", "lote", "lsb",
|
||||
"lt", "mac", "mad", "mah", "mak", "mat", "mb", "mbb", "mbn", "mch", "mei", "mks", "mm", "mny", "mo", "mok", "mor",
|
||||
"msb", "mtj", "mtk", "mvd", "na", "ncc", "nij", "nn", "no", "nr", "nst", "nu", "nut", "of", "ofof", "old", "one",
|
||||
"oo", "opl", "pa", "pap", "pav", "pb", "pch", "pg", "ph", "phd", "pkf", "plot", "po", "pos", "pp", "pr", "pra",
|
||||
"pya", "qq", "quater", "ra", "rbo", "rear", "reisach", "rk", "rm", "rosso", "rs", "rw", "sab", "sal", "sav", "sb",
|
||||
"sba", "sbb", "sbl", "sbn", "sbx", "sc", "sch", "sco", "seb", "sep", "sf", "sgr", "sir", "sj", "sl", "sm", "sn",
|
||||
"snc", "som", "sp", "spi", "spn", "ss", "sta", "stc", "std", "stiege", "suite", "sur", "tam", "ter", "terrace",
|
||||
"tf", "th", "the", "tl", "to", "torre", "tr", "traf", "trd", "ts", "tt", "tu", "uhm", "unit", "utc", "vii", "wa",
|
||||
"wf", "wink", "wrh", "ws", "wsb", "xx", "za", "zh", "zona", "zu", "zw", "א", "ב", "ג", "α", "бб", "бл", "вл", "вх",
|
||||
"лит", "разр", "стр", "тп", "уч", "участок", "ა", "丁目", "之", "号", "號",
|
||||
|
||||
// List of exceptions
|
||||
"владение"
|
||||
};
|
||||
"владение"};
|
||||
|
||||
// Common strings in house numbers.
|
||||
// To get this list, just run:
|
||||
@@ -99,27 +76,20 @@ char const * g_strings[] = {
|
||||
// ./clusterize-tag-values.lisp house-number path-to-taginfo-db.db > numbers.txt
|
||||
// tail -n +2 numbers.txt | head -78 | sed 's/^.*) \(.*\) \[.*$/"\1"/g;s/[ -/]//g;s/$/,/' |
|
||||
// sort | uniq
|
||||
vector<string> const g_patterns = {
|
||||
"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
|
||||
"N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN", "NLNL",
|
||||
"NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS", "S",
|
||||
"SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS",
|
||||
vector<string> const g_patterns = {"BL", "BLN", "BLNSL", "BN", "BNL", "BNSL", "L", "LL", "LN", "LNL", "LNLN", "LNN",
|
||||
"N", "NBL", "NBLN", "NBN", "NBNBN", "NBNL", "NL", "NLBN", "NLL", "NLLN", "NLN",
|
||||
"NLNL", "NLS", "NLSN", "NN", "NNBN", "NNL", "NNLN", "NNN", "NNS", "NS", "NSN", "NSS",
|
||||
"S", "SL", "SLL", "SLN", "SN", "SNBNSS", "SNL", "SNN", "SS", "SSN", "SSS", "SSSS",
|
||||
|
||||
// List of exceptions
|
||||
"NNBNL"
|
||||
};
|
||||
// List of exceptions
|
||||
"NNBNL"};
|
||||
|
||||
// List of patterns which look like house numbers more than other patterns. Constructed by hand.
|
||||
vector<string> const g_patternsStrict = {
|
||||
"N", "NBN", "NBL", "NL"
|
||||
};
|
||||
|
||||
vector<string> const g_patternsStrict = {"N", "NBN", "NBL", "NL"};
|
||||
|
||||
// List of common synonyms for building parts. Constructed by hand.
|
||||
char const * g_buildingPartSynonyms[] = {
|
||||
"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус",
|
||||
"корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"
|
||||
};
|
||||
char const * g_buildingPartSynonyms[] = {"building", "bldg", "bld", "bl", "unit", "block", "blk", "корпус",
|
||||
"корп", "кор", "литер", "лит", "строение", "стр", "блок", "бл"};
|
||||
|
||||
// List of common stop words for buildings. Constructed by hand.
|
||||
UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house"), MakeUniString("д")};
|
||||
@@ -127,10 +97,8 @@ UniString const g_stopWords[] = {MakeUniString("дом"), MakeUniString("house")
|
||||
bool IsStopWord(UniString const & s, bool isPrefix)
|
||||
{
|
||||
for (auto const & p : g_stopWords)
|
||||
{
|
||||
if ((isPrefix && StartsWith(p, s)) || (!isPrefix && p == s))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -149,10 +117,7 @@ public:
|
||||
}
|
||||
|
||||
// Returns true if |s| looks like a building synonym.
|
||||
inline bool Has(UniString const & s) const
|
||||
{
|
||||
return m_synonyms.Has(s.begin(), s.end()) == Synonyms::Status::Full;
|
||||
}
|
||||
inline bool Has(UniString const & s) const { return m_synonyms.Has(s.begin(), s.end()) == Synonyms::Status::Full; }
|
||||
|
||||
private:
|
||||
Synonyms m_synonyms;
|
||||
@@ -205,10 +170,7 @@ public:
|
||||
HouseNumberClassifier(vector<string> const & patterns = g_patterns)
|
||||
{
|
||||
for (auto const & p : patterns)
|
||||
{
|
||||
m_patterns.Add(make_transform_iterator(p.begin(), &CharToType),
|
||||
make_transform_iterator(p.end(), &CharToType));
|
||||
}
|
||||
m_patterns.Add(make_transform_iterator(p.begin(), &CharToType), make_transform_iterator(p.end(), &CharToType));
|
||||
}
|
||||
|
||||
// Returns true when the string |s| looks like a valid house number,
|
||||
@@ -306,8 +268,7 @@ Token::Type GetCharType(UniChar c)
|
||||
|
||||
bool IsLiteralType(Token::Type type)
|
||||
{
|
||||
return type == Token::TYPE_STRING || type == Token::TYPE_LETTER ||
|
||||
type == Token::TYPE_BUILDING_PART_OR_LETTER;
|
||||
return type == Token::TYPE_STRING || type == Token::TYPE_LETTER || type == Token::TYPE_BUILDING_PART_OR_LETTER;
|
||||
}
|
||||
|
||||
// Leaves only numbers and letters, removes all trailing prefix
|
||||
@@ -368,10 +329,8 @@ bool IsShortBuildingSynonym(UniString const & t)
|
||||
{
|
||||
static UniString const kSynonyms[] = {MakeUniString("к"), MakeUniString("с")};
|
||||
for (auto const & s : kSynonyms)
|
||||
{
|
||||
if (t == s)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -458,10 +417,7 @@ uint64_t ToUInt(UniString const & s)
|
||||
void Tokenize(UniString s, bool isPrefix, TokensT & ts)
|
||||
{
|
||||
MakeLowerCaseInplace(s);
|
||||
auto addToken = [&ts](UniString && value, Token::Type type)
|
||||
{
|
||||
ts.emplace_back(std::move(value), type);
|
||||
};
|
||||
auto addToken = [&ts](UniString && value, Token::Type type) { ts.emplace_back(std::move(value), type); };
|
||||
|
||||
size_t i = 0;
|
||||
while (i < s.size())
|
||||
@@ -519,31 +475,29 @@ void ParseHouseNumber(UniString const & s, vector<TokensT> & parses)
|
||||
|
||||
bool numbersSequence = true;
|
||||
ForEachGroup(tokens, [&tokens, &numbersSequence](size_t i, size_t j)
|
||||
{
|
||||
switch (j - i)
|
||||
{
|
||||
case 0: break;
|
||||
case 1:
|
||||
numbersSequence = numbersSequence && tokens[i].m_type == Token::TYPE_NUMBER;
|
||||
break;
|
||||
case 2:
|
||||
numbersSequence = numbersSequence && tokens[i].m_type == Token::TYPE_NUMBER &&
|
||||
IsLiteralType(tokens[i + 1].m_type);
|
||||
break;
|
||||
default: numbersSequence = false; break;
|
||||
}
|
||||
});
|
||||
{
|
||||
switch (j - i)
|
||||
{
|
||||
case 0: break;
|
||||
case 1: numbersSequence = numbersSequence && tokens[i].m_type == Token::TYPE_NUMBER; break;
|
||||
case 2:
|
||||
numbersSequence =
|
||||
numbersSequence && tokens[i].m_type == Token::TYPE_NUMBER && IsLiteralType(tokens[i + 1].m_type);
|
||||
break;
|
||||
default: numbersSequence = false; break;
|
||||
}
|
||||
});
|
||||
|
||||
size_t const oldSize = parses.size();
|
||||
if (numbersSequence)
|
||||
{
|
||||
ForEachGroup(tokens, [&tokens, &parses](size_t i, size_t j)
|
||||
{
|
||||
parses.emplace_back();
|
||||
auto & parse = parses.back();
|
||||
for (size_t k = i; k < j; ++k)
|
||||
parse.emplace_back(std::move(tokens[k]));
|
||||
});
|
||||
{
|
||||
parses.emplace_back();
|
||||
auto & parse = parses.back();
|
||||
for (size_t k = i; k < j; ++k)
|
||||
parse.emplace_back(std::move(tokens[k]));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -597,13 +551,13 @@ bool HouseNumbersMatchConscription(UniString const & houseNumber, TokensT const
|
||||
if (i != end)
|
||||
{
|
||||
// Conscription number / street number.
|
||||
return HouseNumbersMatch(UniString(beg, i), queryParse) ||
|
||||
HouseNumbersMatch(UniString(i + 1, end), queryParse);
|
||||
return HouseNumbersMatch(UniString(beg, i), queryParse) || HouseNumbersMatch(UniString(i + 1, end), queryParse);
|
||||
}
|
||||
return HouseNumbersMatch(houseNumber, queryParse);
|
||||
}
|
||||
|
||||
bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & queryParse, feature::InterpolType interpol)
|
||||
bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & queryParse,
|
||||
feature::InterpolType interpol)
|
||||
{
|
||||
ASSERT(interpol != feature::InterpolType::None, ());
|
||||
|
||||
|
||||
@@ -35,10 +35,7 @@ struct Token
|
||||
Token & operator=(Token &&) = default;
|
||||
Token & operator=(Token const &) = default;
|
||||
|
||||
bool operator==(Token const & rhs) const
|
||||
{
|
||||
return m_type == rhs.m_type && m_value == rhs.m_value;
|
||||
}
|
||||
bool operator==(Token const & rhs) const { return m_type == rhs.m_type && m_value == rhs.m_value; }
|
||||
|
||||
bool operator!=(Token const & rhs) const { return !(*this == rhs); }
|
||||
|
||||
@@ -73,7 +70,8 @@ void ParseQuery(strings::UniString const & query, bool queryIsPrefix, TokensT &
|
||||
/// @{
|
||||
bool HouseNumbersMatch(strings::UniString const & houseNumber, TokensT const & queryParse);
|
||||
bool HouseNumbersMatchConscription(strings::UniString const & houseNumber, TokensT const & queryParse);
|
||||
bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & queryParse, feature::InterpolType interpol);
|
||||
bool HouseNumbersMatchRange(std::string_view const & hnRange, TokensT const & queryParse,
|
||||
feature::InterpolType interpol);
|
||||
/// @}
|
||||
|
||||
// Returns true if |s| looks like a house number.
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
uint32_t fID;
|
||||
if (!m_map->Get(houseId, fID))
|
||||
return {};
|
||||
return {{ fID, StreetIdType::FeatureId }};
|
||||
return {{fID, StreetIdType::FeatureId}};
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -99,7 +99,7 @@ unique_ptr<HouseToStreetTable> LoadHouseTableImpl(MwmValue const & value, std::s
|
||||
result = make_unique<DummyTable>();
|
||||
return result;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<HouseToStreetTable> LoadHouseToStreetTable(MwmValue const & value)
|
||||
{
|
||||
@@ -146,8 +146,7 @@ void HouseToStreetTableBuilder::Freeze(Writer & writer) const
|
||||
|
||||
header.m_tableOffset = base::asserted_cast<uint32_t>(writer.Pos() - startOffset);
|
||||
m_builder.Freeze(writer, writeBlockCallback);
|
||||
header.m_tableSize =
|
||||
base::asserted_cast<uint32_t>(writer.Pos() - header.m_tableOffset - startOffset);
|
||||
header.m_tableSize = base::asserted_cast<uint32_t>(writer.Pos() - header.m_tableOffset - startOffset);
|
||||
|
||||
auto const endOffset = writer.Pos();
|
||||
writer.Seek(startOffset);
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
|
||||
namespace search
|
||||
{
|
||||
IdfMap::IdfMap(Delegate const & delegate, double unknownIdf)
|
||||
: m_delegate(delegate), m_unknownIdf(unknownIdf)
|
||||
IdfMap::IdfMap(Delegate const & delegate, double unknownIdf) : m_delegate(delegate), m_unknownIdf(unknownIdf)
|
||||
{
|
||||
ASSERT_GREATER(m_unknownIdf, 0.0, ());
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
#include "indexer/ftypes_matcher.hpp"
|
||||
#include "indexer/road_shields_parser.hpp"
|
||||
|
||||
#include "platform/measurement_utils.hpp"
|
||||
#include "platform/localization.hpp"
|
||||
#include "platform/measurement_utils.hpp"
|
||||
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
@@ -34,10 +34,7 @@ class SkipRegionInfo
|
||||
public:
|
||||
SkipRegionInfo()
|
||||
{
|
||||
base::StringIL arr[] = {
|
||||
{"place", "continent"},
|
||||
{"place", "country"}
|
||||
};
|
||||
base::StringIL arr[] = {{"place", "continent"}, {"place", "country"}};
|
||||
static_assert(kCount == ARRAY_SIZE(arr), "");
|
||||
|
||||
Classificator const & c = classif();
|
||||
@@ -48,10 +45,8 @@ public:
|
||||
bool IsSkip(uint32_t type) const
|
||||
{
|
||||
for (uint32_t t : m_types)
|
||||
{
|
||||
if (t == type)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
@@ -60,10 +55,11 @@ public:
|
||||
// PreRankerResult ---------------------------------------------------------------------------------
|
||||
PreRankerResult::PreRankerResult(FeatureID const & id, PreRankingInfo const & info,
|
||||
vector<ResultTracer::Branch> const & provenance)
|
||||
: m_id(id), m_info(info)
|
||||
, m_isRelaxed(base::IsExist(provenance, ResultTracer::Branch::Relaxed))
|
||||
: m_id(id)
|
||||
, m_info(info)
|
||||
, m_isRelaxed(base::IsExist(provenance, ResultTracer::Branch::Relaxed))
|
||||
#ifdef SEARCH_USE_PROVENANCE
|
||||
, m_provenance(provenance)
|
||||
, m_provenance(provenance)
|
||||
#endif
|
||||
{
|
||||
ASSERT(m_id.IsValid(), ());
|
||||
@@ -104,7 +100,7 @@ int PreRankerResult::CompareByTokensMatch(PreRankerResult const & lhs, PreRanker
|
||||
return lRange.Size() > rRange.Size() ? -1 : 1;
|
||||
|
||||
if (lhs.m_matchedTokensNumber != rhs.m_matchedTokensNumber)
|
||||
return lhs.m_matchedTokensNumber > rhs.m_matchedTokensNumber ? -1 : 1;
|
||||
return lhs.m_matchedTokensNumber > rhs.m_matchedTokensNumber ? -1 : 1;
|
||||
|
||||
if (lRange.Begin() != rRange.Begin())
|
||||
return lRange.Begin() < rRange.Begin() ? -1 : 1;
|
||||
@@ -123,8 +119,7 @@ bool PreRankerResult::LessByExactMatch(PreRankerResult const & lhs, PreRankerRes
|
||||
return CompareByTokensMatch(lhs, rhs) == -1;
|
||||
}
|
||||
|
||||
bool PreRankerResult::CategoriesComparator::operator()(PreRankerResult const & lhs,
|
||||
PreRankerResult const & rhs) const
|
||||
bool PreRankerResult::CategoriesComparator::operator()(PreRankerResult const & lhs, PreRankerResult const & rhs) const
|
||||
{
|
||||
if (m_positionIsInsideViewport)
|
||||
return lhs.GetDistance() < rhs.GetDistance();
|
||||
@@ -145,17 +140,14 @@ std::string DebugPrint(PreRankerResult const & r)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "PreRankerResult "
|
||||
<< "{ FID: " << r.GetId().m_index // index is enough here for debug purpose
|
||||
<< "; m_matchedTokensNumber: " << r.m_matchedTokensNumber
|
||||
<< "; m_isRelaxed: " << r.m_isRelaxed
|
||||
<< "; " << DebugPrint(r.m_info)
|
||||
<< " }";
|
||||
<< "{ FID: " << r.GetId().m_index // index is enough here for debug purpose
|
||||
<< "; m_matchedTokensNumber: " << r.m_matchedTokensNumber << "; m_isRelaxed: " << r.m_isRelaxed << "; "
|
||||
<< DebugPrint(r.m_info) << " }";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
// RankerResult ------------------------------------------------------------------------------------
|
||||
RankerResult::RankerResult(FeatureType & ft, m2::PointD const & center,
|
||||
string displayName, string const & fileName)
|
||||
RankerResult::RankerResult(FeatureType & ft, m2::PointD const & center, string displayName, string const & fileName)
|
||||
: m_types(ft)
|
||||
, m_str(std::move(displayName))
|
||||
, m_id(ft.GetID())
|
||||
@@ -173,19 +165,19 @@ RankerResult::RankerResult(FeatureType & ft, m2::PointD const & center,
|
||||
}
|
||||
|
||||
RankerResult::RankerResult(FeatureType & ft, std::string const & fileName)
|
||||
: RankerResult(ft, feature::GetCenter(ft, FeatureType::WORST_GEOMETRY),
|
||||
std::string(ft.GetReadableName()), fileName)
|
||||
{
|
||||
}
|
||||
: RankerResult(ft, feature::GetCenter(ft, FeatureType::WORST_GEOMETRY), std::string(ft.GetReadableName()), fileName)
|
||||
{}
|
||||
|
||||
RankerResult::RankerResult(double lat, double lon)
|
||||
: m_str("(" + measurement_utils::FormatLatLon(lat, lon) + ")"), m_resultType(Type::LatLon)
|
||||
: m_str("(" + measurement_utils::FormatLatLon(lat, lon) + ")")
|
||||
, m_resultType(Type::LatLon)
|
||||
{
|
||||
m_region.SetParams({}, mercator::FromLatLon(lat, lon));
|
||||
}
|
||||
|
||||
RankerResult::RankerResult(m2::PointD const & coord, string_view postcode)
|
||||
: m_str(postcode), m_resultType(Type::Postcode)
|
||||
: m_str(postcode)
|
||||
, m_resultType(Type::Postcode)
|
||||
{
|
||||
strings::AsciiToUpper(m_str);
|
||||
m_region.SetParams({}, coord);
|
||||
@@ -202,9 +194,7 @@ bool RankerResult::GetCountryId(storage::CountryInfoGetter const & infoGetter, u
|
||||
|
||||
bool RankerResult::IsEqualBasic(RankerResult const & r) const
|
||||
{
|
||||
return (m_geomType == r.m_geomType &&
|
||||
GetRankingInfo().m_type == r.GetRankingInfo().m_type &&
|
||||
m_str == r.m_str);
|
||||
return (m_geomType == r.m_geomType && GetRankingInfo().m_type == r.GetRankingInfo().m_type && m_str == r.m_str);
|
||||
}
|
||||
|
||||
bool RankerResult::IsEqualCommon(RankerResult const & r) const
|
||||
@@ -212,7 +202,10 @@ bool RankerResult::IsEqualCommon(RankerResult const & r) const
|
||||
return (IsEqualBasic(r) && GetBestType() == r.GetBestType());
|
||||
}
|
||||
|
||||
bool RankerResult::IsStreet() const { return ftypes::IsStreetOrSquareChecker::Instance()(m_types); }
|
||||
bool RankerResult::IsStreet() const
|
||||
{
|
||||
return ftypes::IsStreetOrSquareChecker::Instance()(m_types);
|
||||
}
|
||||
|
||||
uint32_t RankerResult::GetBestType(vector<uint32_t> const * preferredTypes /* = nullptr */) const
|
||||
{
|
||||
@@ -220,10 +213,8 @@ uint32_t RankerResult::GetBestType(vector<uint32_t> const * preferredTypes /* =
|
||||
{
|
||||
ASSERT(is_sorted(preferredTypes->begin(), preferredTypes->end()), ());
|
||||
for (uint32_t type : m_types)
|
||||
{
|
||||
if (binary_search(preferredTypes->begin(), preferredTypes->end(), type))
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return m_types.GetBestType();
|
||||
@@ -257,7 +248,7 @@ void FillDetails(FeatureType & ft, std::string const & name, Result::Details & d
|
||||
|
||||
std::string_view airportIata = ft.GetMetadata(feature::Metadata::FMD_AIRPORT_IATA);
|
||||
|
||||
std::string brand {ft.GetMetadata(feature::Metadata::FMD_BRAND)};
|
||||
std::string brand{ft.GetMetadata(feature::Metadata::FMD_BRAND)};
|
||||
if (!brand.empty())
|
||||
brand = platform::GetLocalizedBrandName(brand);
|
||||
|
||||
@@ -297,7 +288,8 @@ void FillDetails(FeatureType & ft, std::string const & name, Result::Details & d
|
||||
auto const cuisines = feature::GetLocalizedCuisines(typesHolder);
|
||||
auto const cuisine = strings::JoinStrings(cuisines, feature::kFieldsSeparator);
|
||||
|
||||
auto const recycling = strings::JoinStrings(feature::GetLocalizedRecyclingTypes(typesHolder), feature::kFieldsSeparator);
|
||||
auto const recycling =
|
||||
strings::JoinStrings(feature::GetLocalizedRecyclingTypes(typesHolder), feature::kFieldsSeparator);
|
||||
|
||||
auto const roadShields = ftypes::GetRoadShieldsNames(ft);
|
||||
auto const roadShield = strings::JoinStrings(roadShields, feature::kFieldsSeparator);
|
||||
@@ -335,14 +327,13 @@ string DebugPrint(RankerResult const & r)
|
||||
{
|
||||
stringstream ss;
|
||||
ss << "RankerResult "
|
||||
<< "{ FID: " << r.GetID().m_index // index is enough here for debug purpose
|
||||
<< "; Name: " << r.GetName()
|
||||
<< "; Type: " << classif().GetReadableObjectName(r.GetBestType())
|
||||
<< "{ FID: " << r.GetID().m_index // index is enough here for debug purpose
|
||||
<< "; Name: " << r.GetName() << "; Type: " << classif().GetReadableObjectName(r.GetBestType())
|
||||
<< "; Linear model rank: " << r.GetLinearModelRank();
|
||||
|
||||
#ifdef SEARCH_USE_PROVENANCE
|
||||
if (!r.m_provenance.empty())
|
||||
ss << "; Provenance: " << ::DebugPrint(r.m_provenance);
|
||||
if (!r.m_provenance.empty())
|
||||
ss << "; Provenance: " << ::DebugPrint(r.m_provenance);
|
||||
#endif
|
||||
|
||||
if (r.m_dbgInfo)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace storage
|
||||
{
|
||||
class CountryInfoGetter;
|
||||
struct CountryInfo;
|
||||
}
|
||||
} // namespace storage
|
||||
|
||||
namespace search
|
||||
{
|
||||
@@ -62,8 +62,8 @@ public:
|
||||
std::vector<ResultTracer::Branch> const & GetProvenance() const { return m_provenance; }
|
||||
#endif
|
||||
|
||||
//size_t GetInnermostTokensNumber() const { return m_info.InnermostTokenRange().Size(); }
|
||||
//size_t GetMatchedTokensNumber() const { return m_matchedTokensNumber; }
|
||||
// size_t GetInnermostTokensNumber() const { return m_info.InnermostTokenRange().Size(); }
|
||||
// size_t GetMatchedTokensNumber() const { return m_matchedTokensNumber; }
|
||||
bool IsNotRelaxed() const { return !m_isRelaxed; }
|
||||
|
||||
bool SkipForViewportSearch(size_t queryTokensNumber) const
|
||||
@@ -109,8 +109,7 @@ public:
|
||||
};
|
||||
|
||||
/// For Type::Feature and Type::Building.
|
||||
RankerResult(FeatureType & ft, m2::PointD const & center,
|
||||
std::string displayName, std::string const & fileName);
|
||||
RankerResult(FeatureType & ft, m2::PointD const & center, std::string displayName, std::string const & fileName);
|
||||
RankerResult(FeatureType & ft, std::string const & fileName);
|
||||
|
||||
/// For Type::LatLon.
|
||||
@@ -168,8 +167,7 @@ private:
|
||||
m_point = point;
|
||||
}
|
||||
|
||||
bool GetCountryId(storage::CountryInfoGetter const & infoGetter,
|
||||
storage::CountryId & countryId) const;
|
||||
bool GetCountryId(storage::CountryInfoGetter const & infoGetter, storage::CountryId & countryId) const;
|
||||
};
|
||||
|
||||
RegionInfo m_region;
|
||||
@@ -178,7 +176,7 @@ private:
|
||||
Result::Details m_details;
|
||||
|
||||
StoredRankingInfo m_info;
|
||||
std::shared_ptr<RankingInfo> m_dbgInfo; // used in debug logs and tests, nullptr in production
|
||||
std::shared_ptr<RankingInfo> m_dbgInfo; // used in debug logs and tests, nullptr in production
|
||||
|
||||
FeatureID m_id;
|
||||
double m_finalRank;
|
||||
|
||||
@@ -26,9 +26,7 @@ void IntersectionResult::Set(Model::Type type, uint32_t id)
|
||||
case Model::TYPE_STATE:
|
||||
case Model::TYPE_COUNTRY:
|
||||
case Model::TYPE_UNCLASSIFIED:
|
||||
case Model::TYPE_COUNT:
|
||||
ASSERT(false, ("Unsupported type."));
|
||||
break;
|
||||
case Model::TYPE_COUNT: ASSERT(false, ("Unsupported type.")); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,15 +24,9 @@ struct IntersectionResult
|
||||
|
||||
// Building == Streets means that we have actual street result, but got here
|
||||
// via _fake_ TYPE_BUILDING layer (see MatchPOIsAndBuildings).
|
||||
inline bool IsFakeBuildingButStreet() const
|
||||
{
|
||||
return m_building != kInvalidId && m_building == m_street;
|
||||
}
|
||||
inline bool IsFakeBuildingButStreet() const { return m_building != kInvalidId && m_building == m_street; }
|
||||
|
||||
inline bool IsPoiAndComplexPoi() const
|
||||
{
|
||||
return m_complexPoi != kInvalidId && m_subpoi != kInvalidId;
|
||||
}
|
||||
inline bool IsPoiAndComplexPoi() const { return m_complexPoi != kInvalidId && m_subpoi != kInvalidId; }
|
||||
|
||||
// Clears all fields to an invalid state.
|
||||
void Clear();
|
||||
|
||||
@@ -97,8 +97,7 @@ void IntervalSet<Elem>::Add(Interval const & interval)
|
||||
}
|
||||
|
||||
template <typename Elem>
|
||||
void IntervalSet<Elem>::SubtractFrom(Interval const & interval,
|
||||
std::vector<Interval> & difference) const
|
||||
void IntervalSet<Elem>::SubtractFrom(Interval const & interval, std::vector<Interval> & difference) const
|
||||
{
|
||||
Iterator begin;
|
||||
Iterator end;
|
||||
|
||||
@@ -15,14 +15,12 @@ using namespace std;
|
||||
namespace search
|
||||
{
|
||||
// KeywordLangMatcher::Score ----------------------------------------------------------------------
|
||||
KeywordLangMatcher::Score::Score() : m_langScore(numeric_limits<int>::min())
|
||||
{
|
||||
}
|
||||
KeywordLangMatcher::Score::Score() : m_langScore(numeric_limits<int>::min()) {}
|
||||
|
||||
KeywordLangMatcher::Score::Score(KeywordMatcher::Score const & score, int langScore)
|
||||
: m_parentScore(score), m_langScore(langScore)
|
||||
{
|
||||
}
|
||||
: m_parentScore(score)
|
||||
, m_langScore(langScore)
|
||||
{}
|
||||
|
||||
bool KeywordLangMatcher::Score::operator<(KeywordLangMatcher::Score const & score) const
|
||||
{
|
||||
@@ -40,8 +38,7 @@ bool KeywordLangMatcher::Score::operator<=(KeywordLangMatcher::Score const & sco
|
||||
return !(score < *this);
|
||||
}
|
||||
// KeywordLangMatcher ------------------------------------------------------------------------------
|
||||
KeywordLangMatcher::KeywordLangMatcher(size_t maxLanguageTiers)
|
||||
: m_languagePriorities(maxLanguageTiers)
|
||||
KeywordLangMatcher::KeywordLangMatcher(size_t maxLanguageTiers) : m_languagePriorities(maxLanguageTiers)
|
||||
{
|
||||
// Should we ever have this many tiers, the idea of storing a vector of vectors must be revised.
|
||||
ASSERT_LESS(maxLanguageTiers, 10, ());
|
||||
@@ -59,10 +56,8 @@ int KeywordLangMatcher::CalcLangScore(int8_t lang) const
|
||||
for (int i = 0; i < numTiers; ++i)
|
||||
{
|
||||
for (int8_t x : m_languagePriorities[i])
|
||||
{
|
||||
if (x == lang)
|
||||
return -i;
|
||||
}
|
||||
}
|
||||
|
||||
return -numTiers;
|
||||
@@ -73,14 +68,12 @@ KeywordLangMatcher::Score KeywordLangMatcher::CalcScore(int8_t lang, string_view
|
||||
return Score(m_keywordMatcher.CalcScore(name), CalcLangScore(lang));
|
||||
}
|
||||
|
||||
KeywordLangMatcher::Score KeywordLangMatcher::CalcScore(int8_t lang,
|
||||
strings::UniString const & name) const
|
||||
KeywordLangMatcher::Score KeywordLangMatcher::CalcScore(int8_t lang, strings::UniString const & name) const
|
||||
{
|
||||
return Score(m_keywordMatcher.CalcScore(name), CalcLangScore(lang));
|
||||
}
|
||||
|
||||
KeywordLangMatcher::Score KeywordLangMatcher::CalcScore(int8_t lang,
|
||||
strings::UniString const * tokens,
|
||||
KeywordLangMatcher::Score KeywordLangMatcher::CalcScore(int8_t lang, strings::UniString const * tokens,
|
||||
size_t count) const
|
||||
{
|
||||
return Score(m_keywordMatcher.CalcScore(tokens, count), CalcLangScore(lang));
|
||||
|
||||
@@ -43,17 +43,12 @@ public:
|
||||
void ForEachLanguage(Fn && fn) const
|
||||
{
|
||||
for (auto const & langs : m_languagePriorities)
|
||||
{
|
||||
for (int8_t lang : langs)
|
||||
fn(lang);
|
||||
}
|
||||
}
|
||||
|
||||
// Store references to keywords from source array of strings.
|
||||
inline void SetKeywords(QueryString const & query)
|
||||
{
|
||||
m_keywordMatcher.SetKeywords(query);
|
||||
}
|
||||
inline void SetKeywords(QueryString const & query) { m_keywordMatcher.SetKeywords(query); }
|
||||
|
||||
// Returns the Score of the name (greater is better).
|
||||
Score CalcScore(int8_t lang, std::string_view name) const;
|
||||
|
||||
@@ -44,8 +44,7 @@ KeywordMatcher::Score KeywordMatcher::CalcScore(strings::UniString const & name)
|
||||
return CalcScore(tokens.data(), tokens.size());
|
||||
}
|
||||
|
||||
KeywordMatcher::Score KeywordMatcher::CalcScore(strings::UniString const * tokens,
|
||||
size_t count) const
|
||||
KeywordMatcher::Score KeywordMatcher::CalcScore(strings::UniString const * tokens, size_t count) const
|
||||
{
|
||||
// Some names can have too many tokens. Trim them.
|
||||
count = min(count, kMaxNumTokens);
|
||||
@@ -87,10 +86,8 @@ KeywordMatcher::Score KeywordMatcher::CalcScore(strings::UniString const * token
|
||||
|
||||
uint8_t numQueryTokensMatched = 0;
|
||||
for (size_t i = 0; i < isQueryTokenMatched.size(); ++i)
|
||||
{
|
||||
if (isQueryTokenMatched[i])
|
||||
++numQueryTokensMatched;
|
||||
}
|
||||
|
||||
Score score;
|
||||
score.m_fullQueryMatched = prefixMatched && (numQueryTokensMatched == isQueryTokenMatched.size());
|
||||
@@ -117,8 +114,7 @@ KeywordMatcher::Score::Score()
|
||||
, m_numQueryTokensAndPrefixMatched(0)
|
||||
, m_fullQueryMatched(false)
|
||||
, m_prefixMatched(false)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
bool KeywordMatcher::Score::operator<(KeywordMatcher::Score const & s) const
|
||||
{
|
||||
@@ -138,11 +134,9 @@ bool KeywordMatcher::Score::operator<(KeywordMatcher::Score const & s) const
|
||||
|
||||
bool KeywordMatcher::Score::operator==(KeywordMatcher::Score const & s) const
|
||||
{
|
||||
return m_sumTokenMatchDistance == s.m_sumTokenMatchDistance
|
||||
&& m_nameTokensMatched == s.m_nameTokensMatched
|
||||
&& m_numQueryTokensAndPrefixMatched == s.m_numQueryTokensAndPrefixMatched
|
||||
&& m_fullQueryMatched == s.m_fullQueryMatched
|
||||
&& m_prefixMatched == s.m_prefixMatched;
|
||||
return m_sumTokenMatchDistance == s.m_sumTokenMatchDistance && m_nameTokensMatched == s.m_nameTokensMatched &&
|
||||
m_numQueryTokensAndPrefixMatched == s.m_numQueryTokensAndPrefixMatched &&
|
||||
m_fullQueryMatched == s.m_fullQueryMatched && m_prefixMatched == s.m_prefixMatched;
|
||||
}
|
||||
|
||||
bool KeywordMatcher::Score::LessInTokensLength(Score const & s) const
|
||||
|
||||
@@ -43,7 +43,7 @@ void Skip(Char *& s)
|
||||
++s;
|
||||
}
|
||||
|
||||
bool MatchDMSArray(char const * & s, char const * arr[], size_t count)
|
||||
bool MatchDMSArray(char const *& s, char const * arr[], size_t count)
|
||||
{
|
||||
for (size_t i = 0; i < count; ++i)
|
||||
{
|
||||
@@ -57,14 +57,14 @@ bool MatchDMSArray(char const * & s, char const * arr[], size_t count)
|
||||
return false;
|
||||
}
|
||||
|
||||
int GetDMSIndex(char const * & s)
|
||||
int GetDMSIndex(char const *& s)
|
||||
{
|
||||
char const * arrDegree[] = { "*", "°" };
|
||||
char const * arrMinutes[] = { "\'", "’", "′" };
|
||||
char const * arrSeconds[] = { "\"", "”", "″", "\'\'", "’’", "′′" };
|
||||
char const * arrDegree[] = {"*", "°"};
|
||||
char const * arrMinutes[] = {"\'", "’", "′"};
|
||||
char const * arrSeconds[] = {"\"", "”", "″", "\'\'", "’’", "′′"};
|
||||
|
||||
if (MatchDMSArray(s, arrDegree, ARRAY_SIZE(arrDegree)))
|
||||
return 0;
|
||||
return 0;
|
||||
if (MatchDMSArray(s, arrSeconds, ARRAY_SIZE(arrSeconds)))
|
||||
return 2;
|
||||
if (MatchDMSArray(s, arrMinutes, ARRAY_SIZE(arrMinutes)))
|
||||
@@ -73,17 +73,21 @@ int GetDMSIndex(char const * & s)
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SkipNSEW(char const * & s, char const * (&arrPos) [4])
|
||||
bool SkipNSEW(char const *& s, char const * (&arrPos)[4])
|
||||
{
|
||||
Skip(s);
|
||||
|
||||
int ind;
|
||||
switch (*s)
|
||||
{
|
||||
case 'N': case 'n': ind = 0; break;
|
||||
case 'S': case 's': ind = 1; break;
|
||||
case 'E': case 'e': ind = 2; break;
|
||||
case 'W': case 'w': ind = 3; break;
|
||||
case 'N':
|
||||
case 'n': ind = 0; break;
|
||||
case 'S':
|
||||
case 's': ind = 1; break;
|
||||
case 'E':
|
||||
case 'e': ind = 2; break;
|
||||
case 'W':
|
||||
case 'w': ind = 3; break;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
@@ -157,7 +161,7 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
||||
|
||||
// Positions of N, S, E, W symbols
|
||||
char const * arrPos[] = {nullptr, nullptr, nullptr, nullptr};
|
||||
bool arrDegreeSymbol[] = { false, false };
|
||||
bool arrDegreeSymbol[] = {false, false};
|
||||
|
||||
char const * const startQuery = query.c_str();
|
||||
char const * s = startQuery;
|
||||
@@ -195,7 +199,7 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (x < 0 && s == s1 && !(s == startQuery || kSpaces.find(*(s-1)) != string::npos))
|
||||
else if (x < 0 && s == s1 && !(s == startQuery || kSpaces.find(*(s - 1)) != string::npos))
|
||||
{
|
||||
// Skip input like "3-8"
|
||||
return false;
|
||||
@@ -223,7 +227,7 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) // degrees
|
||||
if (i == 0) // degrees
|
||||
{
|
||||
if (v[base].second)
|
||||
{
|
||||
@@ -239,8 +243,7 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
||||
}
|
||||
arrDegreeSymbol[base / 3] = degreeSymbol;
|
||||
}
|
||||
else // minutes or seconds
|
||||
{
|
||||
else // minutes or seconds
|
||||
if (x < 0.0 || x > 60.0 || // minutes or seconds should be in [0, 60] range
|
||||
v[base + i].second || // value already exists
|
||||
!v[base].second || // no degrees found for value
|
||||
@@ -248,7 +251,6 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
v[base + i].first = x;
|
||||
v[base + i].second = true;
|
||||
@@ -268,10 +270,12 @@ bool MatchLatLonDegree(string const & query, double & lat, double & lon)
|
||||
|
||||
// Calculate Lat, Lon with correct sign.
|
||||
lat = fabs(v[0].first) + v[1].first / 60.0 + v[2].first / 3600.0;
|
||||
if (v[0].first < 0.0) lat = -lat;
|
||||
if (v[0].first < 0.0)
|
||||
lat = -lat;
|
||||
|
||||
lon = fabs(v[3].first) + v[4].first / 60.0 + v[5].first / 3600.0;
|
||||
if (v[3].first < 0.0) lon = -lon;
|
||||
if (v[3].first < 0.0)
|
||||
lon = -lon;
|
||||
|
||||
if (max(arrPos[0], arrPos[1]) > max(arrPos[2], arrPos[3]))
|
||||
swap(lat, lon);
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
namespace search
|
||||
{
|
||||
LazyCentersTable::LazyCentersTable(MwmValue const & value)
|
||||
: m_value(value), m_state(STATE_NOT_LOADED), m_reader(std::unique_ptr<ModelReader>())
|
||||
{
|
||||
}
|
||||
: m_value(value)
|
||||
, m_state(STATE_NOT_LOADED)
|
||||
, m_reader(std::unique_ptr<ModelReader>())
|
||||
{}
|
||||
|
||||
void LazyCentersTable::EnsureTableLoaded()
|
||||
{
|
||||
@@ -33,17 +34,11 @@ void LazyCentersTable::EnsureTableLoaded()
|
||||
auto const format = traits.GetCentersTableFormat();
|
||||
|
||||
if (format == version::MwmTraits::CentersTableFormat::PlainEliasFanoMap)
|
||||
{
|
||||
m_table = CentersTable::LoadV0(*m_reader.GetPtr(), m_value.GetHeader().GetDefGeometryCodingParams());
|
||||
}
|
||||
else if (format == version::MwmTraits::CentersTableFormat::EliasFanoMapWithHeader)
|
||||
{
|
||||
m_table = CentersTable::LoadV1(*m_reader.GetPtr());
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(false, ("Unknown centers table format."));
|
||||
}
|
||||
|
||||
if (m_table)
|
||||
m_state = STATE_LOADED;
|
||||
|
||||
@@ -57,16 +57,14 @@ private:
|
||||
class LocalitiesLoader
|
||||
{
|
||||
public:
|
||||
LocalitiesLoader(MwmContext const & ctx, CitiesBoundariesTable const & boundaries,
|
||||
Filter const & filter, LocalityFinder::Holder & holder,
|
||||
map<MwmSet::MwmId, unordered_set<uint32_t>> & loadedIds)
|
||||
LocalitiesLoader(MwmContext const & ctx, CitiesBoundariesTable const & boundaries, Filter const & filter,
|
||||
LocalityFinder::Holder & holder, map<MwmSet::MwmId, unordered_set<uint32_t>> & loadedIds)
|
||||
: m_ctx(ctx)
|
||||
, m_boundaries(boundaries)
|
||||
, m_filter(filter)
|
||||
, m_holder(holder)
|
||||
, m_loadedIds(loadedIds[m_ctx.GetId()])
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void operator()(uint32_t id) const
|
||||
{
|
||||
@@ -88,10 +86,8 @@ public:
|
||||
{
|
||||
case LocalityType::City:
|
||||
case LocalityType::Town:
|
||||
case LocalityType::Village:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
case LocalityType::Village: break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
auto const population = ftypes::GetPopulation(*ft);
|
||||
@@ -131,19 +127,21 @@ int GetVillagesScale()
|
||||
// Needed for backward compatibility. |kCompatibilityVillagesMinDrawableScale| should be set to
|
||||
// maximal value we have in mwms over all data versions.
|
||||
int const kCompatibilityVillagesMinDrawableScale = 13;
|
||||
ASSERT_LESS_OR_EQUAL(
|
||||
currentVillagesMinDrawableScale, kCompatibilityVillagesMinDrawableScale,
|
||||
("Set kCompatibilityVillagesMinDrawableScale to", currentVillagesMinDrawableScale));
|
||||
ASSERT_LESS_OR_EQUAL(currentVillagesMinDrawableScale, kCompatibilityVillagesMinDrawableScale,
|
||||
("Set kCompatibilityVillagesMinDrawableScale to", currentVillagesMinDrawableScale));
|
||||
return max(currentVillagesMinDrawableScale, kCompatibilityVillagesMinDrawableScale);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// LocalityItem ------------------------------------------------------------------------------------
|
||||
LocalityItem::LocalityItem(StringUtf8Multilang const & names, m2::PointD const & center,
|
||||
Boundaries && boundaries, uint64_t population, FeatureID const & id)
|
||||
: m_names(names), m_center(center), m_boundaries(std::move(boundaries)), m_population(population), m_id(id)
|
||||
{
|
||||
}
|
||||
LocalityItem::LocalityItem(StringUtf8Multilang const & names, m2::PointD const & center, Boundaries && boundaries,
|
||||
uint64_t population, FeatureID const & id)
|
||||
: m_names(names)
|
||||
, m_center(center)
|
||||
, m_boundaries(std::move(boundaries))
|
||||
, m_population(population)
|
||||
, m_id(id)
|
||||
{}
|
||||
|
||||
string DebugPrint(LocalityItem const & item)
|
||||
{
|
||||
@@ -167,8 +165,7 @@ void LocalitySelector::operator()(LocalityItem const & item)
|
||||
double const distance = mercator::DistanceOnEarth(item.m_center, m_p);
|
||||
|
||||
// GetPopulationByRadius may return 0.
|
||||
double const score =
|
||||
(ftypes::GetPopulationByRadius(distance) + 1) / static_cast<double>(item.m_population);
|
||||
double const score = (ftypes::GetPopulationByRadius(distance) + 1) / static_cast<double>(item.m_population);
|
||||
|
||||
if (!inside && m_inside)
|
||||
return;
|
||||
@@ -203,8 +200,7 @@ void LocalityFinder::Holder::Add(LocalityItem const & item)
|
||||
m_localities.Add(item, m2::RectD(item.m_center, item.m_center));
|
||||
}
|
||||
|
||||
void LocalityFinder::Holder::ForEachInVicinity(m2::RectD const & rect,
|
||||
LocalitySelector & selector) const
|
||||
void LocalityFinder::Holder::ForEachInVicinity(m2::RectD const & rect, LocalitySelector & selector) const
|
||||
{
|
||||
m_localities.ForEachInRect(rect, selector);
|
||||
}
|
||||
@@ -226,8 +222,7 @@ void LocalityFinder::Holder::Clear()
|
||||
}
|
||||
|
||||
// LocalityFinder ----------------------------------------------------------------------------------
|
||||
LocalityFinder::LocalityFinder(DataSource const & dataSource,
|
||||
CitiesBoundariesTable const & boundariesTable,
|
||||
LocalityFinder::LocalityFinder(DataSource const & dataSource, CitiesBoundariesTable const & boundariesTable,
|
||||
VillagesCache & villagesCache)
|
||||
: m_dataSource(dataSource)
|
||||
, m_boundariesTable(boundariesTable)
|
||||
@@ -235,8 +230,7 @@ LocalityFinder::LocalityFinder(DataSource const & dataSource,
|
||||
, m_cities(kMaxCityRadiusMeters)
|
||||
, m_villages(kMaxVillageRadiusMeters)
|
||||
, m_mapsLoaded(false)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void LocalityFinder::ClearCache()
|
||||
{
|
||||
@@ -268,8 +262,7 @@ void LocalityFinder::LoadVicinity(m2::PointD const & p, bool loadCities, bool lo
|
||||
m_ranks = make_unique<DummyRankTable>();
|
||||
|
||||
MwmContext ctx(std::move(handle));
|
||||
ctx.ForEachIndex(crect, LocalitiesLoader(ctx, m_boundariesTable, CityFilter(*m_ranks),
|
||||
m_cities, m_loadedIds));
|
||||
ctx.ForEachIndex(crect, LocalitiesLoader(ctx, m_boundariesTable, CityFilter(*m_ranks), m_cities, m_loadedIds));
|
||||
}
|
||||
|
||||
m_cities.SetCovered(p);
|
||||
@@ -278,16 +271,17 @@ void LocalityFinder::LoadVicinity(m2::PointD const & p, bool loadCities, bool lo
|
||||
if (loadVillages)
|
||||
{
|
||||
m2::RectD const vrect = m_villages.GetDRect(p);
|
||||
m_maps.ForEachInRect(m2::RectD(p, p), [&](MwmSet::MwmId const & id) {
|
||||
m_maps.ForEachInRect(m2::RectD(p, p), [&](MwmSet::MwmId const & id)
|
||||
{
|
||||
auto handle = m_dataSource.GetMwmHandleById(id);
|
||||
if (!handle.IsAlive())
|
||||
return;
|
||||
|
||||
static int const scale = GetVillagesScale();
|
||||
MwmContext ctx(std::move(handle));
|
||||
ctx.ForEachIndex(vrect, scale,
|
||||
LocalitiesLoader(ctx, m_boundariesTable, VillageFilter(ctx, m_villagesCache),
|
||||
m_villages, m_loadedIds));
|
||||
ctx.ForEachIndex(
|
||||
vrect, scale,
|
||||
LocalitiesLoader(ctx, m_boundariesTable, VillageFilter(ctx, m_villagesCache), m_villages, m_loadedIds));
|
||||
});
|
||||
|
||||
m_villages.SetCovered(p);
|
||||
|
||||
@@ -34,8 +34,8 @@ struct LocalityItem
|
||||
{
|
||||
using Boundaries = CitiesBoundariesTable::Boundaries;
|
||||
|
||||
LocalityItem(StringUtf8Multilang const & names, m2::PointD const & center,
|
||||
Boundaries && boundaries, uint64_t population, FeatureID const & id);
|
||||
LocalityItem(StringUtf8Multilang const & names, m2::PointD const & center, Boundaries && boundaries,
|
||||
uint64_t population, FeatureID const & id);
|
||||
|
||||
bool GetName(int8_t lang, std::string_view & name) const { return m_names.GetString(lang, name); }
|
||||
|
||||
@@ -51,8 +51,8 @@ struct LocalityItem
|
||||
return false;
|
||||
|
||||
feature::NameParamsOut out;
|
||||
feature::GetReadableName({ m_names, mwmInfo->GetRegionData(), languages::GetCurrentMapLanguage(),
|
||||
false /* allowTranslit */ }, out);
|
||||
feature::GetReadableName(
|
||||
{m_names, mwmInfo->GetRegionData(), languages::GetCurrentMapLanguage(), false /* allowTranslit */}, out);
|
||||
|
||||
name = out.primary;
|
||||
return !name.empty();
|
||||
@@ -127,8 +127,7 @@ public:
|
||||
m2::RectD const crect = m_cities.GetRect(p);
|
||||
m2::RectD const vrect = m_villages.GetRect(p);
|
||||
|
||||
LoadVicinity(p, !m_cities.IsCovered(crect) /* loadCities */,
|
||||
!m_villages.IsCovered(vrect) /* loadVillages */);
|
||||
LoadVicinity(p, !m_cities.IsCovered(crect) /* loadCities */, !m_villages.IsCovered(vrect) /* loadVillages */);
|
||||
|
||||
LocalitySelector selector(p);
|
||||
m_cities.ForEachInVicinity(crect, selector);
|
||||
|
||||
@@ -29,9 +29,9 @@ class IdfMapDelegate : public IdfMap::Delegate
|
||||
public:
|
||||
IdfMapDelegate(vector<pair<LevenshteinDFA, uint64_t>> const & tokensToDf,
|
||||
vector<pair<PrefixDFA, uint64_t>> const & prefixToDf)
|
||||
: m_tokensToDf(tokensToDf), m_prefixToDf(prefixToDf)
|
||||
{
|
||||
}
|
||||
: m_tokensToDf(tokensToDf)
|
||||
, m_prefixToDf(prefixToDf)
|
||||
{}
|
||||
|
||||
~IdfMapDelegate() override = default;
|
||||
|
||||
@@ -70,20 +70,20 @@ size_t constexpr kDefaultReadLimit = 100;
|
||||
|
||||
// LocalityScorer::ExLocality ----------------------------------------------------------------------
|
||||
LocalityScorer::ExLocality::ExLocality(Locality && locality, double queryNorm, uint8_t rank)
|
||||
: m_locality(std::move(locality)), m_queryNorm(queryNorm), m_rank(rank)
|
||||
{
|
||||
}
|
||||
: m_locality(std::move(locality))
|
||||
, m_queryNorm(queryNorm)
|
||||
, m_rank(rank)
|
||||
{}
|
||||
|
||||
// LocalityScorer ----------------------------------------------------------------------------------
|
||||
LocalityScorer::LocalityScorer(QueryParams const & params, m2::PointD const & pivot,
|
||||
Delegate & delegate)
|
||||
: m_params(params), m_pivot(pivot), m_delegate(delegate)
|
||||
{
|
||||
}
|
||||
LocalityScorer::LocalityScorer(QueryParams const & params, m2::PointD const & pivot, Delegate & delegate)
|
||||
: m_params(params)
|
||||
, m_pivot(pivot)
|
||||
, m_delegate(delegate)
|
||||
{}
|
||||
|
||||
void LocalityScorer::GetTopLocalities(MwmSet::MwmId const & countryId, BaseContext const & ctx,
|
||||
CBV const & filter, size_t limit,
|
||||
vector<Locality> & localities)
|
||||
void LocalityScorer::GetTopLocalities(MwmSet::MwmId const & countryId, BaseContext const & ctx, CBV const & filter,
|
||||
size_t limit, vector<Locality> & localities)
|
||||
{
|
||||
double constexpr kUnknownIdf = 1.0;
|
||||
size_t const numTokens = ctx.NumTokens();
|
||||
@@ -104,9 +104,8 @@ void LocalityScorer::GetTopLocalities(MwmSet::MwmId const & countryId, BaseConte
|
||||
{
|
||||
auto const & token = m_params.GetToken(i);
|
||||
tokensToDf.emplace_back(BuildLevenshteinDFA(token.GetOriginal()), df);
|
||||
token.ForEachSynonym([&tokensToDf, &df](UniString const & s) {
|
||||
tokensToDf.emplace_back(strings::LevenshteinDFA(s, 0 /* maxErrors */), df);
|
||||
});
|
||||
token.ForEachSynonym([&tokensToDf, &df](UniString const & s)
|
||||
{ tokensToDf.emplace_back(strings::LevenshteinDFA(s, 0 /* maxErrors */), df); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,9 +118,8 @@ void LocalityScorer::GetTopLocalities(MwmSet::MwmId const & countryId, BaseConte
|
||||
{
|
||||
auto const & token = m_params.GetToken(count);
|
||||
prefixToDf.emplace_back(PrefixDFA(BuildLevenshteinDFA(token.GetOriginal())), prefixDf);
|
||||
token.ForEachSynonym([&prefixToDf, &prefixDf](UniString const & s) {
|
||||
prefixToDf.emplace_back(PrefixDFA(strings::LevenshteinDFA(s, 0 /* maxErrors */)), prefixDf);
|
||||
});
|
||||
token.ForEachSynonym([&prefixToDf, &prefixDf](UniString const & s)
|
||||
{ prefixToDf.emplace_back(PrefixDFA(strings::LevenshteinDFA(s, 0 /* maxErrors */)), prefixDf); });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,8 +131,7 @@ void LocalityScorer::GetTopLocalities(MwmSet::MwmId const & countryId, BaseConte
|
||||
auto intersection = intersections[startToken];
|
||||
QueryVec::Builder builder;
|
||||
|
||||
for (size_t endToken = startToken + 1;
|
||||
endToken <= numTokens && !intersection.m_features.IsEmpty(); ++endToken)
|
||||
for (size_t endToken = startToken + 1; endToken <= numTokens && !intersection.m_features.IsEmpty(); ++endToken)
|
||||
{
|
||||
auto const curToken = endToken - 1;
|
||||
auto const & token = m_params.GetToken(curToken).GetOriginal();
|
||||
@@ -148,9 +145,7 @@ void LocalityScorer::GetTopLocalities(MwmSet::MwmId const & countryId, BaseConte
|
||||
if (!m_params.IsNumberTokens(tokenRange))
|
||||
{
|
||||
intersection.ForEach([&](uint32_t featureId, bool exactMatch)
|
||||
{
|
||||
localities.emplace_back(FeatureID(countryId, featureId), tokenRange, QueryVec(idfs, builder), exactMatch);
|
||||
});
|
||||
{ localities.emplace_back(FeatureID(countryId, featureId), tokenRange, QueryVec(idfs, builder), exactMatch); });
|
||||
}
|
||||
|
||||
if (endToken < numTokens)
|
||||
@@ -196,8 +191,7 @@ void LocalityScorer::LeaveTopLocalities(IdfMap & idfs, size_t limit, vector<Loca
|
||||
GetDocVecs(els[i].GetId(), dvs);
|
||||
|
||||
auto const center = m_delegate.GetCenter(els[i].GetId());
|
||||
auto const distance =
|
||||
center ? mercator::DistanceOnEarth(m_pivot, *center) : els[i].m_distanceToPivot;
|
||||
auto const distance = center ? mercator::DistanceOnEarth(m_pivot, *center) : els[i].m_distanceToPivot;
|
||||
auto const belongsToMatchedRegion =
|
||||
center ? m_delegate.BelongsToMatchedRegion(*center) : els[i].m_belongsToMatchedRegion;
|
||||
|
||||
@@ -216,15 +210,12 @@ void LocalityScorer::LeaveTopLocalities(IdfMap & idfs, size_t limit, vector<Loca
|
||||
|
||||
unordered_set<uint32_t> seen;
|
||||
for (auto it = els.begin(); it != els.end() && localities.size() < limit; ++it)
|
||||
{
|
||||
if (seen.insert(it->GetId()).second)
|
||||
localities.push_back(std::move(it->m_locality));
|
||||
}
|
||||
ASSERT_EQUAL(seen.size(), localities.size(), ());
|
||||
}
|
||||
|
||||
void LocalityScorer::LeaveTopByExactMatchNormAndRank(size_t limitUniqueIds,
|
||||
vector<ExLocality> & els) const
|
||||
void LocalityScorer::LeaveTopByExactMatchNormAndRank(size_t limitUniqueIds, vector<ExLocality> & els) const
|
||||
{
|
||||
sort(els.begin(), els.end(), [](ExLocality const & lhs, ExLocality const & rhs)
|
||||
{
|
||||
@@ -264,9 +255,7 @@ void LocalityScorer::GroupBySimilarityAndOther(vector<ExLocality> & els) const
|
||||
});
|
||||
|
||||
auto const lessDistance = [](ExLocality const & lhs, ExLocality const & rhs)
|
||||
{
|
||||
return lhs.m_distanceToPivot < rhs.m_distanceToPivot;
|
||||
};
|
||||
{ return lhs.m_distanceToPivot < rhs.m_distanceToPivot; };
|
||||
|
||||
auto const compareSimilaritySizeAndRegion = [](ExLocality const & lhs, ExLocality const & rhs)
|
||||
{
|
||||
@@ -291,10 +280,8 @@ void LocalityScorer::GroupBySimilarityAndOther(vector<ExLocality> & els) const
|
||||
auto const closest = min_element(range.first, range.second, lessDistance);
|
||||
tmp.emplace_back(std::move(*closest));
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
if (it != closest)
|
||||
tmp.emplace_back(std::move(*it));
|
||||
}
|
||||
begin = range.second;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,8 @@ public:
|
||||
|
||||
// Leaves at most |limit| elements of |localities|, ordered by their
|
||||
// features.
|
||||
void GetTopLocalities(MwmSet::MwmId const & countryId, BaseContext const & ctx,
|
||||
CBV const & filter, size_t limit, std::vector<Locality> & localities);
|
||||
void GetTopLocalities(MwmSet::MwmId const & countryId, BaseContext const & ctx, CBV const & filter, size_t limit,
|
||||
std::vector<Locality> & localities);
|
||||
|
||||
private:
|
||||
struct ExLocality
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
using namespace ftypes;
|
||||
@@ -23,32 +22,30 @@ class IsComplexPoiChecker : public ftypes::BaseChecker
|
||||
{
|
||||
// For MatchPOIsWithParent matching. Some entries may be controversial here, but keep as-is for now.
|
||||
// POI near "Complex POI" matching.
|
||||
base::StringIL const paths[] = {
|
||||
{"aeroway", "aerodrome"},
|
||||
{"amenity", "hospital"},
|
||||
{"amenity", "university"},
|
||||
{"building", "train_station"},
|
||||
{"historic", "archaeological_site"},
|
||||
{"historic", "castle"},
|
||||
{"historic", "fort"},
|
||||
{"landuse", "cemetery"},
|
||||
{"landuse", "religious"},
|
||||
{"landuse", "commercial"},
|
||||
{"landuse", "forest"},
|
||||
{"landuse", "industrial"},
|
||||
{"landuse", "retail"},
|
||||
{"leisure", "garden"},
|
||||
{"leisure", "nature_reserve"},
|
||||
{"leisure", "park"},
|
||||
{"leisure", "stadium"},
|
||||
{"leisure", "water_park"},
|
||||
{"natural", "beach"},
|
||||
{"office", "company"},
|
||||
{"railway", "station"},
|
||||
{"shop", "mall"},
|
||||
{"tourism", "museum"},
|
||||
{"tourism", "gallery"}
|
||||
};
|
||||
base::StringIL const paths[] = {{"aeroway", "aerodrome"},
|
||||
{"amenity", "hospital"},
|
||||
{"amenity", "university"},
|
||||
{"building", "train_station"},
|
||||
{"historic", "archaeological_site"},
|
||||
{"historic", "castle"},
|
||||
{"historic", "fort"},
|
||||
{"landuse", "cemetery"},
|
||||
{"landuse", "religious"},
|
||||
{"landuse", "commercial"},
|
||||
{"landuse", "forest"},
|
||||
{"landuse", "industrial"},
|
||||
{"landuse", "retail"},
|
||||
{"leisure", "garden"},
|
||||
{"leisure", "nature_reserve"},
|
||||
{"leisure", "park"},
|
||||
{"leisure", "stadium"},
|
||||
{"leisure", "water_park"},
|
||||
{"natural", "beach"},
|
||||
{"office", "company"},
|
||||
{"railway", "station"},
|
||||
{"shop", "mall"},
|
||||
{"tourism", "museum"},
|
||||
{"tourism", "gallery"}};
|
||||
|
||||
Classificator const & c = classif();
|
||||
for (auto const & path : paths)
|
||||
|
||||
@@ -42,10 +42,7 @@ public:
|
||||
TYPE_COUNT
|
||||
};
|
||||
|
||||
static bool IsLocalityType(Type const type)
|
||||
{
|
||||
return type >= TYPE_VILLAGE && type <= TYPE_COUNTRY;
|
||||
}
|
||||
static bool IsLocalityType(Type const type) { return type >= TYPE_VILLAGE && type <= TYPE_COUNTRY; }
|
||||
|
||||
static bool IsPoi(Type const type) { return type == TYPE_SUBPOI || type == TYPE_COMPLEX_POI; }
|
||||
static bool IsPoiOrBuilding(Type const type) { return IsPoi(type) || type == TYPE_BUILDING; }
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "indexer/fake_feature_ids.hpp"
|
||||
#include "indexer/feature_source.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
void CoverRect(m2::RectD const & rect, int scale, covering::Intervals & result)
|
||||
@@ -22,11 +21,9 @@ MwmContext::MwmContext(MwmSet::MwmHandle handle)
|
||||
, m_index(m_value.m_cont.GetReader(INDEX_FILE_TAG), m_value.m_factory)
|
||||
, m_centers(m_value)
|
||||
, m_editableSource(m_handle)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
MwmContext::MwmContext(MwmSet::MwmHandle handle, MwmType type)
|
||||
: MwmContext(std::move(handle))
|
||||
MwmContext::MwmContext(MwmSet::MwmHandle handle, MwmType type) : MwmContext(std::move(handle))
|
||||
{
|
||||
m_type = type;
|
||||
}
|
||||
@@ -37,8 +34,7 @@ std::unique_ptr<FeatureType> MwmContext::GetFeature(uint32_t index) const
|
||||
switch (GetEditedStatus(index))
|
||||
{
|
||||
case FeatureStatus::Deleted:
|
||||
case FeatureStatus::Obsolete:
|
||||
return ft;
|
||||
case FeatureStatus::Obsolete: return ft;
|
||||
case FeatureStatus::Modified:
|
||||
case FeatureStatus::Created:
|
||||
ft = m_editableSource.GetModifiedFeature(index);
|
||||
|
||||
@@ -61,12 +61,12 @@ public:
|
||||
void ForEachIndex(covering::Intervals const & intervals, uint32_t scale, Fn && fn) const
|
||||
{
|
||||
ForEachIndexImpl(intervals, scale, [&](uint32_t index)
|
||||
{
|
||||
// TODO: Optimize deleted checks by getting vector of deleted indexes from
|
||||
// the Editor.
|
||||
if (GetEditedStatus(index) != FeatureStatus::Deleted)
|
||||
fn(index);
|
||||
});
|
||||
{
|
||||
// TODO: Optimize deleted checks by getting vector of deleted indexes from
|
||||
// the Editor.
|
||||
if (GetEditedStatus(index) != FeatureStatus::Deleted)
|
||||
fn(index);
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
@@ -91,7 +91,8 @@ public:
|
||||
covering::Intervals intervals;
|
||||
CoverRect(rect, scale, intervals);
|
||||
|
||||
ForEachIndexImpl(intervals, scale, [&](uint32_t index) {
|
||||
ForEachIndexImpl(intervals, scale, [&](uint32_t index)
|
||||
{
|
||||
auto ft = GetFeature(index);
|
||||
if (ft)
|
||||
fn(*ft);
|
||||
@@ -101,10 +102,7 @@ public:
|
||||
// Returns false if feature was deleted by user.
|
||||
std::unique_ptr<FeatureType> GetFeature(uint32_t index) const;
|
||||
|
||||
[[nodiscard]] inline bool GetCenter(uint32_t index, m2::PointD & center)
|
||||
{
|
||||
return m_centers.Get(index, center);
|
||||
}
|
||||
[[nodiscard]] inline bool GetCenter(uint32_t index, m2::PointD & center) { return m_centers.Get(index, center); }
|
||||
|
||||
std::optional<uint32_t> GetStreet(uint32_t index) const;
|
||||
|
||||
@@ -112,22 +110,18 @@ public:
|
||||
MwmValue & m_value;
|
||||
|
||||
private:
|
||||
FeatureStatus GetEditedStatus(uint32_t index) const
|
||||
{
|
||||
return m_editableSource.GetFeatureStatus(index);
|
||||
}
|
||||
FeatureStatus GetEditedStatus(uint32_t index) const { return m_editableSource.GetFeatureStatus(index); }
|
||||
|
||||
template <class Fn>
|
||||
void ForEachIndexImpl(covering::Intervals const & intervals, uint32_t scale, Fn && fn) const
|
||||
{
|
||||
CheckUniqueIndexes checkUnique;
|
||||
for (auto const & i : intervals)
|
||||
m_index.ForEachInIntervalAndScale(i.first, i.second, scale,
|
||||
[&](uint64_t /* key */, uint32_t value)
|
||||
{
|
||||
if (checkUnique(value))
|
||||
fn(value);
|
||||
});
|
||||
m_index.ForEachInIntervalAndScale(i.first, i.second, scale, [&](uint64_t /* key */, uint32_t value)
|
||||
{
|
||||
if (checkUnique(value))
|
||||
fn(value);
|
||||
});
|
||||
}
|
||||
|
||||
FeaturesVector m_vector;
|
||||
|
||||
@@ -20,9 +20,11 @@ double const kPositionToleranceMeters = 15.0;
|
||||
} // namespace
|
||||
|
||||
NestedRectsCache::NestedRectsCache(DataSource const & dataSource)
|
||||
: m_dataSource(dataSource), m_scale(0), m_position(0, 0), m_valid(false)
|
||||
{
|
||||
}
|
||||
: m_dataSource(dataSource)
|
||||
, m_scale(0)
|
||||
, m_position(0, 0)
|
||||
, m_valid(false)
|
||||
{}
|
||||
|
||||
void NestedRectsCache::SetPosition(m2::PointD const & position, int scale)
|
||||
{
|
||||
@@ -92,8 +94,8 @@ void NestedRectsCache::Update()
|
||||
auto & bucket = m_buckets[scale];
|
||||
bucket.clear();
|
||||
|
||||
m2::RectD const rect = mercator::RectByCenterXYAndSizeInMeters(
|
||||
m_position, GetRadiusMeters(static_cast<RectScale>(scale)));
|
||||
m2::RectD const rect =
|
||||
mercator::RectByCenterXYAndSizeInMeters(m_position, GetRadiusMeters(static_cast<RectScale>(scale)));
|
||||
|
||||
MwmSet::MwmId lastId;
|
||||
Features * lastFeatures = nullptr;
|
||||
|
||||
@@ -81,9 +81,7 @@ public:
|
||||
case Event::TYPE_SEGMENT_START: tree.Add(e.m_segment); break;
|
||||
case Event::TYPE_POINT:
|
||||
{
|
||||
auto const segmentFn = [&](SegmentTree::Segment const & segment) {
|
||||
fn(e.m_point.m_id, segment.m_id);
|
||||
};
|
||||
auto const segmentFn = [&](SegmentTree::Segment const & segment) { fn(e.m_point.m_id, segment.m_id); };
|
||||
switch (requestType)
|
||||
{
|
||||
case RequestType::Any: tree.FindAny(e.m_point.m_x, segmentFn); break;
|
||||
@@ -116,15 +114,12 @@ private:
|
||||
TYPE_SEGMENT_END,
|
||||
};
|
||||
|
||||
Event(Type type, SegmentEvent const & segment, double time)
|
||||
: m_segment(segment), m_time(time), m_type(type)
|
||||
Event(Type type, SegmentEvent const & segment, double time) : m_segment(segment), m_time(time), m_type(type)
|
||||
{
|
||||
ASSERT(m_type == TYPE_SEGMENT_START || m_type == TYPE_SEGMENT_END, ());
|
||||
}
|
||||
|
||||
Event(PointEvent const & point, double time) : m_point(point), m_time(time), m_type(TYPE_POINT)
|
||||
{
|
||||
}
|
||||
Event(PointEvent const & point, double time) : m_point(point), m_time(time), m_type(TYPE_POINT) {}
|
||||
|
||||
bool operator<(Event const & rhs) const
|
||||
{
|
||||
@@ -133,7 +128,8 @@ private:
|
||||
return m_type < rhs.m_type;
|
||||
}
|
||||
|
||||
union {
|
||||
union
|
||||
{
|
||||
SegmentEvent m_segment;
|
||||
PointEvent m_point;
|
||||
};
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
#include "defines.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
using namespace std;
|
||||
@@ -38,31 +37,26 @@ PostcodePoints::PostcodePoints(MwmValue const & value)
|
||||
m_header.Read(*reader.GetPtr());
|
||||
|
||||
m_trieSubReader = reader.GetPtr()->CreateSubReader(m_header.m_trieOffset, m_header.m_trieSize);
|
||||
m_root = trie::ReadTrie<SubReaderWrapper<Reader>, SingleUint64Value>(
|
||||
SubReaderWrapper<Reader>(m_trieSubReader.get()), SingleValueSerializer<Uint64IndexValue>());
|
||||
m_root = trie::ReadTrie<SubReaderWrapper<Reader>, SingleUint64Value>(SubReaderWrapper<Reader>(m_trieSubReader.get()),
|
||||
SingleValueSerializer<Uint64IndexValue>());
|
||||
CHECK(m_root, ());
|
||||
|
||||
version::MwmTraits traits(value.GetMwmVersion());
|
||||
auto const format = traits.GetCentersTableFormat();
|
||||
CHECK_EQUAL(format, version::MwmTraits::CentersTableFormat::EliasFanoMapWithHeader,
|
||||
("Unexpected format."));
|
||||
CHECK_EQUAL(format, version::MwmTraits::CentersTableFormat::EliasFanoMapWithHeader, ("Unexpected format."));
|
||||
|
||||
m_pointsSubReader =
|
||||
reader.GetPtr()->CreateSubReader(m_header.m_pointsOffset, m_header.m_pointsSize);
|
||||
m_pointsSubReader = reader.GetPtr()->CreateSubReader(m_header.m_pointsOffset, m_header.m_pointsSize);
|
||||
m_points = CentersTable::LoadV1(*m_pointsSubReader);
|
||||
CHECK(m_points, ());
|
||||
|
||||
auto const kPostcodeRadiusMultiplier = 5.0;
|
||||
auto const area = value.GetHeader().GetBounds().Area();
|
||||
auto const count = static_cast<double>(m_points->Count());
|
||||
CHECK_NOT_EQUAL(
|
||||
count, 0.0,
|
||||
("Zero postcodes should not be serialized to", POSTCODE_POINTS_FILE_TAG, "section"));
|
||||
CHECK_NOT_EQUAL(count, 0.0, ("Zero postcodes should not be serialized to", POSTCODE_POINTS_FILE_TAG, "section"));
|
||||
m_radius = kPostcodeRadiusMultiplier * 0.5 * sqrt(area / count);
|
||||
}
|
||||
|
||||
void PostcodePoints::Get(UniString const & postcode, bool recursive,
|
||||
vector<m2::PointD> & points) const
|
||||
void PostcodePoints::Get(UniString const & postcode, bool recursive, vector<m2::PointD> & points) const
|
||||
{
|
||||
if (!m_root || !m_points || !m_trieSubReader || !m_pointsSubReader || postcode.empty())
|
||||
return;
|
||||
@@ -73,9 +67,7 @@ void PostcodePoints::Get(UniString const & postcode, bool recursive,
|
||||
while (postcodeIt != postcode.end())
|
||||
{
|
||||
auto it = find_if(trieIt->m_edges.begin(), trieIt->m_edges.end(), [&](auto const & edge)
|
||||
{
|
||||
return StartsWith(postcodeIt, postcode.end(), edge.m_label.begin(), edge.m_label.end());
|
||||
});
|
||||
{ return StartsWith(postcodeIt, postcode.end(), edge.m_label.begin(), edge.m_label.end()); });
|
||||
if (it == trieIt->m_edges.end())
|
||||
return;
|
||||
|
||||
@@ -88,19 +80,12 @@ void PostcodePoints::Get(UniString const & postcode, bool recursive,
|
||||
|
||||
vector<uint32_t> indexes;
|
||||
trieIt->m_values.ForEach([&indexes](auto const & v)
|
||||
{
|
||||
indexes.push_back(base::asserted_cast<uint32_t>(v.m_featureId));
|
||||
});
|
||||
{ indexes.push_back(base::asserted_cast<uint32_t>(v.m_featureId)); });
|
||||
|
||||
if (recursive)
|
||||
{
|
||||
trie::ForEachRef(
|
||||
*trieIt,
|
||||
[&indexes](auto const & /* s */, auto const & v)
|
||||
{
|
||||
indexes.push_back(base::asserted_cast<uint32_t>(v.m_featureId));
|
||||
},
|
||||
UniString{});
|
||||
trie::ForEachRef(*trieIt, [&indexes](auto const & /* s */, auto const & v)
|
||||
{ indexes.push_back(base::asserted_cast<uint32_t>(v.m_featureId)); }, UniString{});
|
||||
}
|
||||
|
||||
points.resize(indexes.size());
|
||||
|
||||
@@ -58,8 +58,7 @@ public:
|
||||
double GetRadius() const { return m_radius; }
|
||||
|
||||
private:
|
||||
void Get(strings::UniString const & postcode, bool recursive,
|
||||
std::vector<m2::PointD> & points) const;
|
||||
void Get(strings::UniString const & postcode, bool recursive, std::vector<m2::PointD> & points) const;
|
||||
|
||||
Header m_header;
|
||||
std::unique_ptr<CentersTable> m_points;
|
||||
|
||||
@@ -51,7 +51,7 @@ void SweepNearbyResults(m2::PointD const & eps, unordered_set<FeatureID> const &
|
||||
uint8_t const exactMatch = results[i].GetInfo().m_exactMatch ? 6 : 0;
|
||||
|
||||
// We prefer result which passed the filter even if it has lower rank / popularity / exactMatch.
|
||||
//uint8_t const filterPassed = results[i].GetInfo().m_refusedByFilter ? 0 : 2;
|
||||
// uint8_t const filterPassed = results[i].GetInfo().m_refusedByFilter ? 0 : 2;
|
||||
// We prefer result from prevEmit over result with better filterPassed because otherwise we have
|
||||
// lots of blinking results.
|
||||
uint8_t const prevCount = prevEmit.count(results[i].GetId()) == 0 ? 0 : 3;
|
||||
@@ -61,20 +61,18 @@ void SweepNearbyResults(m2::PointD const & eps, unordered_set<FeatureID> const &
|
||||
|
||||
vector<PreRankerResult> filtered;
|
||||
filtered.reserve(results.size());
|
||||
sweeper.Sweep([&filtered, &results](size_t i)
|
||||
{
|
||||
filtered.push_back(std::move(results[i]));
|
||||
});
|
||||
sweeper.Sweep([&filtered, &results](size_t i) { filtered.push_back(std::move(results[i])); });
|
||||
|
||||
results.swap(filtered);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
PreRanker::PreRanker(DataSource const & dataSource, Ranker & ranker)
|
||||
: m_dataSource(dataSource), m_ranker(ranker), m_pivotFeatures(dataSource)
|
||||
, m_rndSeed(std::random_device()())
|
||||
{
|
||||
}
|
||||
: m_dataSource(dataSource)
|
||||
, m_ranker(ranker)
|
||||
, m_pivotFeatures(dataSource)
|
||||
, m_rndSeed(std::random_device()())
|
||||
{}
|
||||
|
||||
void PreRanker::Init(Params const & params)
|
||||
{
|
||||
@@ -160,19 +158,17 @@ void PreRanker::FillMissingFieldsInPreResults()
|
||||
|
||||
namespace
|
||||
{
|
||||
template <class CompT, class ContT> class CompareIndices
|
||||
template <class CompT, class ContT>
|
||||
class CompareIndices
|
||||
{
|
||||
CompT m_cmp;
|
||||
ContT const & m_cont;
|
||||
|
||||
public:
|
||||
CompareIndices(CompT const & cmp, ContT const & cont) : m_cmp(cmp), m_cont(cont) {}
|
||||
bool operator()(size_t l, size_t r) const
|
||||
{
|
||||
return m_cmp(m_cont[l], m_cont[r]);
|
||||
}
|
||||
bool operator()(size_t l, size_t r) const { return m_cmp(m_cont[l], m_cont[r]); }
|
||||
};
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
void PreRanker::DbgFindAndLog(std::set<uint32_t> const & ids) const
|
||||
{
|
||||
@@ -206,7 +202,7 @@ void PreRanker::Filter()
|
||||
return;
|
||||
|
||||
std::vector<size_t> indices(m_results.size());
|
||||
std::generate(indices.begin(), indices.end(), [n = 0] () mutable { return n++; });
|
||||
std::generate(indices.begin(), indices.end(), [n = 0]() mutable { return n++; });
|
||||
std::unordered_set<size_t> filtered;
|
||||
|
||||
auto const iBeg = indices.begin();
|
||||
@@ -235,9 +231,9 @@ void PreRanker::Filter()
|
||||
PreRankerResult::CategoriesComparator comparator;
|
||||
comparator.m_positionIsInsideViewport =
|
||||
m_params.m_position && m_params.m_viewport.IsPointInside(*m_params.m_position);
|
||||
comparator.m_detailedScale = mercator::DistanceOnEarth(m_params.m_viewport.LeftTop(),
|
||||
m_params.m_viewport.RightBottom()) <
|
||||
2 * kPedestrianRadiusMeters;
|
||||
comparator.m_detailedScale =
|
||||
mercator::DistanceOnEarth(m_params.m_viewport.LeftTop(), m_params.m_viewport.RightBottom()) <
|
||||
2 * kPedestrianRadiusMeters;
|
||||
comparator.m_viewport = m_params.m_viewport;
|
||||
|
||||
std::nth_element(iBeg, iMiddle, iEnd, CompareIndices(comparator, m_results));
|
||||
@@ -306,10 +302,7 @@ void PreRanker::FilterRelaxedResults(bool lastUpdate)
|
||||
}
|
||||
else
|
||||
{
|
||||
auto const it = partition(m_results.begin(), iEnd, [](PreRankerResult const & res)
|
||||
{
|
||||
return res.IsNotRelaxed();
|
||||
});
|
||||
auto const it = partition(m_results.begin(), iEnd, [](PreRankerResult const & res) { return res.IsNotRelaxed(); });
|
||||
|
||||
m_relaxedResults.insert(m_relaxedResults.end(), make_move_iterator(it), make_move_iterator(iEnd));
|
||||
m_results.erase(it, iEnd);
|
||||
|
||||
@@ -25,7 +25,8 @@ class PreRanker
|
||||
public:
|
||||
struct Params
|
||||
{
|
||||
// Minimal distance between search results (by x,y axes in mercator), needed for filtering of viewport search results.
|
||||
// Minimal distance between search results (by x,y axes in mercator), needed for filtering of viewport search
|
||||
// results.
|
||||
m2::PointD m_minDistanceOnMapBetweenResults{0, 0};
|
||||
|
||||
// This is different from geocoder's pivot because pivot is
|
||||
@@ -83,8 +84,7 @@ public:
|
||||
size_t Size() const { return m_results.size() + m_relaxedResults.size(); }
|
||||
size_t BatchSize() const
|
||||
{
|
||||
return m_params.m_viewportSearch ? std::numeric_limits<size_t>::max()
|
||||
: m_params.m_everywhereBatchSize;
|
||||
return m_params.m_viewportSearch ? std::numeric_limits<size_t>::max() : m_params.m_everywhereBatchSize;
|
||||
}
|
||||
size_t NumSentResults() const { return m_numSentResults; }
|
||||
bool ContinueSearch() const { return !m_haveFullyMatchedResult || Size() < BatchSize(); }
|
||||
@@ -126,7 +126,8 @@ public:
|
||||
}
|
||||
|
||||
processed.insert(mwmId);
|
||||
} while (nextAssigned);
|
||||
}
|
||||
while (nextAssigned);
|
||||
}
|
||||
|
||||
void ClearCaches();
|
||||
|
||||
@@ -8,8 +8,7 @@ std::string DebugPrint(PreRankingInfo const & info)
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << std::boolalpha << "PreRankingInfo "
|
||||
<< "{ m_distanceToPivot: " << info.m_distanceToPivot
|
||||
<< ", m_tokenRanges [ ";
|
||||
<< "{ m_distanceToPivot: " << info.m_distanceToPivot << ", m_tokenRanges [ ";
|
||||
for (size_t i = 0; i < Model::TYPE_COUNT; ++i)
|
||||
{
|
||||
if (info.m_tokenRanges[i].Empty())
|
||||
@@ -19,13 +18,9 @@ std::string DebugPrint(PreRankingInfo const & info)
|
||||
os << DebugPrint(type) << " : " << DebugPrint(info.m_tokenRanges[i]) << ", ";
|
||||
}
|
||||
os << " ]"
|
||||
<< ", m_rank: " << static_cast<int>(info.m_rank)
|
||||
<< ", m_popularity: " << static_cast<int>(info.m_popularity)
|
||||
<< ", m_type: " << DebugPrint(info.m_type)
|
||||
<< ", m_allTokensUsed: " << info.m_allTokensUsed
|
||||
<< ", m_exactMatch: " << info.m_exactMatch
|
||||
<< ", m_isCommonMatchOnly: " << info.m_isCommonMatchOnly
|
||||
<< " }";
|
||||
<< ", m_rank: " << static_cast<int>(info.m_rank) << ", m_popularity: " << static_cast<int>(info.m_popularity)
|
||||
<< ", m_type: " << DebugPrint(info.m_type) << ", m_allTokensUsed: " << info.m_allTokensUsed
|
||||
<< ", m_exactMatch: " << info.m_exactMatch << ", m_isCommonMatchOnly: " << info.m_isCommonMatchOnly << " }";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,10 @@ namespace search
|
||||
struct PreRankingInfo
|
||||
{
|
||||
PreRankingInfo(Model::Type type, TokenRange const & range)
|
||||
: m_allTokensUsed(true), m_exactMatch(true), m_centerLoaded(false), m_isCommonMatchOnly(false)
|
||||
: m_allTokensUsed(true)
|
||||
, m_exactMatch(true)
|
||||
, m_centerLoaded(false)
|
||||
, m_isCommonMatchOnly(false)
|
||||
{
|
||||
ASSERT_LESS(type, Model::TYPE_COUNT, ());
|
||||
m_type = type;
|
||||
|
||||
@@ -75,10 +75,8 @@ void RemoveStopWordsIfNeeded(QueryTokens & tokens, strings::UniString & prefix)
|
||||
{
|
||||
size_t numStopWords = 0;
|
||||
for (auto const & token : tokens)
|
||||
{
|
||||
if (IsStopWord(token))
|
||||
++numStopWords;
|
||||
}
|
||||
|
||||
if (numStopWords == tokens.size() && prefix.empty())
|
||||
return;
|
||||
@@ -112,8 +110,8 @@ bool EatFid(string & s, uint32_t & fid)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EatMwmName(base::MemTrie<storage::CountryId, base::VectorValues<bool>> const & countriesTrie,
|
||||
string & s, storage::CountryId & mwmName)
|
||||
bool EatMwmName(base::MemTrie<storage::CountryId, base::VectorValues<bool>> const & countriesTrie, string & s,
|
||||
storage::CountryId & mwmName)
|
||||
{
|
||||
TrimLeadingSpaces(s);
|
||||
|
||||
@@ -159,30 +157,26 @@ bool EatVersion(string & s, uint32_t & version)
|
||||
} // namespace
|
||||
|
||||
Processor::Processor(DataSource const & dataSource, CategoriesHolder const & categories,
|
||||
vector<Suggest> const & suggests,
|
||||
storage::CountryInfoGetter const & infoGetter)
|
||||
vector<Suggest> const & suggests, storage::CountryInfoGetter const & infoGetter)
|
||||
: m_categories(categories)
|
||||
, m_infoGetter(infoGetter)
|
||||
, m_dataSource(dataSource)
|
||||
, m_localitiesCaches(static_cast<base::Cancellable const &>(*this))
|
||||
, m_citiesBoundaries(m_dataSource)
|
||||
, m_keywordsScorer(LanguageTier::LANGUAGE_TIER_COUNT)
|
||||
, m_ranker(m_dataSource, m_citiesBoundaries, infoGetter, m_keywordsScorer, m_emitter, categories,
|
||||
suggests, m_localitiesCaches.m_villages, static_cast<base::Cancellable const &>(*this))
|
||||
, m_ranker(m_dataSource, m_citiesBoundaries, infoGetter, m_keywordsScorer, m_emitter, categories, suggests,
|
||||
m_localitiesCaches.m_villages, static_cast<base::Cancellable const &>(*this))
|
||||
, m_preRanker(m_dataSource, m_ranker)
|
||||
, m_geocoder(m_dataSource, infoGetter, categories, m_citiesBoundaries, m_preRanker,
|
||||
m_localitiesCaches, static_cast<base::Cancellable const &>(*this))
|
||||
, m_geocoder(m_dataSource, infoGetter, categories, m_citiesBoundaries, m_preRanker, m_localitiesCaches,
|
||||
static_cast<base::Cancellable const &>(*this))
|
||||
, m_bookmarksProcessor(m_emitter, static_cast<base::Cancellable const &>(*this))
|
||||
{
|
||||
// Current and input langs are to be set later.
|
||||
m_keywordsScorer.SetLanguages(
|
||||
LanguageTier::LANGUAGE_TIER_EN_AND_INTERNATIONAL,
|
||||
{StringUtf8Multilang::kInternationalCode, StringUtf8Multilang::kEnglishCode});
|
||||
m_keywordsScorer.SetLanguages(LanguageTier::LANGUAGE_TIER_DEFAULT,
|
||||
{StringUtf8Multilang::kDefaultCode});
|
||||
m_keywordsScorer.SetLanguages(
|
||||
LanguageTier::LANGUAGE_TIER_ALT_AND_OLD,
|
||||
{StringUtf8Multilang::kAltNameCode, StringUtf8Multilang::kOldNameCode});
|
||||
m_keywordsScorer.SetLanguages(LanguageTier::LANGUAGE_TIER_EN_AND_INTERNATIONAL,
|
||||
{StringUtf8Multilang::kInternationalCode, StringUtf8Multilang::kEnglishCode});
|
||||
m_keywordsScorer.SetLanguages(LanguageTier::LANGUAGE_TIER_DEFAULT, {StringUtf8Multilang::kDefaultCode});
|
||||
m_keywordsScorer.SetLanguages(LanguageTier::LANGUAGE_TIER_ALT_AND_OLD,
|
||||
{StringUtf8Multilang::kAltNameCode, StringUtf8Multilang::kOldNameCode});
|
||||
|
||||
for (auto const & country : m_infoGetter.GetCountries())
|
||||
m_countriesTrie.Add(country.m_countryId, true);
|
||||
@@ -324,7 +318,10 @@ m2::RectD const & Processor::GetViewport() const
|
||||
return m_viewport;
|
||||
}
|
||||
|
||||
void Processor::CacheWorldLocalities() { m_geocoder.CacheWorldLocalities(); }
|
||||
void Processor::CacheWorldLocalities()
|
||||
{
|
||||
m_geocoder.CacheWorldLocalities();
|
||||
}
|
||||
|
||||
void Processor::LoadCitiesBoundaries()
|
||||
{
|
||||
@@ -334,7 +331,10 @@ void Processor::LoadCitiesBoundaries()
|
||||
LOG(LWARNING, ("Can't load cities boundaries"));
|
||||
}
|
||||
|
||||
void Processor::LoadCountriesTree() { m_ranker.LoadCountriesTree(); }
|
||||
void Processor::LoadCountriesTree()
|
||||
{
|
||||
m_ranker.LoadCountriesTree();
|
||||
}
|
||||
|
||||
void Processor::EnableIndexingOfBookmarksDescriptions(bool enable)
|
||||
{
|
||||
@@ -369,15 +369,13 @@ void Processor::OnBookmarksDeleted(vector<bookmarks::Id> const & marks)
|
||||
m_bookmarksProcessor.Erase(id);
|
||||
}
|
||||
|
||||
void Processor::OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId,
|
||||
vector<bookmarks::Id> const & marks)
|
||||
void Processor::OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId, vector<bookmarks::Id> const & marks)
|
||||
{
|
||||
for (auto const & id : marks)
|
||||
m_bookmarksProcessor.AttachToGroup(id, groupId);
|
||||
}
|
||||
|
||||
void Processor::OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId,
|
||||
vector<bookmarks::Id> const & marks)
|
||||
void Processor::OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId, vector<bookmarks::Id> const & marks)
|
||||
{
|
||||
for (auto const & id : marks)
|
||||
m_bookmarksProcessor.DetachFromGroup(id, groupId);
|
||||
@@ -454,9 +452,7 @@ void Processor::SearchByFeatureId()
|
||||
string s = query;
|
||||
bool const parenPref = strings::EatPrefix(s, "(");
|
||||
bool const parenSuff = strings::EatSuffix(s, ")");
|
||||
if (parenPref == parenSuff &&
|
||||
EatMwmName(m_countriesTrie, s, mwmName) &&
|
||||
strings::EatPrefix(s, ",") &&
|
||||
if (parenPref == parenSuff && EatMwmName(m_countriesTrie, s, mwmName) && strings::EatPrefix(s, ",") &&
|
||||
EatFid(s, fid))
|
||||
{
|
||||
EmitResultsFromMwms(infos, [&putFeature, &mwmName, fid](FeaturesLoaderGuard & guard, auto const & fn)
|
||||
@@ -470,13 +466,8 @@ void Processor::SearchByFeatureId()
|
||||
// Case 2.
|
||||
{
|
||||
string s = query;
|
||||
if (strings::EatPrefix(s, "{ MwmId [") &&
|
||||
EatMwmName(m_countriesTrie, s, mwmName) &&
|
||||
strings::EatPrefix(s, ", ") &&
|
||||
EatVersion(s, version) &&
|
||||
strings::EatPrefix(s, "], ") &&
|
||||
EatFid(s, fid) &&
|
||||
strings::EatPrefix(s, " }"))
|
||||
if (strings::EatPrefix(s, "{ MwmId [") && EatMwmName(m_countriesTrie, s, mwmName) && strings::EatPrefix(s, ", ") &&
|
||||
EatVersion(s, version) && strings::EatPrefix(s, "], ") && EatFid(s, fid) && strings::EatPrefix(s, " }"))
|
||||
{
|
||||
EmitResultsFromMwms(infos, [&putFeature, &mwmName, version, fid](FeaturesLoaderGuard & guard, auto const & fn)
|
||||
{
|
||||
@@ -495,10 +486,8 @@ void Processor::EmitWithMetadata(feature::Metadata::EType type)
|
||||
std::sort(infos.begin(), infos.end());
|
||||
|
||||
std::vector<FeatureID> ids;
|
||||
m_dataSource.ForEachFeatureIDInRect([&ids](FeatureID id)
|
||||
{
|
||||
ids.push_back(std::move(id));
|
||||
}, m_viewport, scales::GetUpperScale());
|
||||
m_dataSource.ForEachFeatureIDInRect([&ids](FeatureID id) { ids.push_back(std::move(id)); }, m_viewport,
|
||||
scales::GetUpperScale());
|
||||
|
||||
// The same, first criteria is less<MwmId> -> less<MwmInfo*>
|
||||
std::sort(ids.begin(), ids.end());
|
||||
@@ -713,8 +702,8 @@ bool Processor::SearchCoordinates()
|
||||
base::SortUnique(results);
|
||||
for (auto const & r : results)
|
||||
{
|
||||
m_emitter.AddResultNoChecks(m_ranker.MakeResult(
|
||||
RankerResult(r.m_lat, r.m_lon), true /* needAddress */, true /* needHighlighting */));
|
||||
m_emitter.AddResultNoChecks(
|
||||
m_ranker.MakeResult(RankerResult(r.m_lat, r.m_lon), true /* needAddress */, true /* needHighlighting */));
|
||||
m_emitter.Emit();
|
||||
}
|
||||
return coords_found;
|
||||
@@ -729,9 +718,8 @@ void Processor::SearchPlusCode()
|
||||
if (openlocationcode::IsFull(query))
|
||||
{
|
||||
openlocationcode::CodeArea const area = openlocationcode::Decode(query);
|
||||
m_emitter.AddResultNoChecks(
|
||||
m_ranker.MakeResult(RankerResult(area.GetCenter().latitude, area.GetCenter().longitude),
|
||||
true /* needAddress */, false /* needHighlighting */));
|
||||
m_emitter.AddResultNoChecks(m_ranker.MakeResult(RankerResult(area.GetCenter().latitude, area.GetCenter().longitude),
|
||||
true /* needAddress */, false /* needHighlighting */));
|
||||
}
|
||||
else if (openlocationcode::IsShort(query))
|
||||
{
|
||||
@@ -744,8 +732,8 @@ void Processor::SearchPlusCode()
|
||||
openlocationcode::CodeArea const areaFromPos = openlocationcode::Decode(codeFromPos);
|
||||
|
||||
m_emitter.AddResultNoChecks(
|
||||
m_ranker.MakeResult(RankerResult(areaFromPos.GetCenter().latitude, areaFromPos.GetCenter().longitude),
|
||||
true /* needAddress */, false /* needHighlighting */));
|
||||
m_ranker.MakeResult(RankerResult(areaFromPos.GetCenter().latitude, areaFromPos.GetCenter().longitude),
|
||||
true /* needAddress */, false /* needHighlighting */));
|
||||
}
|
||||
|
||||
ms::LatLon const latLonFromView = mercator::ToLatLon(m_viewport.Center());
|
||||
@@ -756,7 +744,7 @@ void Processor::SearchPlusCode()
|
||||
openlocationcode::CodeArea const areaFromView = openlocationcode::Decode(codeFromView);
|
||||
|
||||
m_emitter.AddResultNoChecks(
|
||||
m_ranker.MakeResult(RankerResult(areaFromView.GetCenter().latitude, areaFromView.GetCenter().longitude),
|
||||
m_ranker.MakeResult(RankerResult(areaFromView.GetCenter().latitude, areaFromView.GetCenter().longitude),
|
||||
true /* needAddress */, false /* needHighlighting */));
|
||||
}
|
||||
}
|
||||
@@ -798,8 +786,8 @@ void Processor::SearchPostcode()
|
||||
for (auto const & p : points)
|
||||
r.Add(p);
|
||||
|
||||
m_emitter.AddResultNoChecks(m_ranker.MakeResult(
|
||||
RankerResult(r.Center(), query), true /* needAddress */, true /* needHighlighting */));
|
||||
m_emitter.AddResultNoChecks(
|
||||
m_ranker.MakeResult(RankerResult(r.Center(), query), true /* needAddress */, true /* needHighlighting */));
|
||||
m_emitter.Emit();
|
||||
|
||||
return;
|
||||
@@ -859,10 +847,7 @@ void Processor::InitParams(QueryParams & params) const
|
||||
for (size_t i = 0; i < params.GetNumTokens(); ++i)
|
||||
base::SortUnique(params.GetTypeIndices(i));
|
||||
|
||||
m_keywordsScorer.ForEachLanguage([¶ms](int8_t lang)
|
||||
{
|
||||
params.GetLangs().Insert(static_cast<uint64_t>(lang));
|
||||
});
|
||||
m_keywordsScorer.ForEachLanguage([¶ms](int8_t lang) { params.GetLangs().Insert(static_cast<uint64_t>(lang)); });
|
||||
}
|
||||
|
||||
void Processor::InitGeocoder(Geocoder::Params & geocoderParams, SearchParams const & searchParams)
|
||||
@@ -884,8 +869,7 @@ void Processor::InitGeocoder(Geocoder::Params & geocoderParams, SearchParams con
|
||||
m_geocoder.SetParams(geocoderParams);
|
||||
}
|
||||
|
||||
void Processor::InitPreRanker(Geocoder::Params const & geocoderParams,
|
||||
SearchParams const & searchParams)
|
||||
void Processor::InitPreRanker(Geocoder::Params const & geocoderParams, SearchParams const & searchParams)
|
||||
{
|
||||
bool const viewportSearch = searchParams.m_mode == Mode::Viewport;
|
||||
|
||||
@@ -912,7 +896,7 @@ class NotInPreffered : public ftypes::BaseChecker
|
||||
{
|
||||
NotInPreffered() : ftypes::BaseChecker(1)
|
||||
{
|
||||
base::StringIL const types[] = { {"organic"}, {"internet_access"} };
|
||||
base::StringIL const types[] = {{"organic"}, {"internet_access"}};
|
||||
auto const & c = classif();
|
||||
for (auto const & e : types)
|
||||
m_types.push_back(c.GetTypeByPath(e));
|
||||
@@ -921,10 +905,9 @@ class NotInPreffered : public ftypes::BaseChecker
|
||||
public:
|
||||
DECLARE_CHECKER_INSTANCE(NotInPreffered);
|
||||
};
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
void Processor::InitRanker(Geocoder::Params const & geocoderParams,
|
||||
SearchParams const & searchParams)
|
||||
void Processor::InitRanker(Geocoder::Params const & geocoderParams, SearchParams const & searchParams)
|
||||
{
|
||||
bool const viewportSearch = searchParams.m_mode == Mode::Viewport;
|
||||
|
||||
@@ -990,9 +973,8 @@ void Processor::EmitResultsFromMwms(std::vector<std::shared_ptr<MwmInfo>> const
|
||||
|
||||
for (auto const & [_, country, ft] : results)
|
||||
{
|
||||
m_emitter.AddResultNoChecks(m_ranker.MakeResult(RankerResult(*ft, country),
|
||||
true /* needAddress */,
|
||||
true /* needHighlighting */));
|
||||
m_emitter.AddResultNoChecks(
|
||||
m_ranker.MakeResult(RankerResult(*ft, country), true /* needAddress */, true /* needHighlighting */));
|
||||
}
|
||||
|
||||
m_emitter.Emit();
|
||||
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
// Maximum result candidates count for each viewport/criteria.
|
||||
static size_t const kPreResultsCount;
|
||||
|
||||
Processor(DataSource const & dataSource, CategoriesHolder const & categories,
|
||||
std::vector<Suggest> const & suggests, storage::CountryInfoGetter const & infoGetter);
|
||||
Processor(DataSource const & dataSource, CategoriesHolder const & categories, std::vector<Suggest> const & suggests,
|
||||
storage::CountryInfoGetter const & infoGetter);
|
||||
|
||||
void SetViewport(m2::RectD const & viewport);
|
||||
void SetPreferredLocale(std::string const & locale);
|
||||
@@ -101,10 +101,8 @@ public:
|
||||
void OnBookmarksCreated(std::vector<std::pair<bookmarks::Id, bookmarks::Doc>> const & marks);
|
||||
void OnBookmarksUpdated(std::vector<std::pair<bookmarks::Id, bookmarks::Doc>> const & marks);
|
||||
void OnBookmarksDeleted(std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId,
|
||||
std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId,
|
||||
std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksAttachedToGroup(bookmarks::GroupId const & groupId, std::vector<bookmarks::Id> const & marks);
|
||||
void OnBookmarksDetachedFromGroup(bookmarks::GroupId const & groupId, std::vector<bookmarks::Id> const & marks);
|
||||
|
||||
// base::Cancellable overrides:
|
||||
void Reset() override;
|
||||
|
||||
@@ -6,14 +6,10 @@
|
||||
|
||||
#include <limits>
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
// ProjectionOnStreet ------------------------------------------------------------------------------
|
||||
ProjectionOnStreet::ProjectionOnStreet()
|
||||
: m_proj(0, 0), m_distMeters(0), m_segIndex(0), m_projSign(false)
|
||||
{
|
||||
}
|
||||
ProjectionOnStreet::ProjectionOnStreet() : m_proj(0, 0), m_distMeters(0), m_segIndex(0), m_projSign(false) {}
|
||||
|
||||
// ProjectionOnStreetCalculator --------------------------------------------------------------------
|
||||
ProjectionOnStreetCalculator::ProjectionOnStreetCalculator(std::vector<m2::PointD> const & points)
|
||||
@@ -27,8 +23,7 @@ ProjectionOnStreetCalculator::ProjectionOnStreetCalculator(std::vector<m2::Point
|
||||
m_segments.emplace_back(points[i - 1], points[i]);
|
||||
}
|
||||
|
||||
bool ProjectionOnStreetCalculator::GetProjection(m2::PointD const & point,
|
||||
ProjectionOnStreet & proj) const
|
||||
bool ProjectionOnStreetCalculator::GetProjection(m2::PointD const & point, ProjectionOnStreet & proj) const
|
||||
{
|
||||
size_t const kInvalidIndex = m_segments.size();
|
||||
proj.m_segIndex = kInvalidIndex;
|
||||
@@ -43,11 +38,10 @@ bool ProjectionOnStreetCalculator::GetProjection(m2::PointD const & point,
|
||||
proj.m_proj = ptProj;
|
||||
proj.m_distMeters = distMeters;
|
||||
proj.m_segIndex = index;
|
||||
proj.m_projSign =
|
||||
m2::robust::OrientedS(m_segments[index].GetP0(), m_segments[index].GetP1(), point) <= 0.0;
|
||||
proj.m_projSign = m2::robust::OrientedS(m_segments[index].GetP0(), m_segments[index].GetP1(), point) <= 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return (proj.m_segIndex < kInvalidIndex);
|
||||
}
|
||||
} // namespace search
|
||||
} // namespace search
|
||||
|
||||
@@ -75,8 +75,7 @@ struct Params
|
||||
string ToString() const
|
||||
{
|
||||
ostringstream os;
|
||||
os << m_query << ", " << m_locale << ", " << m_position.ToString() << ", "
|
||||
<< m_viewport.ToString();
|
||||
os << m_query << ", " << m_locale << ", " << m_position.ToString() << ", " << m_viewport.ToString();
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@@ -135,8 +134,8 @@ struct SearchEngineProxy
|
||||
{
|
||||
search::search_quality::InitDataSource(m_dataSource, "" /* mwmListPath */);
|
||||
search::search_quality::InitStorageData(m_affiliations, m_countryNameSynonyms);
|
||||
m_engine = search::search_quality::InitSearchEngine(m_dataSource, m_affiliations,
|
||||
"en" /* locale */, 1 /* numThreads */);
|
||||
m_engine =
|
||||
search::search_quality::InitSearchEngine(m_dataSource, m_affiliations, "en" /* locale */, 1 /* numThreads */);
|
||||
}
|
||||
|
||||
search::SearchParams MakeSearchParams(Params const & params) const
|
||||
@@ -167,7 +166,7 @@ struct SearchEngineProxy
|
||||
return results;
|
||||
}
|
||||
|
||||
boost::python::list Trace(Params const ¶ms) const
|
||||
boost::python::list Trace(Params const & params) const
|
||||
{
|
||||
m_engine->SetLocale(params.m_locale);
|
||||
|
||||
|
||||
@@ -839,7 +839,9 @@ map<string, vector<string>> const kSynonyms = {
|
||||
{"płk", {"pułkownika (pułkownik)"}},
|
||||
{"pln", {"plaine", "plein"}},
|
||||
{"pln", {"plein"}},
|
||||
{"pl", {"placu", "plaça", "platz", "plain", "placem", "planta", "plass", "place", "plaza", "plassen", "plains", "plats", "platsen", "plac"}},
|
||||
{"pl",
|
||||
{"placu", "plaça", "platz", "plain", "placem", "planta", "plass", "place", "plaza", "plassen", "plains", "plats",
|
||||
"platsen", "plac"}},
|
||||
{"plt", {"plateau", "plateaux"}},
|
||||
{"plut", {"plutonowego", "plutonowy"}},
|
||||
{"plza", {"plaza"}},
|
||||
@@ -1081,7 +1083,9 @@ map<string, vector<string>> const kSynonyms = {
|
||||
{"s:t", {"sankt"}},
|
||||
/// @todo Should not duplicate Street synonyms defined in StreetsSynonymsHolder (avoid useless double queries).
|
||||
/// Remove "street" and "avenue" here, but should update GetNameScore.
|
||||
{"st", {"santo", "sant", "sint", "saint", "stara", "street", "stary", "stora", "sankt", "store", "stare", "stig", "stigen"}},
|
||||
{"st",
|
||||
{"santo", "sant", "sint", "saint", "stara", "street", "stary", "stora", "sankt", "store", "stare", "stig",
|
||||
"stigen"}},
|
||||
{"št", {"šent"}},
|
||||
{"stwg", {"steenweg"}},
|
||||
{"subdiv", {"subdivision"}},
|
||||
@@ -1208,7 +1212,9 @@ map<string, vector<string>> const kSynonyms = {
|
||||
{"vst", {"vista"}},
|
||||
{"vs", {"volksschule"}},
|
||||
{"vte", {"vieille route"}},
|
||||
{"v", {"västra", "vei", "von", "velike", "veliko", "väg", "via", "quinta", "velikem", "veliki", "vegen", "veien", "veg", "vägen", "quinto", "velika", "van"}},
|
||||
{"v",
|
||||
{"västra", "vei", "von", "velike", "veliko", "väg", "via", "quinta", "velikem", "veliki", "vegen", "veien", "veg",
|
||||
"vägen", "quinto", "velika", "van"}},
|
||||
{"vvdas", {"viviendas"}},
|
||||
{"vv", {"vivenda"}},
|
||||
{"vw", {"view"}},
|
||||
@@ -1462,8 +1468,8 @@ void QueryParams::Token::AddSynonym(String const & s)
|
||||
string DebugPrint(QueryParams::Token const & token)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "Token [ m_original=" << DebugPrint(token.GetOriginal())
|
||||
<< ", m_synonyms=" << DebugPrint(token.m_synonyms) << " ]";
|
||||
os << "Token [ m_original=" << DebugPrint(token.GetOriginal()) << ", m_synonyms=" << DebugPrint(token.m_synonyms)
|
||||
<< " ]";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@@ -1473,14 +1479,15 @@ void QueryParams::ClearStreetIndices()
|
||||
class AdditionalCommonTokens
|
||||
{
|
||||
set<String> m_strings;
|
||||
|
||||
public:
|
||||
AdditionalCommonTokens()
|
||||
{
|
||||
char const * arr[] = {
|
||||
"the", // English
|
||||
"der", "zum", "und", "auf", // German
|
||||
"del", "les", // Spanish
|
||||
"в", "на" // Cyrillic
|
||||
"the", // English
|
||||
"der", "zum", "und", "auf", // German
|
||||
"del", "les", // Spanish
|
||||
"в", "на" // Cyrillic
|
||||
};
|
||||
for (char const * s : arr)
|
||||
m_strings.insert(NormalizeAndSimplifyString(s));
|
||||
@@ -1515,7 +1522,10 @@ void QueryParams::Clear()
|
||||
m_langs.Clear();
|
||||
}
|
||||
|
||||
bool QueryParams::IsCategorySynonym(size_t i) const { return !GetTypeIndices(i).empty(); }
|
||||
bool QueryParams::IsCategorySynonym(size_t i) const
|
||||
{
|
||||
return !GetTypeIndices(i).empty();
|
||||
}
|
||||
|
||||
QueryParams::TypeIndices & QueryParams::GetTypeIndices(size_t i)
|
||||
{
|
||||
@@ -1558,10 +1568,8 @@ bool QueryParams::IsNumberTokens(TokenRange const & range) const
|
||||
ASSERT_LESS_OR_EQUAL(range.End(), GetNumTokens(), ());
|
||||
|
||||
for (size_t i : range)
|
||||
{
|
||||
if (!GetToken(i).AnyOfOriginalOrSynonyms([](String const & s) { return strings::IsASCIINumeric(s); }))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1588,20 +1596,16 @@ void QueryParams::AddSynonyms()
|
||||
string const ss = ToUtf8(MakeLowerCase(token.GetOriginal()));
|
||||
auto const it = kSynonyms.find(ss);
|
||||
if (it != kSynonyms.end())
|
||||
{
|
||||
for (auto const & synonym : it->second)
|
||||
token.AddSynonym(synonym);
|
||||
}
|
||||
}
|
||||
if (m_hasPrefix)
|
||||
{
|
||||
string const ss = ToUtf8(MakeLowerCase(m_prefixToken.GetOriginal()));
|
||||
auto const it = kSynonyms.find(ss);
|
||||
if (it != kSynonyms.end())
|
||||
{
|
||||
for (auto const & synonym : it->second)
|
||||
m_prefixToken.AddSynonym(synonym);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1609,12 +1613,9 @@ string DebugPrint(QueryParams const & params)
|
||||
{
|
||||
ostringstream os;
|
||||
os << boolalpha << "QueryParams "
|
||||
<< "{ m_tokens: " << ::DebugPrint(params.m_tokens)
|
||||
<< ", m_prefixToken: " << DebugPrint(params.m_prefixToken)
|
||||
<< ", m_typeIndices: " << ::DebugPrint(params.m_typeIndices)
|
||||
<< ", m_langs: " << DebugPrint(params.m_langs)
|
||||
<< ", m_isCommonToken: " << ::DebugPrint(params.m_isCommonToken)
|
||||
<< " }";
|
||||
<< "{ m_tokens: " << ::DebugPrint(params.m_tokens) << ", m_prefixToken: " << DebugPrint(params.m_prefixToken)
|
||||
<< ", m_typeIndices: " << ::DebugPrint(params.m_typeIndices) << ", m_langs: " << DebugPrint(params.m_langs)
|
||||
<< ", m_isCommonToken: " << ::DebugPrint(params.m_isCommonToken) << " }";
|
||||
return os.str();
|
||||
}
|
||||
} // namespace search
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
class TokenRange;
|
||||
|
||||
@@ -30,20 +30,14 @@ class SecureMemReader : public Reader
|
||||
void CheckPosAndSize(uint64_t pos, uint64_t size) const
|
||||
{
|
||||
if (pos + size > m_size || size > numeric_limits<size_t>::max())
|
||||
MYTHROW(SizeException, (pos, size, m_size) );
|
||||
MYTHROW(SizeException, (pos, size, m_size));
|
||||
}
|
||||
|
||||
public:
|
||||
// Construct from block of memory.
|
||||
SecureMemReader(void const * pData, size_t size)
|
||||
: m_pData(static_cast<char const *>(pData)), m_size(size)
|
||||
{
|
||||
}
|
||||
SecureMemReader(void const * pData, size_t size) : m_pData(static_cast<char const *>(pData)), m_size(size) {}
|
||||
|
||||
inline uint64_t Size() const override
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
inline uint64_t Size() const override { return m_size; }
|
||||
|
||||
inline void Read(uint64_t pos, void * p, size_t size) const override
|
||||
{
|
||||
@@ -69,7 +63,6 @@ private:
|
||||
};
|
||||
} // namespace
|
||||
|
||||
|
||||
QuerySaver::QuerySaver()
|
||||
{
|
||||
Load();
|
||||
@@ -78,11 +71,12 @@ QuerySaver::QuerySaver()
|
||||
void QuerySaver::Add(SearchRequest const & query)
|
||||
{
|
||||
// This change was made just before release, so we don't use untested search normalization methods.
|
||||
//TODO (ldragunov) Rewrite to normalized requests.
|
||||
// TODO (ldragunov) Rewrite to normalized requests.
|
||||
SearchRequest trimmedQuery(query);
|
||||
strings::Trim(trimmedQuery.first);
|
||||
strings::Trim(trimmedQuery.second);
|
||||
auto trimmedComparator = [&trimmedQuery](SearchRequest request) {
|
||||
auto trimmedComparator = [&trimmedQuery](SearchRequest request)
|
||||
{
|
||||
strings::Trim(request.first);
|
||||
strings::Trim(request.second);
|
||||
return trimmedQuery == request;
|
||||
@@ -140,8 +134,7 @@ void QuerySaver::Deserialize(string const & data)
|
||||
Length stringLength = ReadPrimitiveFromSource<Length>(reader);
|
||||
vector<char> str(stringLength);
|
||||
reader.Read(&str[0], stringLength);
|
||||
m_topQueries.emplace_back(make_pair(string(&locale[0], localeLength),
|
||||
string(&str[0], stringLength)));
|
||||
m_topQueries.emplace_back(make_pair(string(&locale[0], localeLength), string(&str[0], stringLength)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,4 +161,4 @@ void QuerySaver::Load()
|
||||
LOG(LWARNING, ("Search history data corrupted! Creating new one."));
|
||||
}
|
||||
}
|
||||
} // namesapce search
|
||||
} // namespace search
|
||||
|
||||
@@ -38,16 +38,9 @@ template <typename Slice>
|
||||
void UpdateNameScores(string_view name, uint8_t lang, Slice const & slice, NameScores & bestScores)
|
||||
{
|
||||
if (StringUtf8Multilang::IsAltOrOldName(lang))
|
||||
{
|
||||
strings::Tokenize(name, ";", [&](string_view n)
|
||||
{
|
||||
bestScores.UpdateIfBetter(GetNameScores(n, lang, slice));
|
||||
});
|
||||
}
|
||||
strings::Tokenize(name, ";", [&](string_view n) { bestScores.UpdateIfBetter(GetNameScores(n, lang, slice)); });
|
||||
else
|
||||
{
|
||||
bestScores.UpdateIfBetter(GetNameScores(name, lang, slice));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Slice>
|
||||
@@ -102,15 +95,12 @@ vector<strings::UniString> RemoveStreetSynonyms(vector<strings::UniString> const
|
||||
{
|
||||
vector<strings::UniString> res;
|
||||
for (auto const & e : tokens)
|
||||
{
|
||||
if (!IsStreetSynonym(e))
|
||||
res.push_back(e);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
NameScores GetNameScores(FeatureType & ft, Geocoder::Params const & params,
|
||||
TokenRange const & range, Model::Type type)
|
||||
NameScores GetNameScores(FeatureType & ft, Geocoder::Params const & params, TokenRange const & range, Model::Type type)
|
||||
{
|
||||
NameScores bestScores;
|
||||
|
||||
@@ -157,16 +147,9 @@ NameScores GetNameScores(FeatureType & ft, Geocoder::Params const & params,
|
||||
};
|
||||
|
||||
if (StringUtf8Multilang::IsAltOrOldName(lang))
|
||||
{
|
||||
strings::Tokenize(name, ";", [&updateScore](string_view n)
|
||||
{
|
||||
updateScore(n);
|
||||
});
|
||||
}
|
||||
strings::Tokenize(name, ";", [&updateScore](string_view n) { updateScore(n); });
|
||||
else
|
||||
{
|
||||
updateScore(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Model::TYPE_BUILDING)
|
||||
@@ -202,16 +185,12 @@ NameScores GetNameScores(FeatureType & ft, Geocoder::Params const & params,
|
||||
if (!brand.empty())
|
||||
{
|
||||
indexer::ForEachLocalizedBrands(brand, [&](indexer::BrandsHolder::Brand::Name const & name)
|
||||
{
|
||||
UpdateNameScores(name.m_name, name.m_locale, sliceNoCategories, bestScores);
|
||||
});
|
||||
{ UpdateNameScores(name.m_name, name.m_locale, sliceNoCategories, bestScores); });
|
||||
}
|
||||
|
||||
if (type == Model::TYPE_STREET)
|
||||
{
|
||||
for (auto const & shield : ftypes::GetRoadShieldsNames(ft))
|
||||
UpdateNameScores(shield, StringUtf8Multilang::kDefaultCode, sliceNoCategories, bestScores);
|
||||
}
|
||||
|
||||
return bestScores;
|
||||
}
|
||||
@@ -328,8 +307,7 @@ class RankerResultMaker
|
||||
ftypes::IsCountryChecker const & m_countryChecker;
|
||||
|
||||
public:
|
||||
RankerResultMaker(Ranker & ranker, DataSource const & dataSource,
|
||||
storage::CountryInfoGetter const & infoGetter,
|
||||
RankerResultMaker(Ranker & ranker, DataSource const & dataSource, storage::CountryInfoGetter const & infoGetter,
|
||||
ReverseGeocoder const & reverseGeocoder, Geocoder::Params const & params)
|
||||
: m_wayChecker(ftypes::IsWayChecker::Instance())
|
||||
, m_capitalChecker(ftypes::IsCapitalChecker::Instance())
|
||||
@@ -340,8 +318,7 @@ public:
|
||||
, m_reverseGeocoder(reverseGeocoder)
|
||||
, m_params(params)
|
||||
, m_isViewportMode(m_params.m_mode == Mode::Viewport)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
optional<RankerResult> operator()(PreRankerResult const & preResult)
|
||||
{
|
||||
@@ -385,16 +362,15 @@ public:
|
||||
// We do not compare result name and request for categorial requests, but we prefer named features
|
||||
// for Eat, Hotel or Shop categories. Toilets, stops, defibrillators, ... are equal w/wo names.
|
||||
|
||||
if (info.m_classifType.poi != PoiType::Eat &&
|
||||
info.m_classifType.poi != PoiType::Hotel &&
|
||||
if (info.m_classifType.poi != PoiType::Eat && info.m_classifType.poi != PoiType::Hotel &&
|
||||
info.m_classifType.poi != PoiType::ShopOrAmenity)
|
||||
{
|
||||
info.m_hasName = false;
|
||||
}
|
||||
}
|
||||
|
||||
info.m_rank = NormalizeRank(info.m_rank, info.m_type, center, country,
|
||||
m_capitalChecker(*ft), !info.m_allTokensUsed);
|
||||
info.m_rank =
|
||||
NormalizeRank(info.m_rank, info.m_type, center, country, m_capitalChecker(*ft), !info.m_allTokensUsed);
|
||||
|
||||
if (preResult.GetInfo().m_isCommonMatchOnly)
|
||||
{
|
||||
@@ -402,10 +378,7 @@ public:
|
||||
auto normalized = NormalizeAndSimplifyString(res.GetName());
|
||||
PreprocessBeforeTokenization(normalized);
|
||||
int count = 0;
|
||||
SplitUniString(normalized, [&count](strings::UniString const &)
|
||||
{
|
||||
++count;
|
||||
}, Delimiters());
|
||||
SplitUniString(normalized, [&count](strings::UniString const &) { ++count; }, Delimiters());
|
||||
|
||||
// Factor is a number of the rest, not common matched tokens in Feature' name. Bigger is worse.
|
||||
// Example when count == 0: UTH airport has empty name, but "ut" is a _common_ token.
|
||||
@@ -424,10 +397,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
bool IsSameLoader(FeatureID const & id) const
|
||||
{
|
||||
return (m_loader && m_loader->GetId() == id.m_mwmId);
|
||||
}
|
||||
bool IsSameLoader(FeatureID const & id) const { return (m_loader && m_loader->GetId() == id.m_mwmId); }
|
||||
|
||||
unique_ptr<FeatureType> LoadFeature(FeatureID const & id)
|
||||
{
|
||||
@@ -457,8 +427,7 @@ private:
|
||||
}
|
||||
|
||||
// For the best performance, incoming ids should be sorted by id.first (mwm file id).
|
||||
unique_ptr<FeatureType> LoadFeature(FeatureID const & id, m2::PointD & center, string & name,
|
||||
string & country)
|
||||
unique_ptr<FeatureType> LoadFeature(FeatureID const & id, m2::PointD & center, string & name, string & country)
|
||||
{
|
||||
auto ft = LoadFeature(id);
|
||||
if (!ft)
|
||||
@@ -479,7 +448,7 @@ private:
|
||||
{
|
||||
std::string_view brand = (*ft).GetMetadata(feature::Metadata::FMD_BRAND);
|
||||
if (!brand.empty())
|
||||
name = platform::GetLocalizedBrandName(std::string{ brand });
|
||||
name = platform::GetLocalizedBrandName(std::string{brand});
|
||||
}
|
||||
|
||||
// Insert exact address (street and house number) instead of empty result name.
|
||||
@@ -489,7 +458,7 @@ private:
|
||||
featureTypes.SortBySpec();
|
||||
auto const bestType = featureTypes.GetBestType();
|
||||
auto const addressChecker = ftypes::IsAddressChecker::Instance();
|
||||
|
||||
|
||||
if (!addressChecker.IsMatched(bestType))
|
||||
return ft;
|
||||
|
||||
@@ -552,8 +521,8 @@ private:
|
||||
info.m_hasName = ft.HasName();
|
||||
if (!info.m_hasName)
|
||||
{
|
||||
info.m_hasName = ft.HasMetadata(feature::Metadata::FMD_OPERATOR) ||
|
||||
ft.HasMetadata(feature::Metadata::FMD_BRAND);
|
||||
info.m_hasName =
|
||||
ft.HasMetadata(feature::Metadata::FMD_OPERATOR) || ft.HasMetadata(feature::Metadata::FMD_BRAND);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -583,7 +552,7 @@ private:
|
||||
{
|
||||
if (info.m_type != type && dependID != IntersectionResult::kInvalidId)
|
||||
{
|
||||
if (auto p = LoadFeature({ ft.GetID().m_mwmId, dependID }))
|
||||
if (auto p = LoadFeature({ft.GetID().m_mwmId, dependID}))
|
||||
updateScoreForFeature(*p, type);
|
||||
}
|
||||
};
|
||||
@@ -639,8 +608,7 @@ private:
|
||||
info.m_nearbyMatch = preInfo.m_geoParts.IsPoiAndComplexPoi();
|
||||
}
|
||||
|
||||
CategoriesInfo const categoriesInfo(featureTypes,
|
||||
TokenSlice(m_params, preInfo.InnermostTokenRange()),
|
||||
CategoriesInfo const categoriesInfo(featureTypes, TokenSlice(m_params, preInfo.InnermostTokenRange()),
|
||||
m_ranker.m_params.m_categoryLocales, m_ranker.m_categories);
|
||||
|
||||
info.m_pureCats = categoriesInfo.IsPureCategories();
|
||||
@@ -653,16 +621,16 @@ private:
|
||||
info.m_nameScore = NameScore::FULL_PREFIX;
|
||||
|
||||
ASSERT_LESS_OR_EQUAL(categoriesInfo.GetMatchedLength(), totalLength, (featureTypes));
|
||||
info.m_matchedFraction = std::max(info.m_matchedFraction,
|
||||
categoriesInfo.GetMatchedLength() / static_cast<float>(totalLength));
|
||||
info.m_matchedFraction =
|
||||
std::max(info.m_matchedFraction, categoriesInfo.GetMatchedLength() / static_cast<float>(totalLength));
|
||||
if (!info.m_errorsMade.IsValid())
|
||||
info.m_errorsMade = ErrorsMade(0);
|
||||
}
|
||||
info.m_falseCats = categoriesInfo.IsFalseCategories();
|
||||
}
|
||||
|
||||
uint16_t NormalizeRank(uint16_t rank, Model::Type type, m2::PointD const & center,
|
||||
string const & country, bool isCapital, bool isRelaxed)
|
||||
uint16_t NormalizeRank(uint16_t rank, Model::Type type, m2::PointD const & center, string const & country,
|
||||
bool isCapital, bool isRelaxed)
|
||||
{
|
||||
// Do not prioritize objects with population < 800. Same as RankToPopulation(rank) < 800, but faster.
|
||||
if (rank <= 70)
|
||||
@@ -689,7 +657,8 @@ private:
|
||||
return rank * 1.7;
|
||||
|
||||
// Fallthrough like "STATE" for cities without info.
|
||||
} [[fallthrough]];
|
||||
}
|
||||
[[fallthrough]];
|
||||
case Model::TYPE_STATE: return rank / 1.5;
|
||||
case Model::TYPE_COUNTRY: return rank;
|
||||
|
||||
@@ -708,9 +677,8 @@ private:
|
||||
};
|
||||
|
||||
Ranker::Ranker(DataSource const & dataSource, CitiesBoundariesTable const & boundariesTable,
|
||||
storage::CountryInfoGetter const & infoGetter, KeywordLangMatcher & keywordsScorer,
|
||||
Emitter & emitter, CategoriesHolder const & categories,
|
||||
vector<Suggest> const & suggests, VillagesCache & villagesCache,
|
||||
storage::CountryInfoGetter const & infoGetter, KeywordLangMatcher & keywordsScorer, Emitter & emitter,
|
||||
CategoriesHolder const & categories, vector<Suggest> const & suggests, VillagesCache & villagesCache,
|
||||
base::Cancellable const & cancellable)
|
||||
: m_reverseGeocoder(dataSource)
|
||||
, m_cancellable(cancellable)
|
||||
@@ -721,8 +689,7 @@ Ranker::Ranker(DataSource const & dataSource, CitiesBoundariesTable const & boun
|
||||
, m_emitter(emitter)
|
||||
, m_categories(categories)
|
||||
, m_suggests(suggests)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
void Ranker::Init(Params const & params, Geocoder::Params const & geocoderParams)
|
||||
{
|
||||
@@ -763,13 +730,15 @@ Result Ranker::MakeResult(RankerResult const & rankerResult, bool needAddress, b
|
||||
{
|
||||
case RankerResult::Type::Feature:
|
||||
case RankerResult::Type::Building:
|
||||
res.FromFeature(rankerResult.GetID(), rankerResult.GetBestType(), rankerResult.GetBestType(&m_params.m_preferredTypes), rankerResult.m_details);
|
||||
res.FromFeature(rankerResult.GetID(), rankerResult.GetBestType(),
|
||||
rankerResult.GetBestType(&m_params.m_preferredTypes), rankerResult.m_details);
|
||||
break;
|
||||
case RankerResult::Type::LatLon: res.SetType(Result::Type::LatLon); break;
|
||||
case RankerResult::Type::Postcode: res.SetType(Result::Type::Postcode); break;
|
||||
}
|
||||
|
||||
if (needAddress && ftypes::IsLocalityChecker::Instance().GetType(rankerResult.GetTypes()) == ftypes::LocalityType::None)
|
||||
if (needAddress &&
|
||||
ftypes::IsLocalityChecker::Instance().GetType(rankerResult.GetTypes()) == ftypes::LocalityType::None)
|
||||
{
|
||||
m_localities.GetLocality(res.GetFeatureCenter(), [&](LocalityItem const & item)
|
||||
{
|
||||
@@ -825,10 +794,8 @@ void Ranker::UpdateResults(bool lastUpdate)
|
||||
auto it = std::max_element(resV.begin(), resV.end(), base::LessBy(&RankerResult::GetLinearModelRank));
|
||||
double const lowestAllowed = it->GetLinearModelRank() - RankingInfo::GetLinearRankViewportThreshold();
|
||||
|
||||
it = std::partition(resV.begin(), resV.end(), [lowestAllowed](RankerResult const & r)
|
||||
{
|
||||
return r.GetLinearModelRank() >= lowestAllowed;
|
||||
});
|
||||
it = std::partition(resV.begin(), resV.end(),
|
||||
[lowestAllowed](RankerResult const & r) { return r.GetLinearModelRank() >= lowestAllowed; });
|
||||
if (it != resV.end())
|
||||
{
|
||||
LOG(LDEBUG, ("Removed", std::distance(it, resV.end()), "viewport results."));
|
||||
@@ -838,13 +805,11 @@ void Ranker::UpdateResults(bool lastUpdate)
|
||||
else
|
||||
{
|
||||
// Can get same Town features (from World) when searching in many MWMs.
|
||||
base::SortUnique(m_tentativeResults,
|
||||
[](RankerResult const & r1, RankerResult const & r2)
|
||||
{
|
||||
// Expect that linear rank is equal for the same features.
|
||||
return r1.GetLinearModelRank() > r2.GetLinearModelRank();
|
||||
},
|
||||
base::EqualsBy(&RankerResult::GetID));
|
||||
base::SortUnique(m_tentativeResults, [](RankerResult const & r1, RankerResult const & r2)
|
||||
{
|
||||
// Expect that linear rank is equal for the same features.
|
||||
return r1.GetLinearModelRank() > r2.GetLinearModelRank();
|
||||
}, base::EqualsBy(&RankerResult::GetID));
|
||||
|
||||
ProcessSuggestions(m_tentativeResults);
|
||||
}
|
||||
@@ -854,11 +819,8 @@ void Ranker::UpdateResults(bool lastUpdate)
|
||||
size_t i = 0;
|
||||
for (; i < m_tentativeResults.size(); ++i)
|
||||
{
|
||||
if (!lastUpdate && count >= m_params.m_batchSize && !m_params.m_viewportSearch &&
|
||||
!m_params.m_categorialRequest)
|
||||
{
|
||||
if (!lastUpdate && count >= m_params.m_batchSize && !m_params.m_viewportSearch && !m_params.m_categorialRequest)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!lastUpdate)
|
||||
{
|
||||
@@ -878,7 +840,7 @@ void Ranker::UpdateResults(bool lastUpdate)
|
||||
|
||||
/// @DebugNote
|
||||
// Uncomment for extended ranking print.
|
||||
//if (!m_params.m_viewportSearch)
|
||||
// if (!m_params.m_viewportSearch)
|
||||
// LOG(LDEBUG, (rankerResult));
|
||||
|
||||
// Don't make move here in case of BailIfCancelled() throw. Objects in m_tentativeResults should remain valid.
|
||||
@@ -907,14 +869,20 @@ void Ranker::UpdateResults(bool lastUpdate)
|
||||
}
|
||||
}
|
||||
|
||||
void Ranker::ClearCaches() { m_localities.ClearCache(); }
|
||||
void Ranker::ClearCaches()
|
||||
{
|
||||
m_localities.ClearCache();
|
||||
}
|
||||
|
||||
void Ranker::SetLocale(string const & locale)
|
||||
{
|
||||
m_regionInfoGetter.SetLocale(locale);
|
||||
}
|
||||
|
||||
void Ranker::LoadCountriesTree() { m_regionInfoGetter.LoadCountriesTree(); }
|
||||
void Ranker::LoadCountriesTree()
|
||||
{
|
||||
m_regionInfoGetter.LoadCountriesTree();
|
||||
}
|
||||
|
||||
void Ranker::MakeRankerResults()
|
||||
{
|
||||
@@ -955,16 +923,9 @@ void Ranker::GetBestMatchName(FeatureType & f, string & name) const
|
||||
auto bestNameFinder = [&](int8_t lang, string_view s)
|
||||
{
|
||||
if (StringUtf8Multilang::IsAltOrOldName(lang))
|
||||
{
|
||||
strings::Tokenize(s, ";", [lang, &updateScore](std::string_view n)
|
||||
{
|
||||
updateScore(lang, n, true /* force */);
|
||||
});
|
||||
}
|
||||
strings::Tokenize(s, ";", [lang, &updateScore](std::string_view n) { updateScore(lang, n, true /* force */); });
|
||||
else
|
||||
{
|
||||
updateScore(lang, s, true /* force */);
|
||||
}
|
||||
|
||||
// Default name should be written in the regional language.
|
||||
if (lang == StringUtf8Multilang::kDefaultCode)
|
||||
@@ -987,15 +948,13 @@ void Ranker::GetBestMatchName(FeatureType & f, string & name) const
|
||||
}
|
||||
}
|
||||
|
||||
void Ranker::MatchForSuggestions(strings::UniString const & token, int8_t locale,
|
||||
string const & prologue)
|
||||
void Ranker::MatchForSuggestions(strings::UniString const & token, int8_t locale, string const & prologue)
|
||||
{
|
||||
for (auto const & suggest : m_suggests)
|
||||
{
|
||||
strings::UniString const & s = suggest.m_name;
|
||||
if (suggest.m_prefixLength <= token.size()
|
||||
&& token != s // do not push suggestion if it already equals to token
|
||||
&& suggest.m_locale == locale // push suggestions only for needed language
|
||||
if (suggest.m_prefixLength <= token.size() && token != s // do not push suggestion if it already equals to token
|
||||
&& suggest.m_locale == locale // push suggestions only for needed language
|
||||
&& strings::StartsWith(s, token))
|
||||
{
|
||||
string const utf8Str = strings::ToUtf8(s);
|
||||
@@ -1024,8 +983,8 @@ void Ranker::ProcessSuggestions(vector<RankerResult> const & vec) const
|
||||
if (!suggestion.empty())
|
||||
{
|
||||
// todo(@m) RankingInfo is lost here. Should it be?
|
||||
if (m_emitter.AddResult(Result(MakeResult(r, false /* needAddress */, true /* needHighlighting */),
|
||||
std::move(suggestion))))
|
||||
if (m_emitter.AddResult(
|
||||
Result(MakeResult(r, false /* needAddress */, true /* needHighlighting */), std::move(suggestion))))
|
||||
{
|
||||
++added;
|
||||
}
|
||||
|
||||
@@ -61,9 +61,8 @@ public:
|
||||
};
|
||||
|
||||
Ranker(DataSource const & dataSource, CitiesBoundariesTable const & boundariesTable,
|
||||
storage::CountryInfoGetter const & infoGetter, KeywordLangMatcher & keywordsScorer,
|
||||
Emitter & emitter, CategoriesHolder const & categories,
|
||||
std::vector<Suggest> const & suggests, VillagesCache & villagesCache,
|
||||
storage::CountryInfoGetter const & infoGetter, KeywordLangMatcher & keywordsScorer, Emitter & emitter,
|
||||
CategoriesHolder const & categories, std::vector<Suggest> const & suggests, VillagesCache & villagesCache,
|
||||
base::Cancellable const & cancellable);
|
||||
virtual ~Ranker() = default;
|
||||
|
||||
@@ -82,8 +81,7 @@ public:
|
||||
|
||||
virtual void AddPreRankerResults(std::vector<PreRankerResult> && preRankerResults)
|
||||
{
|
||||
std::move(preRankerResults.begin(), preRankerResults.end(),
|
||||
std::back_inserter(m_preRankerResults));
|
||||
std::move(preRankerResults.begin(), preRankerResults.end(), std::back_inserter(m_preRankerResults));
|
||||
}
|
||||
|
||||
virtual void UpdateResults(bool lastUpdate);
|
||||
@@ -102,8 +100,7 @@ private:
|
||||
void MakeRankerResults();
|
||||
|
||||
void GetBestMatchName(FeatureType & f, std::string & name) const;
|
||||
void MatchForSuggestions(strings::UniString const & token, int8_t locale,
|
||||
std::string const & prolog);
|
||||
void MatchForSuggestions(strings::UniString const & token, int8_t locale, std::string const & prolog);
|
||||
void ProcessSuggestions(std::vector<RankerResult> const & vec) const;
|
||||
|
||||
std::string GetLocalizedRegionInfoForResult(RankerResult const & result) const;
|
||||
|
||||
@@ -31,7 +31,7 @@ double constexpr kWalkingDistanceM = 5000.0;
|
||||
|
||||
double constexpr AbsPenaltyPerKm()
|
||||
{
|
||||
return - kDistanceToPivot * 1000.0 / RankingInfo::kMaxDistMeters;
|
||||
return -kDistanceToPivot * 1000.0 / RankingInfo::kMaxDistMeters;
|
||||
}
|
||||
|
||||
// These constants are very important and checked in Famous_Cities_Rank test.
|
||||
@@ -42,7 +42,7 @@ double constexpr kErrorsMade = -0.4;
|
||||
double constexpr kMatchedFraction = 0.1876736;
|
||||
double constexpr kAllTokensUsed = 0.3;
|
||||
double constexpr kCommonTokens = -0.05;
|
||||
double constexpr kAltOldName = -0.3; // Some reasonable penalty like kErrorsMade.
|
||||
double constexpr kAltOldName = -0.3; // Some reasonable penalty like kErrorsMade.
|
||||
|
||||
// Some thoughts about reasonable diff here:
|
||||
// - should be a bit less than fabs(kAltOldName) to filter non-obvious matching
|
||||
@@ -53,62 +53,62 @@ static_assert(kViewportDiffThreshold < -kAltOldName && kViewportDiffThreshold >
|
||||
static_assert(kViewportDiffThreshold < kAllTokensUsed);
|
||||
|
||||
double constexpr kNameScore[] = {
|
||||
-0.05, // Zero
|
||||
0, // Substring
|
||||
0.01, // Prefix
|
||||
0.012, // First Match
|
||||
0.018, // Full Prefix
|
||||
0.02, // Full Match
|
||||
-0.05, // Zero
|
||||
0, // Substring
|
||||
0.01, // Prefix
|
||||
0.012, // First Match
|
||||
0.018, // Full Prefix
|
||||
0.02, // Full Match
|
||||
};
|
||||
static_assert(std::size(kNameScore) == base::E2I(NameScore::COUNT));
|
||||
|
||||
// 0-based factors from POIs, Streets, Buildings, since we don't have ratings or popularities now.
|
||||
double constexpr kType[] = {
|
||||
0, // POI
|
||||
0, // Complex POI
|
||||
0.007, // Building, to compensate max(kStreetType), see Arbat_Address test.
|
||||
0, // Street
|
||||
0, // Suburb
|
||||
-0.025, // Unclassified
|
||||
0, // Village
|
||||
0.01, // City
|
||||
0.0233254, // State
|
||||
0.1679389, // Country
|
||||
0, // POI
|
||||
0, // Complex POI
|
||||
0.007, // Building, to compensate max(kStreetType), see Arbat_Address test.
|
||||
0, // Street
|
||||
0, // Suburb
|
||||
-0.025, // Unclassified
|
||||
0, // Village
|
||||
0.01, // City
|
||||
0.0233254, // State
|
||||
0.1679389, // Country
|
||||
};
|
||||
static_assert(std::size(kType) == Model::TYPE_COUNT);
|
||||
|
||||
// 0-based factors from General.
|
||||
double constexpr kPoiType[] = {
|
||||
0.03, // TransportMajor
|
||||
0.003, // TransportLocal (0 < it < Residential st)
|
||||
0.01, // Eat
|
||||
0.01, // Hotel
|
||||
0.01, // Shop or Amenity
|
||||
0.01, // Attraction
|
||||
0.008, // CarInfra
|
||||
0.005, // PureCategory
|
||||
0, // General
|
||||
-0.01, // Service
|
||||
0.03, // TransportMajor
|
||||
0.003, // TransportLocal (0 < it < Residential st)
|
||||
0.01, // Eat
|
||||
0.01, // Hotel
|
||||
0.01, // Shop or Amenity
|
||||
0.01, // Attraction
|
||||
0.008, // CarInfra
|
||||
0.005, // PureCategory
|
||||
0, // General
|
||||
-0.01, // Service
|
||||
};
|
||||
static_assert(std::size(kPoiType) == base::E2I(PoiType::Count));
|
||||
|
||||
// - When search for "eat", we'd prefer category types, rather than "eat" name.
|
||||
// - To _equalize_ "subway" search: Metro category should be equal with "Subway" fast food.
|
||||
// - See NY_Subway test.
|
||||
double constexpr kFalseCats =
|
||||
kNameScore[base::E2I(NameScore::FULL_PREFIX)] - kNameScore[base::E2I(NameScore::FULL_MATCH)] +
|
||||
kPoiType[base::E2I(PoiType::PureCategory)] - kPoiType[base::E2I(PoiType::Eat)];
|
||||
double constexpr kFalseCats = kNameScore[base::E2I(NameScore::FULL_PREFIX)] -
|
||||
kNameScore[base::E2I(NameScore::FULL_MATCH)] +
|
||||
kPoiType[base::E2I(PoiType::PureCategory)] - kPoiType[base::E2I(PoiType::Eat)];
|
||||
static_assert(kFalseCats < 0.0);
|
||||
|
||||
double constexpr kStreetType[] = {
|
||||
0, // Default
|
||||
0, // Pedestrian
|
||||
0, // Cycleway
|
||||
0, // Outdoor
|
||||
0.004, // Minors
|
||||
0.004, // Residential
|
||||
0.005, // Regular
|
||||
0.006, // Motorway
|
||||
0, // Default
|
||||
0, // Pedestrian
|
||||
0, // Cycleway
|
||||
0, // Outdoor
|
||||
0.004, // Minors
|
||||
0.004, // Residential
|
||||
0.005, // Regular
|
||||
0.006, // Motorway
|
||||
};
|
||||
static_assert(std::size(kStreetType) == base::Underlying(StreetType::Count));
|
||||
|
||||
@@ -156,7 +156,7 @@ protected:
|
||||
std::vector<uint32_t> m_types;
|
||||
|
||||
public:
|
||||
bool operator() (feature::TypesHolder const & th) const
|
||||
bool operator()(feature::TypesHolder const & th) const
|
||||
{
|
||||
return base::AnyOf(m_types, [&th](uint32_t t) { return th.HasWithSubclass(t); });
|
||||
}
|
||||
@@ -167,7 +167,7 @@ class IsAttraction
|
||||
std::vector<uint32_t> m_types;
|
||||
|
||||
public:
|
||||
bool operator() (feature::TypesHolder const & th) const
|
||||
bool operator()(feature::TypesHolder const & th) const
|
||||
{
|
||||
// Strict check (unlike in BaseTypesChecker) to avoid matching:
|
||||
// - historic-memorial-plaque
|
||||
@@ -187,11 +187,8 @@ public:
|
||||
|
||||
// Add _attraction_ leisures too!
|
||||
base::StringIL const types[] = {
|
||||
{"leisure", "beach_resort"},
|
||||
{"leisure", "garden"},
|
||||
{"leisure", "marina"},
|
||||
{"leisure", "nature_reserve"},
|
||||
{"leisure", "park"},
|
||||
{"leisure", "beach_resort"}, {"leisure", "garden"}, {"leisure", "marina"},
|
||||
{"leisure", "nature_reserve"}, {"leisure", "park"},
|
||||
};
|
||||
|
||||
Classificator const & c = classif();
|
||||
@@ -206,24 +203,24 @@ public:
|
||||
IsShopOrAmenity()
|
||||
{
|
||||
base::StringIL const types[] = {
|
||||
{"shop"},
|
||||
{"shop"},
|
||||
|
||||
// Amenity types are very fragmented, so take only most _interesting_ here.
|
||||
{"amenity", "bank"},
|
||||
{"amenity", "brothel"},
|
||||
{"amenity", "casino"},
|
||||
{"amenity", "cinema"},
|
||||
{"amenity", "clinic"},
|
||||
{"amenity", "hospital"},
|
||||
{"amenity", "ice_cream"},
|
||||
{"amenity", "library"},
|
||||
{"amenity", "marketplace"},
|
||||
{"amenity", "nightclub"},
|
||||
{"amenity", "pharmacy"},
|
||||
{"amenity", "police"},
|
||||
{"amenity", "post_office"},
|
||||
{"amenity", "stripclub"},
|
||||
{"amenity", "theatre"},
|
||||
// Amenity types are very fragmented, so take only most _interesting_ here.
|
||||
{"amenity", "bank"},
|
||||
{"amenity", "brothel"},
|
||||
{"amenity", "casino"},
|
||||
{"amenity", "cinema"},
|
||||
{"amenity", "clinic"},
|
||||
{"amenity", "hospital"},
|
||||
{"amenity", "ice_cream"},
|
||||
{"amenity", "library"},
|
||||
{"amenity", "marketplace"},
|
||||
{"amenity", "nightclub"},
|
||||
{"amenity", "pharmacy"},
|
||||
{"amenity", "police"},
|
||||
{"amenity", "post_office"},
|
||||
{"amenity", "stripclub"},
|
||||
{"amenity", "theatre"},
|
||||
};
|
||||
|
||||
Classificator const & c = classif();
|
||||
@@ -238,16 +235,16 @@ public:
|
||||
IsCarInfra()
|
||||
{
|
||||
base::StringIL const types[] = {
|
||||
{"amenity", "car_rental"},
|
||||
{"amenity", "car_sharing"},
|
||||
{"amenity", "car_wash"},
|
||||
{"amenity", "charging_station"},
|
||||
{"amenity", "fuel"},
|
||||
// Do not add parking here, no need to rank them by name.
|
||||
//{"amenity", "parking"},
|
||||
{"amenity", "car_rental"},
|
||||
{"amenity", "car_sharing"},
|
||||
{"amenity", "car_wash"},
|
||||
{"amenity", "charging_station"},
|
||||
{"amenity", "fuel"},
|
||||
// Do not add parking here, no need to rank them by name.
|
||||
//{"amenity", "parking"},
|
||||
|
||||
{"highway", "rest_area"},
|
||||
{"highway", "services"},
|
||||
{"highway", "rest_area"},
|
||||
{"highway", "services"},
|
||||
};
|
||||
|
||||
Classificator const & c = classif();
|
||||
@@ -292,8 +289,7 @@ std::string DebugPrint(StoredRankingInfo const & info)
|
||||
{
|
||||
ostringstream os;
|
||||
os << "StoredRankingInfo "
|
||||
<< "{ m_distanceToPivot: " << info.m_distanceToPivot
|
||||
<< ", m_type: " << DebugPrint(info.m_type)
|
||||
<< "{ m_distanceToPivot: " << info.m_distanceToPivot << ", m_type: " << DebugPrint(info.m_type)
|
||||
<< ", m_classifType: ";
|
||||
|
||||
if (Model::IsPoi(info.m_type))
|
||||
@@ -308,26 +304,17 @@ std::string DebugPrint(StoredRankingInfo const & info)
|
||||
string DebugPrint(RankingInfo const & info)
|
||||
{
|
||||
ostringstream os;
|
||||
os << boolalpha << "RankingInfo { "
|
||||
<< DebugPrint(static_cast<StoredRankingInfo const &>(info)) << ", ";
|
||||
os << boolalpha << "RankingInfo { " << DebugPrint(static_cast<StoredRankingInfo const &>(info)) << ", ";
|
||||
|
||||
PrintParse(os, info.m_tokenRanges, info.m_numTokens);
|
||||
|
||||
os << ", m_rank: " << static_cast<int>(info.m_rank)
|
||||
<< ", m_popularity: " << static_cast<int>(info.m_popularity)
|
||||
<< ", m_nameScore: " << DebugPrint(info.m_nameScore)
|
||||
<< ", m_errorsMade: " << DebugPrint(info.m_errorsMade)
|
||||
<< ", m_isAltOrOldName: " << info.m_isAltOrOldName
|
||||
<< ", m_numTokens: " << info.m_numTokens
|
||||
<< ", m_commonTokensFactor: " << info.m_commonTokensFactor
|
||||
<< ", m_matchedFraction: " << info.m_matchedFraction
|
||||
<< ", m_pureCats: " << info.m_pureCats
|
||||
<< ", m_falseCats: " << info.m_falseCats
|
||||
<< ", m_allTokensUsed: " << info.m_allTokensUsed
|
||||
<< ", m_categorialRequest: " << info.m_categorialRequest
|
||||
<< ", m_hasName: " << info.m_hasName
|
||||
<< ", m_nearbyMatch: " << info.m_nearbyMatch
|
||||
<< " }";
|
||||
os << ", m_rank: " << static_cast<int>(info.m_rank) << ", m_popularity: " << static_cast<int>(info.m_popularity)
|
||||
<< ", m_nameScore: " << DebugPrint(info.m_nameScore) << ", m_errorsMade: " << DebugPrint(info.m_errorsMade)
|
||||
<< ", m_isAltOrOldName: " << info.m_isAltOrOldName << ", m_numTokens: " << info.m_numTokens
|
||||
<< ", m_commonTokensFactor: " << info.m_commonTokensFactor << ", m_matchedFraction: " << info.m_matchedFraction
|
||||
<< ", m_pureCats: " << info.m_pureCats << ", m_falseCats: " << info.m_falseCats
|
||||
<< ", m_allTokensUsed: " << info.m_allTokensUsed << ", m_categorialRequest: " << info.m_categorialRequest
|
||||
<< ", m_hasName: " << info.m_hasName << ", m_nearbyMatch: " << info.m_nearbyMatch << " }";
|
||||
|
||||
return os.str();
|
||||
}
|
||||
@@ -397,8 +384,7 @@ double RankingInfo::GetLinearModelRank(bool viewportMode /* = false */) const
|
||||
if (m_allTokensUsed)
|
||||
result += kAllTokensUsed;
|
||||
|
||||
auto const nameRank = kNameScore[static_cast<size_t>(GetNameScore())] +
|
||||
kErrorsMade * GetErrorsMadePerToken() +
|
||||
auto const nameRank = kNameScore[static_cast<size_t>(GetNameScore())] + kErrorsMade * GetErrorsMadePerToken() +
|
||||
kMatchedFraction * m_matchedFraction;
|
||||
result += nameRank;
|
||||
|
||||
@@ -448,10 +434,8 @@ NameScore RankingInfo::GetNameScore() const
|
||||
{
|
||||
// Promote POI's name rank if all tokens were matched with TYPE_SUBPOI/TYPE_COMPLEXPOI only.
|
||||
for (int i = Model::TYPE_BUILDING; i < Model::TYPE_COUNT; ++i)
|
||||
{
|
||||
if (!m_tokenRanges[i].Empty())
|
||||
return m_nameScore;
|
||||
}
|
||||
|
||||
// It's better for ranking when POIs would be equal by name score in the next cases:
|
||||
|
||||
@@ -497,8 +481,7 @@ PoiType GetPoiType(feature::TypesHolder const & th)
|
||||
if (IsHotelChecker::Instance()(th))
|
||||
return PoiType::Hotel;
|
||||
|
||||
if (IsRailwayStationChecker::Instance()(th) ||
|
||||
IsSubwayStationChecker::Instance()(th) ||
|
||||
if (IsRailwayStationChecker::Instance()(th) || IsSubwayStationChecker::Instance()(th) ||
|
||||
IsAirportChecker::Instance()(th))
|
||||
{
|
||||
return PoiType::TransportMajor;
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
namespace feature { class TypesHolder; }
|
||||
namespace feature
|
||||
{
|
||||
class TypesHolder;
|
||||
}
|
||||
|
||||
namespace search
|
||||
{
|
||||
|
||||
@@ -17,8 +17,8 @@ using namespace std;
|
||||
using namespace strings;
|
||||
|
||||
// CategoriesInfo ----------------------------------------------------------------------------------
|
||||
CategoriesInfo::CategoriesInfo(feature::TypesHolder const & holder, TokenSlice const & tokens,
|
||||
Locales const & locales, CategoriesHolder const & categories)
|
||||
CategoriesInfo::CategoriesInfo(feature::TypesHolder const & holder, TokenSlice const & tokens, Locales const & locales,
|
||||
CategoriesHolder const & categories)
|
||||
{
|
||||
struct TokenInfo
|
||||
{
|
||||
@@ -40,10 +40,8 @@ CategoriesInfo::CategoriesInfo(feature::TypesHolder const & holder, TokenSlice c
|
||||
});
|
||||
|
||||
for (size_t i = 0; i < slice.Size(); ++i)
|
||||
{
|
||||
if (infos[i].m_inFeatureTypes)
|
||||
m_matchedLength += slice.Get(i).size();
|
||||
}
|
||||
|
||||
// Note that m_inFeatureTypes implies m_isCategoryToken.
|
||||
|
||||
@@ -53,10 +51,8 @@ CategoriesInfo::CategoriesInfo(feature::TypesHolder const & holder, TokenSlice c
|
||||
return info.m_inFeatureTypes;
|
||||
});
|
||||
|
||||
m_falseCategories = all_of(infos.begin(), infos.end(), [](TokenInfo const & info)
|
||||
{
|
||||
return !info.m_inFeatureTypes && info.m_isCategoryToken;
|
||||
});
|
||||
m_falseCategories = all_of(infos.begin(), infos.end(),
|
||||
[](TokenInfo const & info) { return !info.m_inFeatureTypes && info.m_isCategoryToken; });
|
||||
}
|
||||
|
||||
// ErrorsMade --------------------------------------------------------------------------------------
|
||||
@@ -70,8 +66,7 @@ string DebugPrint(ErrorsMade const & errorsMade)
|
||||
|
||||
namespace impl
|
||||
{
|
||||
ErrorsMade GetErrorsMade(QueryParams::Token const & token,
|
||||
strings::UniString const & text, LevenshteinDFA const & dfa)
|
||||
ErrorsMade GetErrorsMade(QueryParams::Token const & token, strings::UniString const & text, LevenshteinDFA const & dfa)
|
||||
{
|
||||
if (token.AnyOfSynonyms([&text](strings::UniString const & s) { return text == s; }))
|
||||
return ErrorsMade(0);
|
||||
@@ -84,8 +79,8 @@ ErrorsMade GetErrorsMade(QueryParams::Token const & token,
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token,
|
||||
strings::UniString const & text, LevenshteinDFA const & dfa)
|
||||
ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token, strings::UniString const & text,
|
||||
LevenshteinDFA const & dfa)
|
||||
{
|
||||
if (token.AnyOfSynonyms([&text](strings::UniString const & s) { return StartsWith(text, s); }))
|
||||
return ErrorsMade(0);
|
||||
@@ -106,16 +101,17 @@ bool IsStopWord(UniString const & s)
|
||||
class StopWordsChecker
|
||||
{
|
||||
set<UniString> m_set;
|
||||
|
||||
public:
|
||||
StopWordsChecker()
|
||||
{
|
||||
// Don't want to put _full_ stopwords list, not to break current ranking.
|
||||
// Only 2-letters and the most common.
|
||||
char const * arr[] = {
|
||||
"a", "s", "the", // English
|
||||
"am", "im", "an", // German
|
||||
"d", "da", "de", "di", "du", "la", "le", // French, Spanish, Italian
|
||||
"и", "я" // Cyrillic
|
||||
"a", "s", "the", // English
|
||||
"am", "im", "an", // German
|
||||
"d", "da", "de", "di", "du", "la", "le", // French, Spanish, Italian
|
||||
"и", "я" // Cyrillic
|
||||
};
|
||||
for (char const * s : arr)
|
||||
m_set.insert(MakeUniString(s));
|
||||
@@ -157,10 +153,8 @@ string DebugPrint(NameScores const & scores)
|
||||
{
|
||||
ostringstream os;
|
||||
os << boolalpha << "NameScores "
|
||||
<< "{ m_nameScore: " << DebugPrint(scores.m_nameScore)
|
||||
<< ", m_matchedLength: " << scores.m_matchedLength
|
||||
<< ", m_errorsMade: " << DebugPrint(scores.m_errorsMade)
|
||||
<< ", m_isAltOrOldName: "
|
||||
<< "{ m_nameScore: " << DebugPrint(scores.m_nameScore) << ", m_matchedLength: " << scores.m_matchedLength
|
||||
<< ", m_errorsMade: " << DebugPrint(scores.m_errorsMade) << ", m_isAltOrOldName: "
|
||||
<< " }";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@@ -27,8 +27,8 @@ class TokenSlice;
|
||||
class CategoriesInfo
|
||||
{
|
||||
public:
|
||||
CategoriesInfo(feature::TypesHolder const & holder, TokenSlice const & tokens,
|
||||
Locales const & locales, CategoriesHolder const & categories);
|
||||
CategoriesInfo(feature::TypesHolder const & holder, TokenSlice const & tokens, Locales const & locales,
|
||||
CategoriesHolder const & categories);
|
||||
|
||||
size_t GetMatchedLength() const { return m_matchedLength; }
|
||||
|
||||
@@ -98,23 +98,23 @@ namespace impl
|
||||
// Returns the minimum number of errors needed to match |text| with |token|.
|
||||
// If it's not possible in accordance with GetMaxErrorsForToken(|text|), returns kInfiniteErrors.
|
||||
/// @param[in] dfa DFA for |text|
|
||||
ErrorsMade GetErrorsMade(QueryParams::Token const & token,
|
||||
strings::UniString const & text, strings::LevenshteinDFA const & dfa);
|
||||
ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token,
|
||||
strings::UniString const & text, strings::LevenshteinDFA const & dfa);
|
||||
ErrorsMade GetErrorsMade(QueryParams::Token const & token, strings::UniString const & text,
|
||||
strings::LevenshteinDFA const & dfa);
|
||||
ErrorsMade GetPrefixErrorsMade(QueryParams::Token const & token, strings::UniString const & text,
|
||||
strings::LevenshteinDFA const & dfa);
|
||||
} // namespace impl
|
||||
|
||||
// The order and numeric values are important here. Please, check all use-cases before changing this enum.
|
||||
enum class NameScore : uint8_t
|
||||
{
|
||||
// example name = "Carrefour Mini"
|
||||
// example query:
|
||||
ZERO = 0, // Rewe
|
||||
SUBSTRING, // Mini
|
||||
PREFIX, // Carref
|
||||
FIRST_MATCH, // Carrefour Maxi
|
||||
FULL_PREFIX, // Carrefour
|
||||
FULL_MATCH, // Carrefour Mini
|
||||
// example query:
|
||||
ZERO = 0, // Rewe
|
||||
SUBSTRING, // Mini
|
||||
PREFIX, // Carref
|
||||
FIRST_MATCH, // Carrefour Maxi
|
||||
FULL_PREFIX, // Carrefour
|
||||
FULL_MATCH, // Carrefour Mini
|
||||
|
||||
COUNT
|
||||
};
|
||||
@@ -123,9 +123,11 @@ struct NameScores
|
||||
{
|
||||
NameScores() = default;
|
||||
NameScores(NameScore nameScore, ErrorsMade const & errorsMade, bool isAltOrOldName, size_t matchedLength)
|
||||
: m_nameScore(nameScore), m_errorsMade(errorsMade), m_isAltOrOldName(isAltOrOldName), m_matchedLength(matchedLength)
|
||||
{
|
||||
}
|
||||
: m_nameScore(nameScore)
|
||||
, m_errorsMade(errorsMade)
|
||||
, m_isAltOrOldName(isAltOrOldName)
|
||||
, m_matchedLength(matchedLength)
|
||||
{}
|
||||
|
||||
void UpdateIfBetter(NameScores const & rhs)
|
||||
{
|
||||
@@ -135,8 +137,7 @@ struct NameScores
|
||||
newNameScoreIsBetter = false;
|
||||
|
||||
// FULL_PREFIX with !alt_old_name) is better than FULL_MATCH with alt_old_name.
|
||||
if (!m_isAltOrOldName && rhs.m_isAltOrOldName &&
|
||||
!rhs.m_errorsMade.IsBetterThan(m_errorsMade) &&
|
||||
if (!m_isAltOrOldName && rhs.m_isAltOrOldName && !rhs.m_errorsMade.IsBetterThan(m_errorsMade) &&
|
||||
(int)rhs.m_nameScore - (int)m_nameScore < 2)
|
||||
{
|
||||
newNameScoreIsBetter = false;
|
||||
@@ -151,9 +152,8 @@ struct NameScores
|
||||
// It's okay to pick a slightly worse matched length if other scores are better.
|
||||
auto const matchedLengthsAreSimilar = (m_matchedLength - m_matchedLength / 4) <= rhs.m_matchedLength;
|
||||
|
||||
if (newMatchedLengthIsBetter ||
|
||||
(matchedLengthsAreSimilar && newNameScoreIsBetter) ||
|
||||
(matchedLengthsAreSimilar && nameScoresAreEqual && newLanguageIsBetter))
|
||||
if (newMatchedLengthIsBetter || (matchedLengthsAreSimilar && newNameScoreIsBetter) ||
|
||||
(matchedLengthsAreSimilar && nameScoresAreEqual && newLanguageIsBetter))
|
||||
{
|
||||
m_nameScore = rhs.m_nameScore;
|
||||
m_errorsMade = rhs.m_errorsMade;
|
||||
@@ -183,25 +183,18 @@ std::string DebugPrint(NameScores const & scores);
|
||||
// Returns true when |s| is a stop-word and may be removed from a query.
|
||||
bool IsStopWord(strings::UniString const & s);
|
||||
|
||||
|
||||
class TokensVector
|
||||
{
|
||||
std::vector<strings::UniString> m_tokens;
|
||||
std::vector<strings::LevenshteinDFA> m_dfas;
|
||||
|
||||
private:
|
||||
void Init()
|
||||
{
|
||||
m_dfas.resize(m_tokens.size());
|
||||
}
|
||||
void Init() { m_dfas.resize(m_tokens.size()); }
|
||||
|
||||
public:
|
||||
TokensVector() = default;
|
||||
explicit TokensVector(std::string_view name);
|
||||
explicit TokensVector(std::vector<strings::UniString> && tokens) : m_tokens(std::move(tokens))
|
||||
{
|
||||
Init();
|
||||
}
|
||||
explicit TokensVector(std::vector<strings::UniString> && tokens) : m_tokens(std::move(tokens)) { Init(); }
|
||||
|
||||
std::vector<strings::UniString> const & GetTokens() const { return m_tokens; }
|
||||
size_t Size() const { return m_tokens.size(); }
|
||||
@@ -214,7 +207,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// @param[in] tokens Feature's name (splitted on tokens, without delimiters) to match.
|
||||
/// @param[in] slice Input query.
|
||||
/// @todo Should make the honest recurrent score calculation like:
|
||||
@@ -267,9 +259,7 @@ NameScores GetNameScores(TokensVector & tokens, uint8_t lang, Slice const & slic
|
||||
bool isAltOrOldName = false;
|
||||
|
||||
auto const isFullScore = [&nameScore]()
|
||||
{
|
||||
return (nameScore == NameScore::FULL_MATCH || nameScore == NameScore::FULL_PREFIX);
|
||||
};
|
||||
{ return (nameScore == NameScore::FULL_MATCH || nameScore == NameScore::FULL_PREFIX); };
|
||||
|
||||
// Iterate through the entire slice. Incomplete matches can still be good.
|
||||
// Using this slice & token as an example:
|
||||
@@ -291,8 +281,7 @@ NameScores GetNameScores(TokensVector & tokens, uint8_t lang, Slice const & slic
|
||||
// -6 -5 -4 -3 -2 -1 0 1 2
|
||||
|
||||
size_t iToken, iSlice;
|
||||
for (size_t i = std::max(0, int(offset) + 1 - int(tokenCount));
|
||||
i < std::min(sliceCount, offset + 1); ++i)
|
||||
for (size_t i = std::max(0, int(offset) + 1 - int(tokenCount)); i < std::min(sliceCount, offset + 1); ++i)
|
||||
{
|
||||
size_t const tIdx = i + tokenCount - 1 - offset;
|
||||
|
||||
|
||||
@@ -6,22 +6,21 @@
|
||||
|
||||
namespace search
|
||||
{
|
||||
RegionAddressGetter::RegionAddressGetter(DataSource const & dataSource,
|
||||
storage::CountryInfoGetter const & infoGetter)
|
||||
: m_reverseGeocoder(dataSource), m_cityFinder(dataSource), m_infoGetter(infoGetter)
|
||||
RegionAddressGetter::RegionAddressGetter(DataSource const & dataSource, storage::CountryInfoGetter const & infoGetter)
|
||||
: m_reverseGeocoder(dataSource)
|
||||
, m_cityFinder(dataSource)
|
||||
, m_infoGetter(infoGetter)
|
||||
{
|
||||
m_nameGetter.LoadCountriesTree();
|
||||
m_nameGetter.SetLocale(languages::GetCurrentMapLanguage());
|
||||
}
|
||||
|
||||
ReverseGeocoder::RegionAddress RegionAddressGetter::GetNearbyRegionAddress(
|
||||
m2::PointD const & center)
|
||||
ReverseGeocoder::RegionAddress RegionAddressGetter::GetNearbyRegionAddress(m2::PointD const & center)
|
||||
{
|
||||
return ReverseGeocoder::GetNearbyRegionAddress(center, m_infoGetter, m_cityFinder);
|
||||
}
|
||||
|
||||
std::string RegionAddressGetter::GetLocalizedRegionAddress(
|
||||
ReverseGeocoder::RegionAddress const & addr) const
|
||||
std::string RegionAddressGetter::GetLocalizedRegionAddress(ReverseGeocoder::RegionAddress const & addr) const
|
||||
{
|
||||
return m_reverseGeocoder.GetLocalizedRegionAddress(addr, m_nameGetter);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#include "base/logging.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
|
||||
|
||||
namespace search
|
||||
{
|
||||
using namespace std;
|
||||
@@ -32,7 +31,8 @@ void GetPathToRoot(storage::CountryId const & id, storage::CountryTree const & c
|
||||
{
|
||||
fn(cur->Value().Name());
|
||||
cur = &cur->Parent();
|
||||
} while (!cur->IsRoot());
|
||||
}
|
||||
while (!cur->IsRoot());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -43,8 +43,8 @@ void RegionInfoGetter::LoadCountriesTree()
|
||||
CountryNameSynonyms countryNameSynonyms;
|
||||
MwmTopCityGeoIds mwmTopCityGeoIds;
|
||||
MwmTopCountryGeoIds mwmTopCountryGeoIds;
|
||||
LoadCountriesFromFile(COUNTRIES_FILE, m_countries, affiliations, countryNameSynonyms,
|
||||
mwmTopCityGeoIds, mwmTopCountryGeoIds);
|
||||
LoadCountriesFromFile(COUNTRIES_FILE, m_countries, affiliations, countryNameSynonyms, mwmTopCityGeoIds,
|
||||
mwmTopCountryGeoIds);
|
||||
}
|
||||
|
||||
void RegionInfoGetter::SetLocale(string const & locale)
|
||||
@@ -55,10 +55,7 @@ void RegionInfoGetter::SetLocale(string const & locale)
|
||||
void RegionInfoGetter::GetLocalizedFullName(storage::CountryId const & id, NameBufferT & nameParts) const
|
||||
{
|
||||
buffer_vector<storage::CountryId const *, 4> ids;
|
||||
GetPathToRoot(id, m_countries, [&ids](storage::CountryId const & id)
|
||||
{
|
||||
ids.push_back(&id);
|
||||
});
|
||||
GetPathToRoot(id, m_countries, [&ids](storage::CountryId const & id) { ids.push_back(&id); });
|
||||
|
||||
if (!ids.empty())
|
||||
{
|
||||
|
||||
@@ -30,9 +30,10 @@ void Result::FromFeature(FeatureID const & id, uint32_t mainType, uint32_t match
|
||||
}
|
||||
|
||||
Result::Result(string str, string && suggest)
|
||||
: m_resultType(Type::PureSuggest), m_str(std::move(str)), m_suggestionStr(std::move(suggest))
|
||||
{
|
||||
}
|
||||
: m_resultType(Type::PureSuggest)
|
||||
, m_str(std::move(str))
|
||||
, m_suggestionStr(std::move(suggest))
|
||||
{}
|
||||
|
||||
Result::Result(Result && res, string && suggest)
|
||||
: m_id(std::move(res.m_id))
|
||||
@@ -71,7 +72,7 @@ uint32_t Result::GetFeatureType() const
|
||||
bool Result::IsSameType(uint32_t type) const
|
||||
{
|
||||
uint8_t const level = ftype::GetLevel(type);
|
||||
for (uint32_t t : { m_mainType, m_matchedType })
|
||||
for (uint32_t t : {m_mainType, m_matchedType})
|
||||
{
|
||||
ftype::TruncValue(t, level);
|
||||
if (t == type)
|
||||
@@ -277,19 +278,15 @@ bool Results::AddResult(Result && result)
|
||||
return false;
|
||||
|
||||
for (auto i = m_results.begin(); i != it; ++i)
|
||||
{
|
||||
if (result.IsEqualSuggest(*i))
|
||||
return false;
|
||||
}
|
||||
InsertResult(it, std::move(result));
|
||||
}
|
||||
else
|
||||
{
|
||||
for (; it != m_results.end(); ++it)
|
||||
{
|
||||
if (result.IsEqualFeature(*it))
|
||||
return false;
|
||||
}
|
||||
InsertResult(m_results.end(), std::move(result));
|
||||
}
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
#include "geometry/point2d.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/checked_cast.hpp"
|
||||
#include "base/buffer_vector.hpp"
|
||||
#include "base/checked_cast.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
// Define this option to DebugPrint provenance.
|
||||
#ifdef DEBUG
|
||||
//#define SEARCH_USE_PROVENANCE
|
||||
// #define SEARCH_USE_PROVENANCE
|
||||
#endif
|
||||
|
||||
namespace search
|
||||
@@ -107,11 +107,11 @@ public:
|
||||
bool IsEqualFeature(Result const & r) const;
|
||||
|
||||
void AddHighlightRange(std::pair<uint16_t, uint16_t> const & range);
|
||||
void AddDescHighlightRange(const std::pair<uint16_t, uint16_t> & range);
|
||||
void AddDescHighlightRange(std::pair<uint16_t, uint16_t> const & range);
|
||||
std::pair<uint16_t, uint16_t> const & GetHighlightRange(size_t idx) const;
|
||||
size_t GetHighlightRangesCount() const { return m_hightlightRanges.size(); }
|
||||
|
||||
//returns ranges to hightlight in address
|
||||
|
||||
// returns ranges to hightlight in address
|
||||
std::pair<uint16_t, uint16_t> const & GetDescHighlightRange(size_t idx) const;
|
||||
size_t GetDescHighlightRangesCount() const { return m_descHightlightRanges.size(); }
|
||||
|
||||
@@ -158,7 +158,7 @@ private:
|
||||
buffer_vector<std::pair<uint16_t, uint16_t>, 4> m_hightlightRanges;
|
||||
buffer_vector<std::pair<uint16_t, uint16_t>, 4> m_descHightlightRanges;
|
||||
|
||||
std::shared_ptr<RankingInfo> m_dbgInfo; // used in debug logs and tests, nullptr in production
|
||||
std::shared_ptr<RankingInfo> m_dbgInfo; // used in debug logs and tests, nullptr in production
|
||||
|
||||
// The position that this result occupied in the vector returned by
|
||||
// a search query. -1 if undefined.
|
||||
@@ -192,10 +192,7 @@ public:
|
||||
bool IsEndedNormal() const { return m_status == Status::EndedNormal; }
|
||||
bool IsEndedCancelled() const { return m_status == Status::EndedCancelled; }
|
||||
|
||||
void SetEndMarker(bool cancelled)
|
||||
{
|
||||
m_status = cancelled ? Status::EndedCancelled : Status::EndedNormal;
|
||||
}
|
||||
void SetEndMarker(bool cancelled) { m_status = cancelled ? Status::EndedCancelled : Status::EndedNormal; }
|
||||
|
||||
// Used for results in the list.
|
||||
bool AddResult(Result && result);
|
||||
|
||||
@@ -46,8 +46,7 @@ public:
|
||||
, m_features(features)
|
||||
, m_exactlyMatchedFeatures(exactlyMatchedFeatures)
|
||||
, m_counter(0)
|
||||
{
|
||||
}
|
||||
{}
|
||||
|
||||
template <typename Value>
|
||||
void operator()(Value const & value, bool exactMatch)
|
||||
@@ -189,8 +188,7 @@ pair<bool, bool> MatchesByType(feature::TypesHolder const & types, vector<DFA> c
|
||||
}
|
||||
|
||||
template <typename DFA>
|
||||
pair<bool, bool> MatchFeatureByNameAndType(EditableMapObject const & emo,
|
||||
SearchTrieRequest<DFA> const & request)
|
||||
pair<bool, bool> MatchFeatureByNameAndType(EditableMapObject const & emo, SearchTrieRequest<DFA> const & request)
|
||||
{
|
||||
auto const & th = emo.GetTypes();
|
||||
|
||||
@@ -249,14 +247,11 @@ Retrieval::ExtendedFeatures RetrieveAddressFeaturesImpl(Retrieval::TrieRoot<Valu
|
||||
vector<uint64_t> exactlyMatchedFeatures;
|
||||
FeaturesCollector collector(cancellable, features, exactlyMatchedFeatures);
|
||||
|
||||
MatchFeaturesInTrie(
|
||||
request, root,
|
||||
[&holder](Value const & value) {
|
||||
return !holder.ModifiedOrDeleted(base::asserted_cast<uint32_t>(value.m_featureId));
|
||||
} /* filter */,
|
||||
collector);
|
||||
MatchFeaturesInTrie(request, root, [&holder](Value const & value)
|
||||
{ return !holder.ModifiedOrDeleted(base::asserted_cast<uint32_t>(value.m_featureId)); } /* filter */, collector);
|
||||
|
||||
holder.ForEachModifiedOrCreated([&](EditableMapObject const & emo, uint64_t index) {
|
||||
holder.ForEachModifiedOrCreated([&](EditableMapObject const & emo, uint64_t index)
|
||||
{
|
||||
auto const matched = MatchFeatureByNameAndType(emo, request);
|
||||
if (matched.first)
|
||||
{
|
||||
@@ -280,14 +275,11 @@ Retrieval::ExtendedFeatures RetrievePostcodeFeaturesImpl(Retrieval::TrieRoot<Val
|
||||
vector<uint64_t> exactlyMatchedFeatures;
|
||||
FeaturesCollector collector(cancellable, features, exactlyMatchedFeatures);
|
||||
|
||||
MatchPostcodesInTrie(
|
||||
slice, root,
|
||||
[&holder](Value const & value) {
|
||||
return !holder.ModifiedOrDeleted(base::asserted_cast<uint32_t>(value.m_featureId));
|
||||
} /* filter */,
|
||||
collector);
|
||||
MatchPostcodesInTrie(slice, root, [&holder](Value const & value)
|
||||
{ return !holder.ModifiedOrDeleted(base::asserted_cast<uint32_t>(value.m_featureId)); } /* filter */, collector);
|
||||
|
||||
holder.ForEachModifiedOrCreated([&](EditableMapObject const & emo, uint64_t index) {
|
||||
holder.ForEachModifiedOrCreated([&](EditableMapObject const & emo, uint64_t index)
|
||||
{
|
||||
if (MatchFeatureByPostcode(emo, slice))
|
||||
features.push_back(index);
|
||||
});
|
||||
@@ -296,8 +288,8 @@ Retrieval::ExtendedFeatures RetrievePostcodeFeaturesImpl(Retrieval::TrieRoot<Val
|
||||
}
|
||||
|
||||
Retrieval::ExtendedFeatures RetrieveGeometryFeaturesImpl(MwmContext const & context,
|
||||
base::Cancellable const & cancellable,
|
||||
m2::RectD const & rect, int scale)
|
||||
base::Cancellable const & cancellable, m2::RectD const & rect,
|
||||
int scale)
|
||||
{
|
||||
EditedFeaturesHolder holder(context.GetId());
|
||||
|
||||
@@ -311,7 +303,8 @@ Retrieval::ExtendedFeatures RetrieveGeometryFeaturesImpl(MwmContext const & cont
|
||||
|
||||
context.ForEachIndex(coverage, scale, collector);
|
||||
|
||||
holder.ForEachModifiedOrCreated([&](EditableMapObject const & emo, uint64_t index) {
|
||||
holder.ForEachModifiedOrCreated([&](EditableMapObject const & emo, uint64_t index)
|
||||
{
|
||||
auto const center = emo.GetMercator();
|
||||
if (rect.IsPointInside(center))
|
||||
features.push_back(index);
|
||||
@@ -342,13 +335,15 @@ struct RetrievePostcodeFeaturesAdaptor
|
||||
template <typename Value>
|
||||
unique_ptr<Retrieval::TrieRoot<Value>> ReadTrie(ModelReaderPtr & reader)
|
||||
{
|
||||
return trie::ReadTrie<SubReaderWrapper<Reader>, ValueList<Value>>(
|
||||
SubReaderWrapper<Reader>(reader.GetPtr()), SingleValueSerializer<Value>());
|
||||
return trie::ReadTrie<SubReaderWrapper<Reader>, ValueList<Value>>(SubReaderWrapper<Reader>(reader.GetPtr()),
|
||||
SingleValueSerializer<Value>());
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Retrieval::Retrieval(MwmContext const & context, base::Cancellable const & cancellable)
|
||||
: m_context(context), m_cancellable(cancellable), m_reader(unique_ptr<ModelReader>())
|
||||
: m_context(context)
|
||||
, m_cancellable(cancellable)
|
||||
, m_reader(unique_ptr<ModelReader>())
|
||||
{
|
||||
auto const & value = context.m_value;
|
||||
|
||||
@@ -375,8 +370,7 @@ Retrieval::Retrieval(MwmContext const & context, base::Cancellable const & cance
|
||||
m_root = ReadTrie<Uint64IndexValue>(m_reader);
|
||||
}
|
||||
|
||||
Retrieval::ExtendedFeatures Retrieval::RetrieveAddressFeatures(
|
||||
SearchTrieRequest<UniStringDFA> const & request) const
|
||||
Retrieval::ExtendedFeatures Retrieval::RetrieveAddressFeatures(SearchTrieRequest<UniStringDFA> const & request) const
|
||||
{
|
||||
return Retrieve<RetrieveAddressFeaturesAdaptor>(request);
|
||||
}
|
||||
@@ -387,8 +381,7 @@ Retrieval::ExtendedFeatures Retrieval::RetrieveAddressFeatures(
|
||||
return Retrieve<RetrieveAddressFeaturesAdaptor>(request);
|
||||
}
|
||||
|
||||
Retrieval::ExtendedFeatures Retrieval::RetrieveAddressFeatures(
|
||||
SearchTrieRequest<LevenshteinDFA> const & request) const
|
||||
Retrieval::ExtendedFeatures Retrieval::RetrieveAddressFeatures(SearchTrieRequest<LevenshteinDFA> const & request) const
|
||||
{
|
||||
return Retrieve<RetrieveAddressFeaturesAdaptor>(request);
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class TokenSlice;
|
||||
class Retrieval
|
||||
{
|
||||
public:
|
||||
template<typename Value>
|
||||
template <typename Value>
|
||||
using TrieRoot = trie::Iterator<ValueList<Value>>;
|
||||
using Features = search::CBV;
|
||||
|
||||
@@ -40,14 +40,12 @@ public:
|
||||
ExtendedFeatures(ExtendedFeatures const &) = default;
|
||||
ExtendedFeatures(ExtendedFeatures &&) = default;
|
||||
|
||||
explicit ExtendedFeatures(Features const & cbv) : m_features(cbv), m_exactMatchingFeatures(cbv)
|
||||
{
|
||||
}
|
||||
explicit ExtendedFeatures(Features const & cbv) : m_features(cbv), m_exactMatchingFeatures(cbv) {}
|
||||
|
||||
ExtendedFeatures(Features && features, Features && exactMatchingFeatures)
|
||||
: m_features(std::move(features)), m_exactMatchingFeatures(std::move(exactMatchingFeatures))
|
||||
{
|
||||
}
|
||||
: m_features(std::move(features))
|
||||
, m_exactMatchingFeatures(std::move(exactMatchingFeatures))
|
||||
{}
|
||||
|
||||
ExtendedFeatures & operator=(ExtendedFeatures const &) = default;
|
||||
ExtendedFeatures & operator=(ExtendedFeatures &&) = default;
|
||||
@@ -56,8 +54,7 @@ public:
|
||||
{
|
||||
ExtendedFeatures result;
|
||||
result.m_features = m_features.Intersect(rhs.m_features);
|
||||
result.m_exactMatchingFeatures =
|
||||
m_exactMatchingFeatures.Intersect(rhs.m_exactMatchingFeatures);
|
||||
result.m_exactMatchingFeatures = m_exactMatchingFeatures.Intersect(rhs.m_exactMatchingFeatures);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -77,9 +74,8 @@ public:
|
||||
|
||||
void ForEach(std::function<void(uint32_t, bool)> const & f) const
|
||||
{
|
||||
m_features.ForEach([&](uint64_t id) {
|
||||
f(base::asserted_cast<uint32_t>(id), m_exactMatchingFeatures.HasBit(id));
|
||||
});
|
||||
m_features.ForEach([&](uint64_t id)
|
||||
{ f(base::asserted_cast<uint32_t>(id), m_exactMatchingFeatures.HasBit(id)); });
|
||||
}
|
||||
|
||||
Features m_features;
|
||||
@@ -89,14 +85,12 @@ public:
|
||||
Retrieval(MwmContext const & context, base::Cancellable const & cancellable);
|
||||
|
||||
// Following functions retrieve all features matching to |request| from the search index.
|
||||
ExtendedFeatures RetrieveAddressFeatures(
|
||||
SearchTrieRequest<strings::UniStringDFA> const & request) const;
|
||||
ExtendedFeatures RetrieveAddressFeatures(SearchTrieRequest<strings::UniStringDFA> const & request) const;
|
||||
|
||||
ExtendedFeatures RetrieveAddressFeatures(
|
||||
SearchTrieRequest<strings::PrefixDFAModifier<strings::UniStringDFA>> const & request) const;
|
||||
|
||||
ExtendedFeatures RetrieveAddressFeatures(
|
||||
SearchTrieRequest<strings::LevenshteinDFA> const & request) const;
|
||||
ExtendedFeatures RetrieveAddressFeatures(SearchTrieRequest<strings::LevenshteinDFA> const & request) const;
|
||||
|
||||
ExtendedFeatures RetrieveAddressFeatures(
|
||||
SearchTrieRequest<strings::PrefixDFAModifier<strings::LevenshteinDFA>> const & request) const;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user