WIP: Localized address ordering #8682

Draft
zyphlar wants to merge 4 commits from localized_address_ordering into master
8 changed files with 103 additions and 64 deletions

View file

@ -674,9 +674,6 @@ void Framework::FillInfoFromFeatureType(FeatureType & ft, place_page::Info & inf
info.SetFeatureStatus(featureStatus);
info.SetLocalizedWifiString(m_stringsBundle.GetString("wifi"));
if (ftypes::IsAddressObjectChecker::Instance()(ft))
info.SetAddress(GetAddressAtPoint(feature::GetCenter(ft)).FormatAddress());
info.SetFromFeatureType(ft);
FillDescription(ft, info);
@ -691,18 +688,23 @@ void Framework::FillInfoFromFeatureType(FeatureType & ft, place_page::Info & inf
// Fill countryId for place page info
auto const & types = info.GetTypes();
bool const isState = ftypes::IsStateChecker::Instance()(types);
size_t const level = isState ? 1 : 0;
CountriesVec countries;
CountryId countryId = m_infoGetter->GetRegionCountryId(info.GetMercator());
GetStorage().GetTopmostNodesFor(countryId, countries, level);
if (countries.size() == 1)
countryId = countries.front();
if (isState || ftypes::IsCountryChecker::Instance()(types))
{
size_t const level = isState ? 1 : 0;
CountriesVec countries;
CountryId countryId = m_infoGetter->GetRegionCountryId(info.GetMercator());
GetStorage().GetTopmostNodesFor(countryId, countries, level);
if (countries.size() == 1)
countryId = countries.front();
info.SetCountryId(countryId);
info.SetTopmostCountryIds(std::move(countries));
}
if (ftypes::IsAddressObjectChecker::Instance()(ft)) {
info.SetAddress(GetAddressAtPoint(feature::GetCenter(ft)).FormatAddress(countryId)); // SetTitleAndAddress
}
info.SetFromFeatureType(ft);
FillDescription(ft, info);
}
void Framework::FillApiMarkInfo(ApiMarkPoint const & api, place_page::Info & info) const

View file

@ -138,6 +138,7 @@ public:
/// UI setters
void SetCustomName(std::string const & name);
void SetTitlesForBookmark();
// void SetTitleAndAddress(std::string && title) { m_uiTitle = std::move(title); m_address = m_uiTitle; };
void SetCustomNames(std::string const & title, std::string const & subtitle);
void SetCustomNameWithCoordinates(m2::PointD const & mercator, std::string const & name);
void SetAddress(std::string && address) { m_address = std::move(address); }

View file

@ -108,6 +108,21 @@ public:
Postcode
};
struct RegionInfo
{
storage::CountryId m_countryId;
m2::PointD m_point;
void SetParams(storage::CountryId const & countryId, m2::PointD const & point)
{
m_countryId = countryId;
m_point = point;
}
bool GetCountryId(storage::CountryInfoGetter const & infoGetter,
storage::CountryId & countryId) const;
};
/// For Type::Feature and Type::Building.
RankerResult(FeatureType & ft, m2::PointD const & center,
std::string displayName, std::string const & fileName);
@ -141,6 +156,7 @@ public:
bool GetCountryId(storage::CountryInfoGetter const & infoGetter, uint32_t ftype,
storage::CountryId & countryId) const;
RegionInfo const & GetRegion() const { return m_region; }
bool IsEqualBasic(RankerResult const & r) const;
bool IsEqualCommon(RankerResult const & r) const;
@ -157,21 +173,6 @@ private:
friend class RankerResultMaker;
friend class Ranker;
struct RegionInfo
{
storage::CountryId m_countryId;
m2::PointD m_point;
void SetParams(storage::CountryId const & countryId, m2::PointD const & point)
{
m_countryId = countryId;
m_point = point;
}
bool GetCountryId(storage::CountryInfoGetter const & infoGetter,
storage::CountryId & countryId) const;
};
RegionInfo m_region;
feature::TypesHolder m_types;
std::string m_str;

View file

@ -299,23 +299,6 @@ ftypes::LocalityType GetLocalityIndex(feature::TypesHolder const & types)
UNREACHABLE();
}
// TODO: Format street and house number according to local country's rules.
string FormatStreetAndHouse(ReverseGeocoder::Address const & addr)
{
return addr.GetStreetName() + ", " + addr.GetHouseNumber();
}
// TODO: Share common formatting code for search results and place page.
string FormatFullAddress(ReverseGeocoder::Address const & addr, string const & region)
{
/// @todo Print "near" for not exact addresses.
/// Add some threshold for addr:interpolation or refactor ReverseGeocoder?
if (addr.GetDistance() != 0)
return region;
return FormatStreetAndHouse(addr) + (region.empty() ? "" : ", ") + region;
}
} // namespace
class RankerResultMaker
@ -494,7 +477,8 @@ private:
{
string streetName;
m_ranker.GetBestMatchName(*streetFeature, streetName);
name = streetName + ", " + addr.GetHouseNumber();
LOG(LDEBUG, ("WAB LoadFeature", streetName, addr.GetHouseNumber()));
name = streetName + ", " + addr.GetHouseNumber(); /// @todo consider using partialAddress logic below
}
}
}
@ -719,25 +703,79 @@ void Ranker::Finish(bool cancelled)
m_emitter.Finish(cancelled);
}
/// This is one of the final steps in finishing a result and displaying an address in the GUI
/// So it returns a full string like "City, Street Name, 123, Province, Country"
/// @todo Share common formatting code for search results and place page.
Result Ranker::MakeResult(RankerResult const & rankerResult, bool needAddress, bool needHighlighting) const
{
// If we don't want to bother with addresses at all, just use the ranker result which is "Main St, 123"
Result res(rankerResult.GetCenter(), rankerResult.m_str);
if (needAddress)
{
string address = GetLocalizedRegionInfoForResult(rankerResult);
string partialAddress = "";
string fullAddress = "";
ReverseGeocoder::Address addr;
string_view city;
string region = GetLocalizedRegionInfoForResult(rankerResult);
// Format full address only for suitable results.
if (ftypes::IsAddressObjectChecker::Instance()(rankerResult.GetTypes()))
{
ReverseGeocoder::Address addr;
if (ftypes::IsAddressObjectChecker::Instance()(rankerResult.GetTypes())) {
if (!(rankerResult.GetID().IsValid() && m_reverseGeocoder.GetExactAddress(rankerResult.GetID(), addr)))
m_reverseGeocoder.GetNearbyAddress(rankerResult.GetCenter(), addr);
address = FormatFullAddress(addr, address);
}
res.SetAddress(std::move(address));
// Get city when possible
if (ftypes::IsLocalityChecker::Instance().GetType(rankerResult.GetTypes()) == ftypes::LocalityType::None)
{
m_localities.GetLocality(res.GetFeatureCenter(), [&](LocalityItem const & item)
{
item.GetReadableName(city);
});
}
/// @todo Print "near" for not exact addresses.
/// Add some threshold for addr:interpolation or refactor ReverseGeocoder?
if (rankerResult.GetRegion().m_countryId.starts_with("US_")) {
// US partial is 123 Main St
if (addr.IsValid() && addr.GetDistance() == 0) partialAddress += addr.GetHouseNumber() + " " + addr.GetStreetName();
// US full is 123 Main St, Chicago, Illinois, USA
if (addr.IsValid() && addr.GetDistance() == 0) fullAddress += addr.GetHouseNumber() + " " + addr.GetStreetName();
if (!city.empty()) {
if(!fullAddress.empty()) fullAddress += ", ";
fullAddress.append(city);
}
if (!region.empty())
{
if(!fullAddress.empty()) fullAddress += ", ";
fullAddress += region;
}
}
else
{
// OM default partial is Main St, 123
if (addr.IsValid() && addr.GetDistance() == 0) partialAddress += addr.GetStreetName() + ", " + addr.GetHouseNumber();
// OM default full is Chicago, Main St, 123, Illinois, USA
if (!city.empty()) fullAddress.append(city);
if (addr.IsValid() && addr.GetDistance() == 0)
{
if(!fullAddress.empty()) fullAddress += ", ";
fullAddress += addr.GetStreetName() + ", " + addr.GetHouseNumber();
}
if (!region.empty())
{
if(!fullAddress.empty()) fullAddress += ", ";
fullAddress += region;
}
}
if(!partialAddress.empty()) res.SetString(std::move(partialAddress));
res.SetAddress(std::move(fullAddress));
}
switch (rankerResult.GetResultType())
@ -750,16 +788,6 @@ Result Ranker::MakeResult(RankerResult const & rankerResult, bool needAddress, b
case RankerResult::Type::Postcode: res.SetType(Result::Type::Postcode); break;
}
if (needAddress && ftypes::IsLocalityChecker::Instance().GetType(rankerResult.GetTypes()) == ftypes::LocalityType::None)
{
m_localities.GetLocality(res.GetFeatureCenter(), [&](LocalityItem const & item)
{
string_view city;
if (item.GetReadableName(city))
res.PrependCity(city);
});
}
if (needHighlighting)
HighlightResult(m_params.m_query.m_tokens, m_params.m_query.m_prefix, res);
@ -768,7 +796,7 @@ Result Ranker::MakeResult(RankerResult const & rankerResult, bool needAddress, b
#ifdef SEARCH_USE_PROVENANCE
res.SetProvenance(std::move(rankerResult.m_provenance));
#endif
LOG(LDEBUG, ("WAB MakeResult", res));
return res;
}

View file

@ -237,6 +237,7 @@ string DebugPrint(Result const & result)
ostringstream os;
os << "Result [";
os << "name: " << result.GetString();
os << ", addr: " << result.GetAddress();
os << ", type: " << readableType;
os << ", info: " << DebugPrint(result.GetRankingInfo());

View file

@ -61,6 +61,7 @@ public:
Result(m2::PointD const & pt, std::string const & name) : m_center(pt), m_str(name) {}
void FromFeature(FeatureID const & id, uint32_t mainType, uint32_t matchedType, Details const & details);
void SetString(std::string && str) { m_str = std::move(str); }
void SetAddress(std::string && address) { m_address = std::move(address); }
void SetType(Result::Type type) { m_resultType = type; }

View file

@ -331,6 +331,7 @@ string ReverseGeocoder::GetLocalizedRegionAddress(RegionAddress const & addr,
addrStr = nameGetter.GetLocalizedFullName(addr.m_countryId);
}
LOG(LWARNING, ("WAB LocalizedRegionAddress", addrStr));
return addrStr;
}
@ -370,7 +371,7 @@ std::optional<HouseToStreetTable::Result> ReverseGeocoder::HouseTable::Get(Featu
return res;
}
string ReverseGeocoder::Address::FormatAddress() const
string ReverseGeocoder::Address::FormatAddress(storage::CountryId countryId) const
{
// Check whether we can format address according to the query type
// and actual address distance.
@ -380,7 +381,10 @@ string ReverseGeocoder::Address::FormatAddress() const
if (m_building.m_distanceMeters > 200.0)
return {};
return Join(m_street.m_name, m_building.m_name);
if (countryId == "United States of America")
return m_building.m_name + " " + m_street.m_name; // WB
else
return Join(m_street.m_name, m_building.m_name); // WB
}
bool ReverseGeocoder::RegionAddress::IsValid() const

View file

@ -92,7 +92,8 @@ public:
bool IsValid() const { return m_building.IsValid() && m_street.IsValid(); }
// 7 vulica Frunze
std::string FormatAddress() const;
std::string FormatAddress() const { return FormatAddress(storage::CountryId()); };
std::string FormatAddress(storage::CountryId countryId) const;
};
struct RegionAddress