forked from organicmaps/organicmaps
[search] Implement suggestions for countries, cities, streets.
This commit is contained in:
parent
80498aa751
commit
4ae69054f4
10 changed files with 242 additions and 122 deletions
|
@ -271,10 +271,12 @@ Java_com_mapswithme_maps_SearchActivity_nativeGetResult(
|
|||
}
|
||||
else
|
||||
{
|
||||
jmethodID methodID = env->GetMethodID(klass, "<init>", "(Ljava/lang/String;)V");
|
||||
jmethodID methodID = env->GetMethodID(klass, "<init>", "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
ASSERT ( methodID, () );
|
||||
|
||||
return env->NewObject(klass, methodID, jni::ToJavaString(env, res->GetSuggestionString()));
|
||||
return env->NewObject(klass, methodID,
|
||||
jni::ToJavaString(env, res->GetString()),
|
||||
jni::ToJavaString(env, res->GetSuggestionString()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -209,6 +209,7 @@ public class SearchActivity extends MapsWithMeBaseListActivity implements Locati
|
|||
public static class SearchResult
|
||||
{
|
||||
public String m_name;
|
||||
public String m_suggestion;
|
||||
public String m_country;
|
||||
public String m_amenity;
|
||||
public String m_distance;
|
||||
|
@ -219,9 +220,10 @@ public class SearchActivity extends MapsWithMeBaseListActivity implements Locati
|
|||
|
||||
// Called from native code
|
||||
@SuppressWarnings("unused")
|
||||
public SearchResult(String suggestion)
|
||||
public SearchResult(String name, String suggestion)
|
||||
{
|
||||
m_name = suggestion;
|
||||
m_name = name;
|
||||
m_suggestion = suggestion;
|
||||
m_type = 0;
|
||||
}
|
||||
|
||||
|
@ -389,7 +391,7 @@ public class SearchActivity extends MapsWithMeBaseListActivity implements Locati
|
|||
else
|
||||
{
|
||||
// advise suggestion
|
||||
return r.m_name + ' ';
|
||||
return r.m_suggestion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,4 +69,46 @@ IsBuildingChecker::IsBuildingChecker()
|
|||
m_types.push_back(c.GetTypeByPath(vector<string>(arr1, arr1 + 2)));
|
||||
}
|
||||
|
||||
IsLocalityChecker::IsLocalityChecker()
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
char const * arr[][2] = {
|
||||
{ "place", "country" },
|
||||
{ "place", "state" },
|
||||
{ "place", "city" },
|
||||
{ "place", "town" }
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
|
||||
m_types.push_back(c.GetTypeByPath(vector<string>(arr[i], arr[i] + 2)));
|
||||
}
|
||||
|
||||
Type IsLocalityChecker::GetLocalityType(feature::TypesHolder const & types) const
|
||||
{
|
||||
for (size_t i = 0; i < types.Size(); ++i)
|
||||
{
|
||||
uint32_t t = types[i];
|
||||
ftype::TruncValue(t, 2);
|
||||
|
||||
if (t == m_types[0])
|
||||
return COUNTRY;
|
||||
|
||||
if (t == m_types[1])
|
||||
return STATE;
|
||||
|
||||
for (int j = 2; j < m_types.size(); ++j)
|
||||
if (t == m_types[j])
|
||||
return CITY;
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
Type IsLocalityChecker::GetLocalityType(const FeatureType & f) const
|
||||
{
|
||||
feature::TypesHolder types(f);
|
||||
return GetLocalityType(types);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -36,4 +36,17 @@ public:
|
|||
IsBuildingChecker();
|
||||
};
|
||||
|
||||
/// Type of locality (do not change values - they have detalization order)
|
||||
/// COUNTRY < STATE < CITY
|
||||
enum Type { NONE = -1, COUNTRY = 0, STATE, CITY };
|
||||
|
||||
class IsLocalityChecker : public BaseChecker
|
||||
{
|
||||
public:
|
||||
IsLocalityChecker();
|
||||
|
||||
Type GetLocalityType(feature::TypesHolder const & types) const;
|
||||
Type GetLocalityType(FeatureType const & f) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -176,19 +176,6 @@ PreResult2::PreResult2(m2::RectD const & viewport, m2::PointD const & pos, doubl
|
|||
CalcParams(viewport, pos);
|
||||
}
|
||||
|
||||
PreResult2::PreResult2(string const & name, int penalty)
|
||||
: m_str(name), m_completionString(name + " "),
|
||||
|
||||
// Categories should always be the first:
|
||||
m_distance(-1000.0), // smallest distance :)
|
||||
m_distanceFromViewportCenter(-1000.0),
|
||||
m_resultType(RESULT_CATEGORY),
|
||||
m_rank(255), // best rank
|
||||
m_viewportDistance(0), // closest to viewport
|
||||
m_geomType(feature::GEOM_UNDEFINED)
|
||||
{
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class SkipRegionInfo
|
||||
|
@ -243,12 +230,9 @@ Result PreResult2::GenerateFinalResult(
|
|||
#endif
|
||||
, type, m_distance);
|
||||
|
||||
case RESULT_LATLON:
|
||||
return Result(GetCenter(), m_str, info.m_name, info.m_flag, m_distance);
|
||||
|
||||
default:
|
||||
ASSERT_EQUAL ( m_resultType, RESULT_CATEGORY, () );
|
||||
return Result(m_str, m_completionString);
|
||||
ASSERT_EQUAL(m_resultType, RESULT_LATLON, ());
|
||||
return Result(GetCenter(), m_str, info.m_name, info.m_flag, m_distance);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,7 +255,7 @@ bool PreResult2::StrictEqualF::operator() (PreResult2 const & r) const
|
|||
{
|
||||
if (m_r.m_resultType == r.m_resultType && m_r.m_resultType == RESULT_FEATURE)
|
||||
{
|
||||
if (m_r.m_str == r.m_str && m_r.GetBestType() == r.GetBestType())
|
||||
if (m_r.IsEqualCommon(r))
|
||||
return (PointDistance(m_r.GetCenter(), r.GetCenter()) < DIST_EQUAL_RESULTS);
|
||||
}
|
||||
|
||||
|
@ -301,12 +285,18 @@ bool PreResult2::EqualLinearTypesF::operator() (PreResult2 const & r1, PreResult
|
|||
{
|
||||
// Note! Do compare for distance when filtering linear objects.
|
||||
// Otherwise we will skip the results for different parts of the map.
|
||||
return (r1.m_geomType == r2.m_geomType &&
|
||||
r1.m_geomType == feature::GEOM_LINE &&
|
||||
r1.m_str == r2.m_str &&
|
||||
return (r1.m_geomType == feature::GEOM_LINE &&
|
||||
r1.IsEqualCommon(r2) &&
|
||||
PointDistance(r1.GetCenter(), r2.GetCenter()) < DIST_SAME_STREET);
|
||||
}
|
||||
|
||||
bool PreResult2::IsEqualCommon(PreResult2 const & r) const
|
||||
{
|
||||
return (m_geomType == r.m_geomType &&
|
||||
GetBestType() == r.GetBestType() &&
|
||||
m_str == r.m_str);
|
||||
}
|
||||
|
||||
bool PreResult2::IsStreet() const
|
||||
{
|
||||
static ftypes::IsStreetChecker checker;
|
||||
|
|
|
@ -66,7 +66,6 @@ public:
|
|||
enum ResultType
|
||||
{
|
||||
RESULT_LATLON,
|
||||
RESULT_CATEGORY,
|
||||
RESULT_FEATURE
|
||||
};
|
||||
|
||||
|
@ -79,9 +78,6 @@ public:
|
|||
PreResult2(m2::RectD const & viewport, m2::PointD const & pos,
|
||||
double lat, double lon);
|
||||
|
||||
// For RESULT_CATEGORY.
|
||||
PreResult2(string const & name, int penalty);
|
||||
|
||||
/// @param[in] pInfo Need to get region for result.
|
||||
/// @param[in] pCat Categories need to display readable type string.
|
||||
/// @param[in] pTypes Set of preffered types that match input tokens by categories.
|
||||
|
@ -120,13 +116,18 @@ public:
|
|||
string DebugPrint() const;
|
||||
|
||||
bool IsStreet() const;
|
||||
|
||||
inline FeatureID const & GetID() const { return m_id; }
|
||||
inline string const & GetName() const { return m_str; }
|
||||
inline feature::TypesHolder const & GetTypes() const { return m_types; }
|
||||
|
||||
private:
|
||||
template <class T> friend bool LessRankT(T const & r1, T const & r2);
|
||||
template <class T> friend bool LessViewportDistanceT(T const & r1, T const & r2);
|
||||
template <class T> friend bool LessDistanceT(T const & r1, T const & r2);
|
||||
|
||||
bool IsEqualCommon(PreResult2 const & r) const;
|
||||
|
||||
string GetFeatureType(CategoriesHolder const * pCat,
|
||||
set<uint32_t> const * pTypes,
|
||||
int8_t lang) const;
|
||||
|
@ -136,7 +137,7 @@ private:
|
|||
|
||||
uint32_t GetBestType(set<uint32_t> const * pPrefferedTypes = 0) const;
|
||||
|
||||
string m_str, m_completionString;
|
||||
string m_str;
|
||||
|
||||
struct RegionInfo
|
||||
{
|
||||
|
|
|
@ -28,8 +28,8 @@ Result::Result(m2::PointD const & fCenter,
|
|||
{
|
||||
}
|
||||
|
||||
Result::Result(string const & str, string const & suggestionStr)
|
||||
: m_str(str), m_suggestionStr(suggestionStr)
|
||||
Result::Result(string const & str, string const & suggest)
|
||||
: m_str(str), m_suggestionStr(suggest)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -70,23 +70,33 @@ char const * Result::GetSuggestionString() const
|
|||
bool Result::operator== (Result const & r) const
|
||||
{
|
||||
ResultType const type = GetResultType();
|
||||
if (type == r.GetResultType() && type != RESULT_SUGGESTION)
|
||||
if (type == r.GetResultType())
|
||||
{
|
||||
// This function is used to filter duplicate results in cases:
|
||||
// - emitted Wrold.mwm and Country.mwm
|
||||
// - after additional search in all mwm
|
||||
// so it's suitable here to test for 500m
|
||||
return (m_str == r.m_str && m_region == r.m_region &&
|
||||
m_featureType == r.m_featureType &&
|
||||
PointDistance(m_center, r.m_center) < 500.0);
|
||||
if (type == RESULT_SUGGESTION)
|
||||
return m_suggestionStr == r.m_suggestionStr;
|
||||
else
|
||||
{
|
||||
// This function is used to filter duplicate results in cases:
|
||||
// - emitted World.mwm and Country.mwm
|
||||
// - after additional search in all mwm
|
||||
// so it's suitable here to test for 500m
|
||||
return (m_str == r.m_str && m_region == r.m_region &&
|
||||
m_featureType == r.m_featureType &&
|
||||
PointDistance(m_center, r.m_center) < 500.0);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Results::AddResultCheckExisting(Result const & r)
|
||||
bool Results::AddResultCheckExistingEx(Result const & r)
|
||||
{
|
||||
if (find(m_vec.begin(), m_vec.end(), r) == m_vec.end())
|
||||
{
|
||||
AddResult(r);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
string const & flag, double distance);
|
||||
|
||||
/// For RESULT_SUGGESTION.
|
||||
Result(string const & str, string const & suggestionStr);
|
||||
Result(string const & str, string const & suggest);
|
||||
|
||||
/// Strings that is displayed in the GUI.
|
||||
//@{
|
||||
|
@ -100,7 +100,11 @@ public:
|
|||
//@}
|
||||
|
||||
inline void AddResult(Result const & r) { m_vec.push_back(r); }
|
||||
void AddResultCheckExisting(Result const & r);
|
||||
inline void AddResultCheckExisting(Result const & r)
|
||||
{
|
||||
(void)AddResultCheckExistingEx(r);
|
||||
}
|
||||
bool AddResultCheckExistingEx(Result const & r);
|
||||
|
||||
inline void Clear() { m_vec.clear(); }
|
||||
|
||||
|
|
|
@ -270,6 +270,8 @@ void Query::ClearQueues()
|
|||
|
||||
void Query::SetQuery(string const & query)
|
||||
{
|
||||
m_query = &query;
|
||||
|
||||
#ifdef HOUSE_SEARCH_TEST
|
||||
m_house.clear();
|
||||
m_streetID.clear();
|
||||
|
@ -301,7 +303,6 @@ void Query::SetQuery(string const & query)
|
|||
m_house.swap(m_prefix);
|
||||
m_prefix.clear();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (!m_tokens.empty() && !delims(strings::LastUniChar(query)))
|
||||
|
@ -316,6 +317,17 @@ void Query::SetQuery(string const & query)
|
|||
|
||||
// assign tokens and prefix to scorer
|
||||
m_keywordsScorer.SetKeywords(m_tokens.data(), m_tokens.size(), m_prefix);
|
||||
|
||||
// get preffered types to show in results
|
||||
m_prefferedTypes.clear();
|
||||
if (m_pCategories)
|
||||
{
|
||||
for (size_t i = 0; i < m_tokens.size(); ++i)
|
||||
m_pCategories->ForEachTypeByName(m_tokens[i], MakeInsertFunctor(m_prefferedTypes));
|
||||
|
||||
if (!m_prefix.empty())
|
||||
m_pCategories->ForEachTypeByName(m_prefix, MakeInsertFunctor(m_prefferedTypes));
|
||||
}
|
||||
}
|
||||
|
||||
void Query::SearchCoordinates(string const & query, Results & res) const
|
||||
|
@ -635,16 +647,7 @@ void Query::FlushResults(Results & res, bool allMWMs, size_t resCount)
|
|||
|
||||
SortByIndexedValue(indV, CompFactory2());
|
||||
|
||||
// get preffered types to show in results
|
||||
set<uint32_t> prefferedTypes;
|
||||
if (m_pCategories)
|
||||
{
|
||||
for (size_t i = 0; i < m_tokens.size(); ++i)
|
||||
m_pCategories->ForEachTypeByName(m_tokens[i], MakeInsertFunctor(prefferedTypes));
|
||||
|
||||
if (!m_prefix.empty())
|
||||
m_pCategories->ForEachTypeByName(m_prefix, MakeInsertFunctor(prefferedTypes));
|
||||
}
|
||||
ProcessSuggestions(indV, res);
|
||||
|
||||
// emit feature results
|
||||
size_t count = res.GetCount();
|
||||
|
@ -654,7 +657,94 @@ void Query::FlushResults(Results & res, bool allMWMs, size_t resCount)
|
|||
|
||||
LOG(LDEBUG, (indV[i]));
|
||||
|
||||
(res.*addFn)(MakeResult(*(indV[i]), &prefferedTypes));
|
||||
(res.*addFn)(MakeResult(*(indV[i])));
|
||||
}
|
||||
}
|
||||
|
||||
ftypes::Type Query::GetLocalityIndex(feature::TypesHolder const & types) const
|
||||
{
|
||||
static ftypes::IsLocalityChecker checker;
|
||||
return checker.GetLocalityType(types);
|
||||
}
|
||||
|
||||
void Query::GetSuggestion(string const & name, string & suggest) const
|
||||
{
|
||||
// Split result's name on tokens.
|
||||
search::Delimiters delims;
|
||||
vector<strings::UniString> vName;
|
||||
SplitUniString(NormalizeAndSimplifyString(name), MakeBackInsertFunctor(vName), delims);
|
||||
|
||||
// Find tokens that already present in input query.
|
||||
vector<bool> tokensMatched(vName.size());
|
||||
bool prefixMatched = false;
|
||||
for (size_t i = 0; i < vName.size(); ++i)
|
||||
{
|
||||
if (find(m_tokens.begin(), m_tokens.end(), vName[i]) != m_tokens.end())
|
||||
tokensMatched[i] = true;
|
||||
else
|
||||
if (vName[i].size() > m_prefix.size() &&
|
||||
StartsWith(vName[i].begin(), vName[i].end(), m_prefix.begin(), m_prefix.end()))
|
||||
{
|
||||
prefixMatched = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Name doesn't match prefix - do nothing.
|
||||
if (!prefixMatched)
|
||||
return;
|
||||
|
||||
// Find start iterator of prefix in input query.
|
||||
typedef utf8::unchecked::iterator<string::const_iterator> IterT;
|
||||
IterT iter(m_query->end());
|
||||
while (iter.base() != m_query->begin())
|
||||
{
|
||||
IterT prev = iter;
|
||||
--prev;
|
||||
|
||||
if (delims(*prev))
|
||||
break;
|
||||
else
|
||||
iter = prev;
|
||||
}
|
||||
|
||||
// Assign suggest with input query without prefix.
|
||||
suggest.assign(m_query->begin(), iter.base());
|
||||
|
||||
// Append unmatched result's tokens to the suggestion.
|
||||
for (size_t i = 0; i < vName.size(); ++i)
|
||||
if (!tokensMatched[i])
|
||||
{
|
||||
suggest += strings::ToUtf8(vName[i]);
|
||||
suggest += " ";
|
||||
}
|
||||
}
|
||||
|
||||
template <class T> void Query::ProcessSuggestions(vector<T> & vec, Results & res) const
|
||||
{
|
||||
if (m_prefix.empty())
|
||||
return;
|
||||
|
||||
int added = 0;
|
||||
for (typename vector<T>::iterator i = vec.begin(); i != vec.end();)
|
||||
{
|
||||
impl::PreResult2 const & r = **i;
|
||||
|
||||
ftypes::Type const type = GetLocalityIndex(r.GetTypes());
|
||||
if ((type == ftypes::COUNTRY || type == ftypes::CITY) || r.IsStreet())
|
||||
{
|
||||
string suggest;
|
||||
GetSuggestion(r.GetName(), suggest);
|
||||
if (!suggest.empty() && added < MAX_SUGGESTS_COUNT)
|
||||
{
|
||||
if (res.AddResultCheckExistingEx(Result(r.GetName(), suggest)))
|
||||
{
|
||||
++added;
|
||||
i = vec.erase(i);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -705,9 +795,9 @@ void Query::GetBestMatchName(FeatureType const & f, string & name) const
|
|||
(void)f.ForEachNameRef(bestNameFinder);
|
||||
}
|
||||
|
||||
Result Query::MakeResult(impl::PreResult2 const & r, set<uint32_t> const * pPrefferedTypes/* = 0*/) const
|
||||
Result Query::MakeResult(impl::PreResult2 const & r) const
|
||||
{
|
||||
return r.GenerateFinalResult(m_pInfoGetter, m_pCategories, pPrefferedTypes, GetLanguage(LANG_CURRENT));
|
||||
return r.GenerateFinalResult(m_pInfoGetter, m_pCategories, &m_prefferedTypes, GetLanguage(LANG_CURRENT));
|
||||
}
|
||||
|
||||
namespace impl
|
||||
|
@ -1097,17 +1187,17 @@ namespace impl
|
|||
Query::TrieValueT m_value;
|
||||
vector<size_t> m_matchedTokens; ///< indexes of matched tokens for locality
|
||||
|
||||
/// Type of locality (do not change values - they have detalization order)
|
||||
/// COUNTRY < STATE < CITY
|
||||
enum Type { NONE = -1, COUNTRY = 0, STATE, CITY };
|
||||
Type m_type;
|
||||
ftypes::Type m_type;
|
||||
|
||||
Locality() : m_type(NONE) {}
|
||||
Locality(Query::TrieValueT const & val, Type type) : m_value(val), m_type(type) {}
|
||||
Locality() : m_type(ftypes::NONE) {}
|
||||
Locality(Query::TrieValueT const & val, ftypes::Type type)
|
||||
: m_value(val), m_type(type)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
if (m_type != NONE)
|
||||
if (m_type != ftypes::NONE)
|
||||
{
|
||||
ASSERT ( !m_matchedTokens.empty(), () );
|
||||
return true;
|
||||
|
@ -1183,6 +1273,8 @@ namespace impl
|
|||
bool const isMatched = IsFullNameMatched();
|
||||
|
||||
// Do filtering of possible localities.
|
||||
using namespace ftypes;
|
||||
|
||||
switch (m_type)
|
||||
{
|
||||
case STATE: // we process USA, Canada states only for now
|
||||
|
@ -1336,51 +1428,6 @@ namespace impl
|
|||
FeaturesVector m_vector;
|
||||
size_t m_index; ///< index of processing token
|
||||
|
||||
/// Check for "locality" types.
|
||||
class TypeChecker
|
||||
{
|
||||
vector<uint32_t> m_vec;
|
||||
|
||||
public:
|
||||
TypeChecker()
|
||||
{
|
||||
Classificator const & c = classif();
|
||||
|
||||
char const * arr[][2] = {
|
||||
{ "place", "country" },
|
||||
{ "place", "state" },
|
||||
{ "place", "city" },
|
||||
{ "place", "town" }
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(arr); ++i)
|
||||
m_vec.push_back(c.GetTypeByPath(vector<string>(arr[i], arr[i] + 2)));
|
||||
}
|
||||
|
||||
/// @return Feature type and locality type @see Locality::m_index.
|
||||
Locality::Type GetLocalityIndex(FeatureType const & f)
|
||||
{
|
||||
feature::TypesHolder types(f);
|
||||
for (size_t i = 0; i < types.Size(); ++i)
|
||||
{
|
||||
uint32_t t = types[i];
|
||||
ftype::TruncValue(t, 2);
|
||||
|
||||
if (t == m_vec[0])
|
||||
return Locality::COUNTRY;
|
||||
|
||||
if (t == m_vec[1])
|
||||
return Locality::STATE;
|
||||
|
||||
for (int j = 2; j < m_vec.size(); ++j)
|
||||
if (t == m_vec[j])
|
||||
return Locality::CITY;
|
||||
}
|
||||
|
||||
return Locality::NONE;
|
||||
}
|
||||
};
|
||||
|
||||
Locality * PushLocality(Locality const & l)
|
||||
{
|
||||
ASSERT ( 0 <= l.m_type && l.m_type <= ARRAY_SIZE(m_localities), (l.m_type) );
|
||||
|
@ -1508,9 +1555,8 @@ namespace impl
|
|||
m_vector.Get(v.m_featureId, f);
|
||||
|
||||
// check, if feature is locality
|
||||
static TypeChecker checker;
|
||||
Locality::Type const index = checker.GetLocalityIndex(f);
|
||||
if (index != Locality::NONE)
|
||||
ftypes::Type const index = m_query.GetLocalityIndex(feature::TypesHolder(f));
|
||||
if (index != ftypes::NONE)
|
||||
{
|
||||
Locality * loc = PushLocality(Locality(v, index));
|
||||
if (loc)
|
||||
|
@ -1527,17 +1573,17 @@ namespace impl
|
|||
|
||||
void SortLocalities()
|
||||
{
|
||||
for (int i = Locality::COUNTRY; i <= Locality::CITY; ++i)
|
||||
for (int i = ftypes::COUNTRY; i <= ftypes::CITY; ++i)
|
||||
sort(m_localities[i].begin(), m_localities[i].end());
|
||||
}
|
||||
|
||||
void GetRegions(vector<Region> & regions) const
|
||||
{
|
||||
//LOG(LDEBUG, ("Countries before processing = ", m_localities[Locality::COUNTRY]));
|
||||
//LOG(LDEBUG, ("States before processing = ", m_localities[Locality::STATE]));
|
||||
//LOG(LDEBUG, ("Countries before processing = ", m_localities[ftypes::COUNTRY]));
|
||||
//LOG(LDEBUG, ("States before processing = ", m_localities[ftypes::STATE]));
|
||||
|
||||
AddRegions(Locality::STATE, regions);
|
||||
AddRegions(Locality::COUNTRY, regions);
|
||||
AddRegions(ftypes::STATE, regions);
|
||||
AddRegions(ftypes::COUNTRY, regions);
|
||||
|
||||
//LOG(LDEBUG, ("Regions after processing = ", regions));
|
||||
}
|
||||
|
@ -1545,7 +1591,7 @@ namespace impl
|
|||
void GetBestCity(Locality & res, vector<Region> const & regions)
|
||||
{
|
||||
size_t const regsCount = regions.size();
|
||||
vector<Locality> & arr = m_localities[Locality::CITY];
|
||||
vector<Locality> & arr = m_localities[ftypes::CITY];
|
||||
|
||||
// Interate in reverse order from better to generic locality.
|
||||
for (vector<Locality>::reverse_iterator i = arr.rbegin(); i != arr.rend(); ++i)
|
||||
|
@ -1842,7 +1888,8 @@ bool Query::MatchForSuggestionsImpl(strings::UniString const & token, int8_t lan
|
|||
(it->m_lang == lang) && // push suggestions only for needed language
|
||||
StartsWith(s.begin(), s.end(), token.begin(), token.end()))
|
||||
{
|
||||
res.AddResult(MakeResult(impl::PreResult2(strings::ToUtf8(s), it->m_prefixLength)));
|
||||
string const utf8Str = strings::ToUtf8(s);
|
||||
res.AddResult(Result(utf8Str, utf8Str + " "));
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include "intermediate_result.hpp"
|
||||
#include "keyword_lang_matcher.hpp"
|
||||
#include "ftypes_matcher.hpp"
|
||||
|
||||
#include "../indexer/search_trie.hpp"
|
||||
#include "../indexer/index.hpp" // for Index::MwmLock
|
||||
|
@ -161,6 +162,10 @@ private:
|
|||
|
||||
void FlushResults(Results & res, bool allMWMs, size_t resCount);
|
||||
|
||||
ftypes::Type GetLocalityIndex(feature::TypesHolder const & types) const;
|
||||
void GetSuggestion(string const & name, string & suggest) const;
|
||||
template <class T> void ProcessSuggestions(vector<T> & vec, Results & res) const;
|
||||
|
||||
void SearchAddress();
|
||||
|
||||
/// Search for best localities by input tokens.
|
||||
|
@ -186,7 +191,7 @@ private:
|
|||
|
||||
void GetBestMatchName(FeatureType const & f, string & name) const;
|
||||
|
||||
Result MakeResult(impl::PreResult2 const & r, set<uint32_t> const * pPrefferedTypes = 0) const;
|
||||
Result MakeResult(impl::PreResult2 const & r) const;
|
||||
|
||||
Index const * m_pIndex;
|
||||
CategoriesHolder const * m_pCategories;
|
||||
|
@ -195,8 +200,10 @@ private:
|
|||
|
||||
volatile bool m_cancel;
|
||||
|
||||
string const * m_query;
|
||||
buffer_vector<strings::UniString, 32> m_tokens;
|
||||
strings::UniString m_prefix;
|
||||
set<uint32_t> m_prefferedTypes;
|
||||
|
||||
#ifdef HOUSE_SEARCH_TEST
|
||||
strings::UniString m_house;
|
||||
|
@ -204,6 +211,8 @@ private:
|
|||
search::HouseDetector m_houseDetector;
|
||||
#endif
|
||||
|
||||
static int const MAX_SUGGESTS_COUNT = 5;
|
||||
|
||||
/// 0 - current viewport rect
|
||||
/// 1 - near me rect
|
||||
/// 2 - around city rect
|
||||
|
|
Loading…
Add table
Reference in a new issue